use of com.cburch.logisim.circuit.SubcircuitFactory in project logisim-evolution by reds-heig.
the class Netlist method WarningTraceForGatedClock.
private void WarningTraceForGatedClock(ConnectionPoint Source, int index, ArrayList<Netlist> HierarchyNetlists, ArrayList<String> HierarchyNames, FPGAReport Reporter) {
Component comp = Source.GetComp();
if (comp.getFactory() instanceof Pin) {
if (HierarchyNames.isEmpty())
/* we cannot go up at toplevel, so leave */
return;
int idx = -1;
for (int i = 0; i < MyInputPorts.size(); i++) {
if (MyInputPorts.get(i).GetComponent().equals(comp))
idx = i;
}
if (idx < 0) {
Reporter.AddFatalError("BUG: Could not find port!\n ==> " + this.getClass().getName().replaceAll("\\.", "/") + ":" + Thread.currentThread().getStackTrace()[2].getLineNumber() + "\n");
return;
}
ConnectionPoint SubNet = HierarchyNetlists.get(HierarchyNetlists.size() - 2).GetNetlistConnectionForSubCircuitInput(HierarchyNames.get(HierarchyNames.size() - 1), idx, (byte) index);
if (SubNet == null) {
Reporter.AddFatalError("BUG: Could not find a sub-circuit connection in overlying hierarchy level!\n ==> " + this.getClass().getName().replaceAll("\\.", "/") + ":" + Thread.currentThread().getStackTrace()[2].getLineNumber() + "\n");
return;
}
if (SubNet.GetParrentNet() != null) {
ArrayList<String> NewHierarchyNames = new ArrayList<String>();
ArrayList<Netlist> NewHierarchyNetlists = new ArrayList<Netlist>();
NewHierarchyNames.addAll(HierarchyNames);
NewHierarchyNames.remove(NewHierarchyNames.size() - 1);
NewHierarchyNetlists.addAll(HierarchyNetlists);
NewHierarchyNetlists.remove(NewHierarchyNetlists.size() - 1);
Netlist SubNetList = HierarchyNetlists.get(HierarchyNetlists.size() - 2);
Net NewNet = SubNet.GetParrentNet();
Byte NewNetIndex = SubNet.GetParrentNetBitIndex();
Set<Wire> Segments = new HashSet<Wire>();
SourceInfo source = SubNetList.GetHiddenSource(NewNet, NewNetIndex, SubNetList.MyComplexSplitters, null, new HashSet<String>(), Segments, Reporter);
if (source == null) {
Reporter.AddFatalError("BUG: Unable to find source in sub-circuit!\n ==> " + this.getClass().getName().replaceAll("\\.", "/") + ":" + Thread.currentThread().getStackTrace()[2].getLineNumber() + "\n");
return;
}
ComponentFactory sfac = source.getSource().GetComp().getFactory();
if (sfac instanceof Pin || sfac instanceof SubcircuitFactory) {
SimpleDRCContainer warn = new SimpleDRCContainer(SubNetList.getCircuit(), Strings.get("NetList_GatedClockInt"), SimpleDRCContainer.LEVEL_NORMAL, SimpleDRCContainer.MARK_WIRE, true);
warn.AddMarkComponents(Segments);
Reporter.AddWarning(warn);
SubNetList.WarningTraceForGatedClock(source.getSource(), source.getIndex(), NewHierarchyNetlists, NewHierarchyNames, Reporter);
} else {
SimpleDRCContainer warn = new SimpleDRCContainer(SubNetList.getCircuit(), Strings.get("NetList_GatedClockSource"), SimpleDRCContainer.LEVEL_NORMAL, SimpleDRCContainer.MARK_WIRE, true);
warn.AddMarkComponents(Segments);
Reporter.AddWarning(warn);
}
}
}
if (comp.getFactory() instanceof SubcircuitFactory) {
/* TODO */
SubcircuitFactory sub = (SubcircuitFactory) comp.getFactory();
if (Source.getChildsPortIndex() < 0) {
Reporter.AddFatalError("BUG: Subcircuit port is not annotated!\n ==> " + this.getClass().getName().replaceAll("\\.", "/") + ":" + Thread.currentThread().getStackTrace()[2].getLineNumber() + "\n");
return;
}
NetlistComponent OutputPort = sub.getSubcircuit().getNetList().GetOutputPin(Source.getChildsPortIndex());
if (OutputPort == null) {
Reporter.AddFatalError("BUG: Unable to find Subcircuit output port!\n ==> " + this.getClass().getName().replaceAll("\\.", "/") + ":" + Thread.currentThread().getStackTrace()[2].getLineNumber() + "\n");
return;
}
Net ConnectedNet = Source.GetParrentNet();
/* Find the correct subcircuit */
NetlistComponent SubCirc = null;
for (NetlistComponent subc : MySubCircuits) {
if (subc.GetComponent().equals(Source.GetComp()))
SubCirc = subc;
}
if (SubCirc == null) {
Reporter.AddFatalError("BUG: Unable to find Subcircuit!\n ==> " + this.getClass().getName().replaceAll("\\.", "/") + ":" + Thread.currentThread().getStackTrace()[2].getLineNumber() + "\n");
return;
}
byte BitIndex = SubCirc.GetConnectionBitIndex(ConnectedNet, (byte) index);
if (BitIndex < 0) {
Reporter.AddFatalError("BUG: Unable to find the bit index of a Subcircuit output port!\n ==> " + this.getClass().getName().replaceAll("\\.", "/") + ":" + Thread.currentThread().getStackTrace()[2].getLineNumber() + "\n");
return;
}
ConnectionPoint SubNet = OutputPort.getEnd(0).GetConnection(BitIndex);
if (SubNet.GetParrentNet() != null) {
/* we have a connected pin */
Netlist SubNetList = sub.getSubcircuit().getNetList();
ArrayList<String> NewHierarchyNames = new ArrayList<String>();
ArrayList<Netlist> NewHierarchyNetlists = new ArrayList<Netlist>();
NewHierarchyNames.addAll(HierarchyNames);
NewHierarchyNames.add(CorrectLabel.getCorrectLabel(SubCirc.GetComponent().getAttributeSet().getValue(StdAttr.LABEL)));
NewHierarchyNetlists.addAll(HierarchyNetlists);
NewHierarchyNetlists.add(SubNetList);
Net NewNet = SubNet.GetParrentNet();
Byte NewNetIndex = SubNet.GetParrentNetBitIndex();
Set<Wire> Segments = new HashSet<Wire>();
SourceInfo source = SubNetList.GetHiddenSource(NewNet, NewNetIndex, SubNetList.MyComplexSplitters, null, new HashSet<String>(), Segments, Reporter);
if (source == null) {
Reporter.AddFatalError("BUG: Unable to find source in sub-circuit!\n ==> " + this.getClass().getName().replaceAll("\\.", "/") + ":" + Thread.currentThread().getStackTrace()[2].getLineNumber() + "\n");
return;
}
ComponentFactory sfac = source.getSource().GetComp().getFactory();
if (sfac instanceof Pin || sfac instanceof SubcircuitFactory) {
SimpleDRCContainer warn = new SimpleDRCContainer(SubNetList.getCircuit(), Strings.get("NetList_GatedClockInt"), SimpleDRCContainer.LEVEL_NORMAL, SimpleDRCContainer.MARK_WIRE, true);
warn.AddMarkComponents(Segments);
Reporter.AddWarning(warn);
SubNetList.WarningTraceForGatedClock(source.getSource(), source.getIndex(), NewHierarchyNetlists, NewHierarchyNames, Reporter);
} else {
SimpleDRCContainer warn = new SimpleDRCContainer(SubNetList.getCircuit(), Strings.get("NetList_GatedClockSource"), SimpleDRCContainer.LEVEL_NORMAL, SimpleDRCContainer.MARK_WIRE, true);
warn.AddMarkComponents(Segments);
Reporter.AddWarning(warn);
}
}
}
}
use of com.cburch.logisim.circuit.SubcircuitFactory in project logisim-evolution by reds-heig.
the class Netlist method DesignRuleCheckResult.
public int DesignRuleCheckResult(FPGAReport Reporter, String HDLIdentifier, boolean IsTopLevel, ArrayList<String> Sheetnames) {
ArrayList<String> CompName = new ArrayList<String>();
Map<String, Component> Labels = new HashMap<String, Component>();
ArrayList<SimpleDRCContainer> drc = new ArrayList<SimpleDRCContainer>();
int CommonDRCStatus = DRC_PASSED;
/* First we go down the tree and get the DRC status of all sub-circuits */
for (Circuit circ : MySubCircuitMap.keySet()) {
CommonDRCStatus |= circ.getNetList().DesignRuleCheckResult(Reporter, HDLIdentifier, false, Sheetnames);
}
/* Check if we are okay */
if (DRCStatus == DRC_PASSED) {
return CommonDRCStatus;
} else {
/* There are changes, so we clean up the old information */
clear();
DRCStatus = DRC_PASSED;
/*
* we mark already passed, if an error
* occurs the status is changed
*/
}
/*
* Check for duplicated sheet names, this is bad as we will have
* multiple "different" components with the same name
*/
if (MyCircuit.getName().isEmpty()) {
/*
* in the current implementation of logisim this should never
* happen, but we leave it in
*/
Reporter.AddFatalError("Found a sheet in your design with an empty name. This is not allowed, please specify a name!");
DRCStatus |= DRC_ERROR;
}
if (Sheetnames.contains(MyCircuit.getName())) {
/*
* in the current implementation of logisim this should never
* happen, but we leave it in
*/
Reporter.AddFatalError("Found more than one sheet in your design with the name :\"" + MyCircuit.getName() + "\". This is not allowed, please make sure that all sheets have a unique name!");
DRCStatus |= DRC_ERROR;
} else {
Sheetnames.add(MyCircuit.getName());
}
/* Preparing stage */
for (Component comp : MyCircuit.getNonWires()) {
String ComponentName = comp.getFactory().getHDLName(comp.getAttributeSet());
if (!CompName.contains(ComponentName)) {
CompName.add(ComponentName);
}
}
drc.clear();
drc.add(new SimpleDRCContainer(MyCircuit, Strings.get("HDL_noLabel"), SimpleDRCContainer.LEVEL_FATAL, SimpleDRCContainer.MARK_INSTANCE));
drc.add(new SimpleDRCContainer(MyCircuit, Strings.get("HDL_CompNameIsLabel"), SimpleDRCContainer.LEVEL_FATAL, SimpleDRCContainer.MARK_INSTANCE | SimpleDRCContainer.MARK_LABEL));
drc.add(new SimpleDRCContainer(MyCircuit, Strings.get("HDL_LabelInvalid"), SimpleDRCContainer.LEVEL_FATAL, SimpleDRCContainer.MARK_INSTANCE | SimpleDRCContainer.MARK_LABEL));
drc.add(new SimpleDRCContainer(MyCircuit, Strings.get("HDL_DuplicatedLabels"), SimpleDRCContainer.LEVEL_FATAL, SimpleDRCContainer.MARK_INSTANCE | SimpleDRCContainer.MARK_LABEL));
drc.add(new SimpleDRCContainer(MyCircuit, Strings.get("HDL_Tristate"), SimpleDRCContainer.LEVEL_FATAL, SimpleDRCContainer.MARK_INSTANCE));
drc.add(new SimpleDRCContainer(MyCircuit, Strings.get("HDL_unsupported"), SimpleDRCContainer.LEVEL_FATAL, SimpleDRCContainer.MARK_INSTANCE));
for (Component comp : MyCircuit.getNonWires()) {
/*
* Here we check if the components are supported for the HDL
* generation
*/
if (!comp.getFactory().HDLSupportedComponent(HDLIdentifier, comp.getAttributeSet())) {
drc.get(5).AddMarkComponent(comp);
DRCStatus |= DRC_ERROR;
}
/*
* we check that all components that require a non zero label
* (annotation) have a label set
*/
if (comp.getFactory().RequiresNonZeroLabel()) {
String Label = CorrectLabel.getCorrectLabel(comp.getAttributeSet().getValue(StdAttr.LABEL).toString()).toUpperCase();
String ComponentName = comp.getFactory().getHDLName(comp.getAttributeSet());
if (Label.isEmpty()) {
drc.get(0).AddMarkComponent(comp);
DRCStatus |= ANNOTATE_REQUIRED;
} else {
if (CompName.contains(Label)) {
drc.get(1).AddMarkComponent(comp);
DRCStatus |= DRC_ERROR;
}
if (!CorrectLabel.IsCorrectLabel(Label, HDLIdentifier)) {
/* this should not happen anymore */
drc.get(2).AddMarkComponent(comp);
DRCStatus |= DRC_ERROR;
}
if (Labels.containsKey(Label)) {
drc.get(3).AddMarkComponent(comp);
drc.get(3).AddMarkComponent(Labels.get(Label));
DRCStatus |= DRC_ERROR;
} else {
Labels.put(Label, comp);
}
}
if (comp.getFactory() instanceof SubcircuitFactory) {
/* Special care has to be taken for sub-circuits */
if (Label.equals(ComponentName.toUpperCase())) {
drc.get(1).AddMarkComponent(comp);
DRCStatus |= DRC_ERROR;
}
if (!CorrectLabel.IsCorrectLabel(comp.getFactory().getName(), HDLIdentifier, "Found that the component \"" + comp.getFactory().getName() + "\" in circuit \"" + MyCircuit.getName(), Reporter)) {
DRCStatus |= DRC_ERROR;
}
SubcircuitFactory sub = (SubcircuitFactory) comp.getFactory();
LocalNrOfInportBubles = LocalNrOfInportBubles + sub.getSubcircuit().getNetList().NumberOfInputBubbles();
LocalNrOfOutportBubles = LocalNrOfOutportBubles + sub.getSubcircuit().getNetList().NumberOfOutputBubbles();
LocalNrOfInOutBubles = LocalNrOfInOutBubles + sub.getSubcircuit().getNetList().NumberOfInOutBubbles();
}
}
/* Now we check that no tri-state are present */
if (comp.getFactory().HasThreeStateDrivers(comp.getAttributeSet())) {
drc.get(4).AddMarkComponent(comp);
DRCStatus |= DRC_ERROR;
}
}
for (int i = 0; i < drc.size(); i++) if (drc.get(i).DRCInfoPresent())
Reporter.AddError(drc.get(i));
drc.clear();
/* Here we have to quit as the netlist generation needs a clean tree */
if ((DRCStatus | CommonDRCStatus) != DRC_PASSED) {
return DRCStatus | CommonDRCStatus;
}
/*
* Okay we now know for sure that all elements are supported, lets build
* the net list
*/
Reporter.AddInfo("Building netlist for sheet \"" + MyCircuit.getName() + "\"");
if (!this.GenerateNetlist(Reporter, HDLIdentifier)) {
this.clear();
DRCStatus = DRC_ERROR;
/*
* here we have to quit, as all the following steps depend on a
* proper netlist
*/
return DRCStatus | CommonDRCStatus;
}
if (NetlistHasShortCircuits(Reporter)) {
clear();
DRCStatus = DRC_ERROR;
return DRCStatus | CommonDRCStatus;
}
/* Check for connections without a source */
NetlistHasSinksWithoutSource(Reporter);
/* Check for unconnected input pins on components and generate warnings */
for (NetlistComponent comp : MyComponents) {
boolean openInputs = false;
for (int j = 0; j < comp.NrOfEnds(); j++) {
if (comp.EndIsInput(j) && !comp.EndIsConnected(j))
openInputs = true;
}
if (openInputs) {
SimpleDRCContainer warn = new SimpleDRCContainer(MyCircuit, Strings.get("NetList_UnconnectedInputs"), SimpleDRCContainer.LEVEL_NORMAL, SimpleDRCContainer.MARK_INSTANCE);
warn.AddMarkComponent(comp.GetComponent());
Reporter.AddWarning(warn);
}
}
/* Check for unconnected input pins on subcircuits and generate warnings */
for (NetlistComponent comp : MySubCircuits) {
boolean openInputs = false;
for (int j = 0; j < comp.NrOfEnds(); j++) {
if (comp.EndIsInput(j) && !comp.EndIsConnected(j))
openInputs = true;
}
if (openInputs) {
SimpleDRCContainer warn = new SimpleDRCContainer(MyCircuit, Strings.get("NetList_UnconnectedInputs"), SimpleDRCContainer.LEVEL_SEVERE, SimpleDRCContainer.MARK_INSTANCE);
warn.AddMarkComponent(comp.GetComponent());
Reporter.AddWarning(warn);
}
}
/* Only if we are on the top-level we are going to build the clock-tree */
if (IsTopLevel) {
if (!DetectClockTree(Reporter)) {
DRCStatus = DRC_ERROR;
return DRCStatus | CommonDRCStatus;
}
ConstructHierarchyTree(null, new ArrayList<String>(), new Integer(0), new Integer(0), new Integer(0));
int ports = NumberOfInputPorts() + NumberOfOutputPorts() + LocalNrOfInportBubles + LocalNrOfOutportBubles + LocalNrOfInOutBubles;
if (ports == 0) {
Reporter.AddFatalError("Toplevel \"" + MyCircuit.getName() + "\" has no input(s) and/or no output(s)!");
DRCStatus = DRC_ERROR;
return DRCStatus | CommonDRCStatus;
}
/* Check for gated clocks */
if (!DetectGatedClocks(Reporter)) {
DRCStatus = DRC_ERROR;
return DRCStatus | CommonDRCStatus;
}
}
Reporter.AddInfo("Circuit \"" + MyCircuit.getName() + "\" has " + NumberOfNets() + " nets and " + NumberOfBusses() + " busses.");
Reporter.AddInfo("Circuit \"" + MyCircuit.getName() + "\" passed DRC check");
DRCStatus = DRC_PASSED;
return DRCStatus | CommonDRCStatus;
}
use of com.cburch.logisim.circuit.SubcircuitFactory in project logisim-evolution by reds-heig.
the class Netlist method EnumerateGlobalBubbleTree.
/* Here all private handles are defined */
private void EnumerateGlobalBubbleTree(ArrayList<String> HierarchyName, int StartInputID, int StartOutputID, int StartInOutID) {
for (NetlistComponent comp : MySubCircuits) {
SubcircuitFactory sub = (SubcircuitFactory) comp.GetComponent().getFactory();
ArrayList<String> MyHierarchyName = new ArrayList<String>();
MyHierarchyName.addAll(HierarchyName);
MyHierarchyName.add(CorrectLabel.getCorrectLabel(comp.GetComponent().getAttributeSet().getValue(StdAttr.LABEL).toString()));
sub.getSubcircuit().getNetList().EnumerateGlobalBubbleTree(MyHierarchyName, StartInputID + comp.GetLocalBubbleInputStartId(), StartOutputID + comp.GetLocalBubbleOutputStartId(), StartInOutID + comp.GetLocalBubbleInOutStartId());
}
for (NetlistComponent comp : MyComponents) {
if (comp.GetIOInformationContainer() != null) {
ArrayList<String> MyHierarchyName = new ArrayList<String>();
MyHierarchyName.addAll(HierarchyName);
MyHierarchyName.add(CorrectLabel.getCorrectLabel(comp.GetComponent().getAttributeSet().getValue(StdAttr.LABEL).toString()));
int subInputBubbles = comp.GetIOInformationContainer().GetNrOfInports();
int subInOutBubbles = comp.GetIOInformationContainer().GetNrOfInOutports();
int subOutputBubbles = comp.GetIOInformationContainer().GetNrOfOutports();
comp.AddGlobalBubbleID(MyHierarchyName, StartInputID + comp.GetLocalBubbleInputStartId(), subInputBubbles, StartOutputID + comp.GetLocalBubbleOutputStartId(), subOutputBubbles, StartInOutID, subInOutBubbles);
}
}
}
use of com.cburch.logisim.circuit.SubcircuitFactory in project logisim-evolution by reds-heig.
the class Netlist method TraceClockNet.
public boolean TraceClockNet(Net ClockNet, byte ClockNetBitIndex, int ClockSourceId, ArrayList<String> HierarchyNames, ArrayList<Netlist> HierarchyNetlists, FPGAReport Reporter) {
/* first pass, we check if the clock net goes down the hierarchy */
for (NetlistComponent SubCirc : MySubCircuits) {
SubcircuitFactory sub = (SubcircuitFactory) SubCirc.GetComponent().getFactory();
for (ConnectionPoint SolderPoint : SubCirc.GetConnections(ClockNet, ClockNetBitIndex, false)) {
if (SolderPoint.getChildsPortIndex() < 0) {
Reporter.AddFatalError("BUG: Subcircuit port is not annotated!\n ==> " + this.getClass().getName().replaceAll("\\.", "/") + ":" + Thread.currentThread().getStackTrace()[2].getLineNumber() + "\n");
return false;
}
NetlistComponent InputPort = sub.getSubcircuit().getNetList().GetInputPin(SolderPoint.getChildsPortIndex());
if (InputPort == null) {
Reporter.AddFatalError("BUG: Unable to find Subcircuit input port!\n ==> " + this.getClass().getName().replaceAll("\\.", "/") + ":" + Thread.currentThread().getStackTrace()[2].getLineNumber() + "\n");
return false;
}
byte BitIndex = SubCirc.GetConnectionBitIndex(ClockNet, ClockNetBitIndex);
if (BitIndex < 0) {
Reporter.AddFatalError("BUG: Unable to find the bit index of a Subcircuit input port!\n ==> " + this.getClass().getName().replaceAll("\\.", "/") + ":" + Thread.currentThread().getStackTrace()[2].getLineNumber() + "\n");
return false;
}
ConnectionPoint SubClockNet = InputPort.getEnd(0).GetConnection(BitIndex);
if (SubClockNet.GetParrentNet() != null) {
/* we have a connected pin */
ArrayList<String> NewHierarchyNames = new ArrayList<String>();
ArrayList<Netlist> NewHierarchyNetlists = new ArrayList<Netlist>();
NewHierarchyNames.addAll(HierarchyNames);
NewHierarchyNames.add(CorrectLabel.getCorrectLabel(SubCirc.GetComponent().getAttributeSet().getValue(StdAttr.LABEL)));
NewHierarchyNetlists.addAll(HierarchyNetlists);
NewHierarchyNetlists.add(sub.getSubcircuit().getNetList());
sub.getSubcircuit().getNetList().MarkClockNet(NewHierarchyNames, ClockSourceId, SubClockNet);
if (!sub.getSubcircuit().getNetList().TraceClockNet(SubClockNet.GetParrentNet(), SubClockNet.GetParrentNetBitIndex(), ClockSourceId, NewHierarchyNames, NewHierarchyNetlists, Reporter)) {
return false;
}
}
}
}
/* second pass, we check if the clock net goes up the hierarchy */
if (!HierarchyNames.isEmpty()) {
for (NetlistComponent OutputPort : MyOutputPorts) {
if (!OutputPort.GetConnections(ClockNet, ClockNetBitIndex, false).isEmpty()) {
byte bitindex = OutputPort.GetConnectionBitIndex(ClockNet, ClockNetBitIndex);
ConnectionPoint SubClockNet = HierarchyNetlists.get(HierarchyNetlists.size() - 2).GetNetlistConnectionForSubCircuit(HierarchyNames.get(HierarchyNames.size() - 1), MyOutputPorts.indexOf(OutputPort), bitindex);
if (SubClockNet == null) {
Reporter.AddFatalError("BUG: Could not find a sub-circuit connection in overlying hierarchy level!\n ==> " + this.getClass().getName().replaceAll("\\.", "/") + ":" + Thread.currentThread().getStackTrace()[2].getLineNumber() + "\n");
return false;
}
if (SubClockNet.GetParrentNet() == null) {
} else {
ArrayList<String> NewHierarchyNames = new ArrayList<String>();
ArrayList<Netlist> NewHierarchyNetlists = new ArrayList<Netlist>();
NewHierarchyNames.addAll(HierarchyNames);
NewHierarchyNames.remove(NewHierarchyNames.size() - 1);
NewHierarchyNetlists.addAll(HierarchyNetlists);
NewHierarchyNetlists.remove(NewHierarchyNetlists.size() - 1);
HierarchyNetlists.get(HierarchyNetlists.size() - 2).MarkClockNet(NewHierarchyNames, ClockSourceId, SubClockNet);
if (!HierarchyNetlists.get(HierarchyNetlists.size() - 2).TraceClockNet(SubClockNet.GetParrentNet(), SubClockNet.GetParrentNetBitIndex(), ClockSourceId, NewHierarchyNames, NewHierarchyNetlists, Reporter)) {
return false;
}
}
}
}
}
return true;
}
use of com.cburch.logisim.circuit.SubcircuitFactory in project logisim-evolution by reds-heig.
the class Netlist method GenerateNetlist.
private boolean GenerateNetlist(FPGAReport Reporter, String HDLIdentifier) {
ArrayList<SimpleDRCContainer> drc = new ArrayList<SimpleDRCContainer>();
boolean errors = false;
GridBagConstraints gbc = new GridBagConstraints();
JFrame panel = new JFrame("Netlist: " + MyCircuit.getName());
panel.setResizable(false);
panel.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
GridBagLayout thisLayout = new GridBagLayout();
panel.setLayout(thisLayout);
JLabel LocText = new JLabel("Generating Netlist for Circuit: " + MyCircuit.getName());
gbc.gridx = 0;
gbc.gridy = 0;
gbc.fill = GridBagConstraints.HORIZONTAL;
panel.add(LocText, gbc);
JProgressBar progres = new JProgressBar(0, 7);
progres.setValue(0);
progres.setStringPainted(true);
gbc.gridx = 0;
gbc.gridy = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
panel.add(progres, gbc);
panel.pack();
panel.setLocation(Projects.getCenteredLoc(panel.getWidth(), panel.getHeight()));
panel.setVisible(true);
CircuitName = MyCircuit.getName();
wires.clear();
wires.addAll(MyCircuit.getWires());
/*
* FIRST PASS: In this pass we take all wire segments and see if they
* are connected to other segments. If they are connected we build a
* net.
*/
while (wires.size() != 0) {
Net NewNet = new Net();
GetNet(null, NewNet);
if (!NewNet.isEmpty()) {
MyNets.add(NewNet);
}
}
/*
* Here we start to detect direct input-output component connections,
* read we detect "hidden" nets
*/
Set<Component> components = MyCircuit.getNonWires();
/* we Start with the creation of an outputs list */
Set<Location> OutputsList = new HashSet<Location>();
Set<Location> InputsList = new HashSet<Location>();
Set<Component> TunnelList = new HashSet<Component>();
MyComplexSplitters.clear();
drc.clear();
drc.add(new SimpleDRCContainer(MyCircuit, Strings.get("NetList_IOError"), SimpleDRCContainer.LEVEL_FATAL, SimpleDRCContainer.MARK_INSTANCE));
drc.add(new SimpleDRCContainer(MyCircuit, Strings.get("NetList_BitwidthError"), SimpleDRCContainer.LEVEL_FATAL, SimpleDRCContainer.MARK_WIRE));
for (Component com : components) {
/*
* We do not process the splitter and tunnel, they are processed
* later on
*/
boolean Ignore = false;
/* In this case, the probe should not be synthetised:
* We could set the Probe as non-HDL element. But If we set the Probe
* as non HDL element, logisim will not allow user to download the design.
*
* In some case we need to use Logisim Simulation before running the design on the hardware.
* During simulation, probes are very helpful to see signals values. And when simulation is ok,
* the user does not want to delete all probes.
* Thus, here we remove it form the netlist so it is transparent.
*/
if (com.getFactory() instanceof Probe) {
continue;
}
if (com.getFactory() instanceof SplitterFactory) {
MyComplexSplitters.add(com);
Ignore = true;
}
if (com.getFactory() instanceof Tunnel) {
TunnelList.add(com);
Ignore = true;
}
List<EndData> ends = com.getEnds();
for (EndData end : ends) {
if (!Ignore) {
if (end.isInput() && end.isOutput()) {
drc.get(0).AddMarkComponent(com);
}
if (end.isOutput()) {
OutputsList.add(end.getLocation());
} else {
InputsList.add(end.getLocation());
}
}
/* Here we are going to mark the bitwidths on the nets */
int width = end.getWidth().getWidth();
Location loc = end.getLocation();
for (Net ThisNet : MyNets) {
if (ThisNet.contains(loc)) {
if (!ThisNet.setWidth(width)) {
drc.get(1).AddMarkComponents(ThisNet.getWires());
}
}
}
}
}
for (int i = 0; i < drc.size(); i++) {
if (drc.get(i).DRCInfoPresent()) {
errors = true;
Reporter.AddError(drc.get(i));
}
}
if (errors) {
panel.dispose();
return false;
}
progres.setValue(1);
Rectangle ProgRect = progres.getBounds();
ProgRect.x = 0;
ProgRect.y = 0;
progres.paintImmediately(ProgRect);
/*
* Now we check if an input pin is connected to an output and in case of
* a Splitter if it is connected to either of them
*/
drc.add(new SimpleDRCContainer(MyCircuit, Strings.get("NetAdd_ComponentWidthMismatch"), SimpleDRCContainer.LEVEL_FATAL, SimpleDRCContainer.MARK_INSTANCE));
Map<Location, Integer> Points = new HashMap<Location, Integer>();
for (Component comp : components) {
for (EndData end : comp.getEnds()) {
Location loc = end.getLocation();
if (Points.containsKey(loc)) {
/* Found a connection already used */
boolean newNet = true;
for (Net net : MyNets) {
if (net.contains(loc))
newNet = false;
}
if (newNet) {
int BitWidth = Points.get(loc);
if (BitWidth == end.getWidth().getWidth()) {
MyNets.add(new Net(loc, BitWidth));
} else {
drc.get(0).AddMarkComponent(comp);
}
}
} else
Points.put(loc, end.getWidth().getWidth());
}
}
if (drc.get(0).DRCInfoPresent()) {
Reporter.AddError(drc.get(0));
panel.dispose();
return false;
}
progres.setValue(2);
ProgRect = progres.getBounds();
ProgRect.x = 0;
ProgRect.y = 0;
progres.paintImmediately(ProgRect);
/*
* Here we are going to process the tunnels and possible merging of the
* tunneled nets
*/
boolean TunnelsPresent = false;
for (Component com : TunnelList) {
List<EndData> ends = com.getEnds();
for (EndData end : ends) {
for (Net ThisNet : MyNets) {
if (ThisNet.contains(end.getLocation())) {
ThisNet.addTunnel(com.getAttributeSet().getValue(StdAttr.LABEL));
TunnelsPresent = true;
}
}
}
}
drc.clear();
drc.add(new SimpleDRCContainer(MyCircuit, Strings.get("NetMerge_BitWidthError"), SimpleDRCContainer.LEVEL_FATAL, SimpleDRCContainer.MARK_WIRE));
if (TunnelsPresent) {
Iterator<Net> NetIterator = MyNets.listIterator();
while (NetIterator.hasNext()) {
Net ThisNet = NetIterator.next();
if (ThisNet.HasTunnel() && (MyNets.indexOf(ThisNet) < (MyNets.size() - 1))) {
boolean merged = false;
Iterator<Net> SearchIterator = MyNets.listIterator(MyNets.indexOf(ThisNet) + 1);
while (SearchIterator.hasNext() && !merged) {
Net SearchNet = SearchIterator.next();
for (String name : ThisNet.TunnelNames()) {
if (SearchNet.ContainsTunnel(name) && !merged) {
merged = true;
if (!SearchNet.merge(ThisNet)) {
drc.get(0).AddMarkComponents(SearchNet.getWires());
drc.get(0).AddMarkComponents(ThisNet.getWires());
}
}
}
}
if (merged) {
NetIterator.remove();
}
}
}
}
if (drc.get(0).DRCInfoPresent()) {
Reporter.AddError(drc.get(0));
panel.dispose();
return false;
}
progres.setValue(3);
ProgRect = progres.getBounds();
ProgRect.x = 0;
ProgRect.y = 0;
progres.paintImmediately(ProgRect);
/* At this point all net segments are build. All tunnels have been removed. There is still the processing of
* the splitters and the determination of the direction of the nets.
*/
/* First we are going to check on duplicated splitters and remove them */
Iterator<Component> MySplitIterator = MyComplexSplitters.listIterator();
while (MySplitIterator.hasNext()) {
Component ThisSplitter = MySplitIterator.next();
if (MyComplexSplitters.indexOf(ThisSplitter) < (MyComplexSplitters.size() - 1)) {
boolean FoundDuplicate = false;
Iterator<Component> SearchIterator = MyComplexSplitters.listIterator(MyComplexSplitters.indexOf(ThisSplitter) + 1);
while (SearchIterator.hasNext() && !FoundDuplicate) {
Component SearchSplitter = SearchIterator.next();
if (SearchSplitter.getLocation().equals(ThisSplitter.getLocation())) {
FoundDuplicate = true;
for (int i = 0; i < SearchSplitter.getEnds().size(); i++) {
if (!SearchSplitter.getEnd(i).getLocation().equals(ThisSplitter.getEnd(i).getLocation()))
FoundDuplicate = false;
}
}
}
if (FoundDuplicate) {
SimpleDRCContainer warn = new SimpleDRCContainer(MyCircuit, Strings.get("NetList_duplicatedSplitter"), SimpleDRCContainer.LEVEL_SEVERE, SimpleDRCContainer.MARK_INSTANCE);
warn.AddMarkComponent(ThisSplitter);
Reporter.AddWarning(warn);
MySplitIterator.remove();
}
}
}
/* In this round we are going to detect the unconnected nets meaning those having a width of 0 and remove them */
drc.clear();
Iterator<Net> NetIterator = MyNets.listIterator();
drc.add(new SimpleDRCContainer(MyCircuit, Strings.get("NetList_emptynets"), SimpleDRCContainer.LEVEL_NORMAL, SimpleDRCContainer.MARK_WIRE));
while (NetIterator.hasNext()) {
Net wire = NetIterator.next();
if (wire.BitWidth() == 0) {
drc.get(0).AddMarkComponents(wire.getWires());
NetIterator.remove();
}
}
if (drc.get(0).DRCInfoPresent()) {
Reporter.AddWarning(drc.get(0));
}
MySplitIterator = MyComplexSplitters.iterator();
/* We also check quickly the splitters and remove the ones where input-bus is output-bus. We mark those who are not
* correctly connected and remove both versions from the set.
*/
drc.clear();
drc.add(new SimpleDRCContainer(MyCircuit, Strings.get("NetList_ShortCircuit"), SimpleDRCContainer.LEVEL_FATAL, SimpleDRCContainer.MARK_WIRE));
errors = false;
while (MySplitIterator.hasNext()) {
Component mySplitter = MySplitIterator.next();
int BusWidth = mySplitter.getEnd(0).getWidth().getWidth();
List<EndData> myEnds = mySplitter.getEnds();
int MaxFanoutWidth = 0;
int index = -1;
for (int i = 1; i < myEnds.size(); i++) {
int width = mySplitter.getEnd(i).getWidth().getWidth();
if (width > MaxFanoutWidth) {
MaxFanoutWidth = width;
index = i;
}
}
/* stupid situation first: the splitters bus connection is a single fanout */
if (BusWidth == MaxFanoutWidth) {
Net busnet = null;
Net connectedNet = null;
Location BusLoc = mySplitter.getEnd(0).getLocation();
Location ConnectedLoc = mySplitter.getEnd(index).getLocation();
boolean issueWarning = false;
/* here we search for the nets */
for (Net CurrentNet : MyNets) {
if (CurrentNet.contains(BusLoc)) {
if (busnet != null) {
Reporter.AddFatalError("BUG: Multiple bus nets found for a single splitter\n ==> " + this.getClass().getName().replaceAll("\\.", "/") + ":" + Thread.currentThread().getStackTrace()[2].getLineNumber() + "\n");
panel.dispose();
return false;
} else {
busnet = CurrentNet;
}
}
if (CurrentNet.contains(ConnectedLoc)) {
if (connectedNet != null) {
Reporter.AddFatalError("BUG: Multiple nets found for a single splitter split connection\n ==> " + this.getClass().getName().replaceAll("\\.", "/") + ":" + Thread.currentThread().getStackTrace()[2].getLineNumber() + "\n");
panel.dispose();
return false;
} else {
connectedNet = CurrentNet;
}
}
}
if (connectedNet != null) {
if (busnet != null) {
/* we can merge both nets */
if (!busnet.merge(connectedNet)) {
Reporter.AddFatalError("BUG: Splitter bus merge error\n ==> " + this.getClass().getName().replaceAll("\\.", "/") + ":" + Thread.currentThread().getStackTrace()[2].getLineNumber() + "\n");
panel.dispose();
return false;
} else {
MyNets.remove(MyNets.indexOf(connectedNet));
}
} else {
issueWarning = true;
}
} else {
issueWarning = true;
}
if (issueWarning) {
SimpleDRCContainer warn = new SimpleDRCContainer(MyCircuit, Strings.get("NetList_NoSplitterConnection"), SimpleDRCContainer.LEVEL_SEVERE, SimpleDRCContainer.MARK_INSTANCE);
warn.AddMarkComponent(mySplitter);
Reporter.AddWarning(warn);
}
MySplitIterator.remove();
/* Does not exist anymore */
}
}
progres.setValue(4);
ProgRect = progres.getBounds();
ProgRect.x = 0;
ProgRect.y = 0;
progres.paintImmediately(ProgRect);
/*
* Finally we have to process the splitters to determine the bus
* hierarchy (if any)
*/
/*
* In this round we only process the evident splitters and remove them
* from the list
*/
Iterator<Component> MySplitters = MyComplexSplitters.iterator();
while (MySplitters.hasNext()) {
Component com = MySplitters.next();
/*
* Currently by definition end(0) is the combined end of the
* splitter
*/
List<EndData> ends = com.getEnds();
EndData CombinedEnd = ends.get(0);
int RootNet = -1;
/* We search for the root net in the list of nets */
for (int i = 0; i < MyNets.size() && RootNet < 0; i++) {
if (MyNets.get(i).contains(CombinedEnd.getLocation())) {
RootNet = i;
}
}
if (RootNet < 0) {
Reporter.AddFatalError("BUG: Splitter without a bus connection\n ==> " + this.getClass().getName().replaceAll("\\.", "/") + ":" + Thread.currentThread().getStackTrace()[2].getLineNumber() + "\n");
this.clear();
panel.dispose();
return false;
}
/*
* Now we process all the other ends to find the child busses/nets
* of this root bus
*/
ArrayList<Integer> Connections = new ArrayList<Integer>();
for (int i = 1; i < ends.size(); i++) {
EndData ThisEnd = ends.get(i);
/* Find the connected net */
int ConnectedNet = -1;
for (int j = 0; j < MyNets.size() && ConnectedNet < 1; j++) {
if (MyNets.get(j).contains(ThisEnd.getLocation())) {
ConnectedNet = j;
}
}
Connections.add(ConnectedNet);
}
boolean unconnectedEnds = false;
for (int i = 1; i < ends.size(); i++) {
int ConnectedNet = Connections.get(i - 1);
if (ConnectedNet >= 0) {
/* There is a net connected to this splitter's end point */
if (!MyNets.get(ConnectedNet).setParent(MyNets.get(RootNet))) {
MyNets.get(ConnectedNet).ForceRootNet();
}
/* Here we have to process the inherited bits of the parent */
byte[] BusBitConnection = ((Splitter) com).GetEndpoints();
for (byte b = 0; b < BusBitConnection.length; b++) {
if (BusBitConnection[b] == i) {
MyNets.get(ConnectedNet).AddParrentBit(b);
}
}
} else {
unconnectedEnds = true;
}
}
if (unconnectedEnds) {
SimpleDRCContainer warn = new SimpleDRCContainer(MyCircuit, Strings.get("NetList_NoSplitterEndConnections"), SimpleDRCContainer.LEVEL_NORMAL, SimpleDRCContainer.MARK_INSTANCE);
warn.AddMarkComponent(com);
Reporter.AddWarning(warn);
}
}
progres.setValue(5);
ProgRect = progres.getBounds();
ProgRect.x = 0;
ProgRect.y = 0;
progres.paintImmediately(ProgRect);
/*
* Now the complete netlist is created, we have to check that each
* net/bus entry has only 1 source and 1 or more sinks. If there exist
* more than 1 source we have a short circuit! We keep track of the
* sources and sinks at the root nets/buses
*/
for (Net ThisNet : MyNets) {
if (ThisNet.IsRootNet()) {
ThisNet.InitializeSourceSinks();
}
}
for (Component comp : components) {
if (comp.getFactory() instanceof SubcircuitFactory) {
if (!ProcessSubcircuit(comp, Reporter)) {
this.clear();
panel.dispose();
return false;
}
} else if ((comp.getFactory() instanceof Pin) || (comp.getFactory().getIOInformation() != null) || (comp.getFactory().getHDLGenerator(HDLIdentifier, comp.getAttributeSet()) != null)) {
if (!ProcessNormalComponent(comp, Reporter)) {
this.clear();
panel.dispose();
return false;
}
}
}
progres.setValue(6);
ProgRect = progres.getBounds();
ProgRect.x = 0;
ProgRect.y = 0;
progres.paintImmediately(ProgRect);
/*
* Here we are going to process the complex splitters, note that in the
* previous handling of the splitters we marked all nets connected to a
* complex splitter with a forcerootnet annotation; we are going to
* cycle trough all these nets
*/
for (Net thisnet : MyNets) {
if (thisnet.IsForcedRootNet()) {
/* Cycle through all the bits of this net */
for (int bit = 0; bit < thisnet.BitWidth(); bit++) {
for (Component comp : MyComplexSplitters) {
/*
* Currently by definition end(0) is the combined end of
* the splitter
*/
List<EndData> ends = comp.getEnds();
EndData CombinedEnd = ends.get(0);
int ConnectedBus = -1;
/* We search for the root net in the list of nets */
for (int i = 0; i < MyNets.size() && ConnectedBus < 0; i++) {
if (MyNets.get(i).contains(CombinedEnd.getLocation())) {
ConnectedBus = i;
}
}
if (ConnectedBus < 0) {
/*
* This should never happen as we already checked in
* the first pass
*/
Reporter.AddFatalError("BUG: This is embarasing as this should never happen\n ==> " + this.getClass().getName().replaceAll("\\.", "/") + ":" + Thread.currentThread().getStackTrace()[2].getLineNumber() + "\n");
this.clear();
panel.dispose();
return false;
}
for (int endid = 1; endid < ends.size(); endid++) {
/*
* we iterate through all bits to see if the current
* net is connected to this splitter
*/
if (thisnet.contains(ends.get(endid).getLocation())) {
/*
* first we have to get the bitindices of the
* rootbus
*/
/*
* Here we have to process the inherited bits of
* the parent
*/
byte[] BusBitConnection = ((Splitter) comp).GetEndpoints();
ArrayList<Byte> IndexBits = new ArrayList<Byte>();
for (byte b = 0; b < BusBitConnection.length; b++) {
if (BusBitConnection[b] == endid) {
IndexBits.add(b);
}
}
byte ConnectedBusIndex = IndexBits.get(bit);
/* Figure out the rootbusid and rootbusindex */
Net Rootbus = MyNets.get(ConnectedBus);
while (!Rootbus.IsRootNet()) {
ConnectedBusIndex = Rootbus.getBit(ConnectedBusIndex);
Rootbus = Rootbus.getParent();
}
ConnectionPoint SolderPoint = new ConnectionPoint(comp);
SolderPoint.SetParrentNet(Rootbus, ConnectedBusIndex);
Boolean IsSink = true;
if (!thisnet.hasBitSource(bit)) {
if (HasHiddenSource(Rootbus, ConnectedBusIndex, MyComplexSplitters, comp, new HashSet<String>())) {
IsSink = false;
}
}
if (IsSink) {
thisnet.addSinkNet(bit, SolderPoint);
} else {
thisnet.addSourceNet(bit, SolderPoint);
}
}
}
}
}
}
}
progres.setValue(7);
ProgRect = progres.getBounds();
ProgRect.x = 0;
ProgRect.y = 0;
progres.paintImmediately(ProgRect);
panel.dispose();
/* So now we have all information we need! */
return true;
}
Aggregations