/*******************************************************************************
* 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.bfh.logisim.designrulecheck;
import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JProgressBar;
import org.hamcrest.core.IsInstanceOf;
import com.bfh.logisim.fpgagui.FPGAReport;
import com.bfh.logisim.hdlgenerator.AbstractHDLGeneratorFactory;
import com.cburch.logisim.circuit.Circuit;
import com.cburch.logisim.circuit.CircuitAttributes;
import com.cburch.logisim.circuit.CircuitEvent;
import com.cburch.logisim.circuit.CircuitListener;
import com.cburch.logisim.circuit.Splitter;
import com.cburch.logisim.circuit.SplitterFactory;
import com.cburch.logisim.circuit.SubcircuitFactory;
import com.cburch.logisim.circuit.Wire;
import com.cburch.logisim.comp.Component;
import com.cburch.logisim.comp.ComponentFactory;
import com.cburch.logisim.comp.EndData;
import com.cburch.logisim.data.AttributeSet;
import com.cburch.logisim.data.Location;
import com.cburch.logisim.instance.Instance;
import com.cburch.logisim.instance.InstanceComponent;
import com.cburch.logisim.instance.StdAttr;
import com.cburch.logisim.proj.Projects;
import com.cburch.logisim.std.io.DipSwitch;
import com.cburch.logisim.std.io.ReptarLocalBus;
import com.cburch.logisim.std.memory.Counter;
import com.cburch.logisim.std.memory.DFlipFlop;
import com.cburch.logisim.std.memory.JKFlipFlop;
import com.cburch.logisim.std.memory.Ram;
import com.cburch.logisim.std.memory.Random;
import com.cburch.logisim.std.memory.Register;
import com.cburch.logisim.std.memory.SRFlipFlop;
import com.cburch.logisim.std.memory.ShiftRegister;
import com.cburch.logisim.std.memory.TFlipFlop;
import com.cburch.logisim.std.wiring.Clock;
import com.cburch.logisim.std.wiring.Pin;
import com.cburch.logisim.std.wiring.Probe;
import com.cburch.logisim.std.wiring.Tunnel;
public class Netlist implements CircuitListener {
@Override
public void circuitChanged(CircuitEvent event) {
int ev = event.getAction();
if (event.getData() instanceof InstanceComponent) {
InstanceComponent inst = (InstanceComponent) event.getData();
if (event.getCircuit().equals(MyCircuit)) {
switch (ev) {
case CircuitEvent.ACTION_ADD:
DRCStatus = DRC_REQUIRED;
if (inst.getFactory() instanceof SubcircuitFactory) {
SubcircuitFactory fac = (SubcircuitFactory) inst
.getFactory();
Circuit sub = fac.getSubcircuit();
if (MySubCircuitMap.containsKey(sub)) {
MySubCircuitMap.put(sub,
MySubCircuitMap.get(sub) + 1);
} else {
MySubCircuitMap.put(sub, 1);
sub.addCircuitListener(this);
}
}
break;
case CircuitEvent.ACTION_REMOVE:
DRCStatus = DRC_REQUIRED;
if (inst.getFactory() instanceof SubcircuitFactory) {
SubcircuitFactory fac = (SubcircuitFactory) inst
.getFactory();
Circuit sub = fac.getSubcircuit();
if (MySubCircuitMap.containsKey(sub)) {
if (MySubCircuitMap.get(sub) == 1) {
MySubCircuitMap.remove(sub);
sub.removeCircuitListener(this);
} else {
MySubCircuitMap.put(sub,
MySubCircuitMap.get(sub) - 1);
}
}
}
break;
case CircuitEvent.ACTION_CHANGE:
case CircuitEvent.ACTION_CLEAR:
case CircuitEvent.ACTION_INVALIDATE:
DRCStatus = DRC_REQUIRED;
break;
}
} else {
if (inst.getFactory() instanceof Pin) {
DRCStatus = DRC_REQUIRED;
}
}
}
}
private class SourceInfo {
private ConnectionPoint source;
private byte index;
public SourceInfo(ConnectionPoint source,
byte index) {
this.source = source;
this.index = index;
}
public Integer getIndex() {
return (int) index;
}
public ConnectionPoint getSource() {
return source;
}
}
public class NetInfo {
private Net TheNet;
private byte BitIndex;
public NetInfo(Net ConcernedNet, byte Index) {
TheNet = ConcernedNet;
BitIndex = Index;
}
public Byte getIndex() {
return BitIndex;
}
public Net getNet() {
return TheNet;
}
}
private String CircuitName;
private ArrayList<Net> MyNets = new ArrayList<Net>();
private Map<Circuit, Integer> MySubCircuitMap = new HashMap<Circuit, Integer>();
private ArrayList<NetlistComponent> MySubCircuits = new ArrayList<NetlistComponent>();
private ArrayList<NetlistComponent> MyComponents = new ArrayList<NetlistComponent>();
private ArrayList<NetlistComponent> MyClockGenerators = new ArrayList<NetlistComponent>();
private ArrayList<NetlistComponent> MyInOutPorts = new ArrayList<NetlistComponent>();
private ArrayList<NetlistComponent> MyInputPorts = new ArrayList<NetlistComponent>();
private ArrayList<NetlistComponent> MyOutputPorts = new ArrayList<NetlistComponent>();
private ArrayList<Component> MyComplexSplitters = new ArrayList<Component>();
private Integer LocalNrOfInportBubles;
private Integer LocalNrOfOutportBubles;
private Integer LocalNrOfInOutBubles;
private ClockTreeFactory MyClockInformation = new ClockTreeFactory();
private Circuit MyCircuit;
private int DRCStatus;
private Set<Wire> wires = new HashSet<Wire>();
private ArrayList<String> CurrentHierarchyLevel;
public static final int DRC_REQUIRED = 4;
public static final int DRC_PASSED = 0;
public static final int ANNOTATE_REQUIRED = 1;
public static final int DRC_ERROR = 2;
public static final Color DRC_INSTANCE_MARK_COLOR = Color.RED;
public static final Color DRC_LABEL_MARK_COLOR = Color.MAGENTA;
public static final Color DRC_WIRE_MARK_COLOR = Color.RED;
public Netlist(Circuit ThisCircuit) {
MyCircuit = ThisCircuit;
this.clear();
}
public void cleanClockTree(ClockSourceContainer ClockSources) {
/* First pass, we cleanup all old information */
MyClockInformation.clean();
MyClockInformation.SetSourceContainer(ClockSources);
/* Second pass, we go down the hierarchy */
for (NetlistComponent sub : MySubCircuits) {
SubcircuitFactory SubFact = (SubcircuitFactory) sub.GetComponent()
.getFactory();
SubFact.getSubcircuit().getNetList().cleanClockTree(ClockSources);
}
}
public void clear() {
for (NetlistComponent subcirc : MySubCircuits) {
SubcircuitFactory SubFact = (SubcircuitFactory) subcirc.GetComponent().getFactory();
SubFact.getSubcircuit().getNetList().clear();
}
DRCStatus = DRC_REQUIRED;
MyNets.clear();
MySubCircuits.clear();
MyComponents.clear();
MyClockGenerators.clear();
MyInputPorts.clear();
MyInOutPorts.clear();
MyOutputPorts.clear();
MyComplexSplitters.clear();
LocalNrOfInportBubles = 0;
LocalNrOfOutportBubles = 0;
LocalNrOfInOutBubles = 0;
if (CurrentHierarchyLevel == null) {
CurrentHierarchyLevel = new ArrayList<String>();
} else {
CurrentHierarchyLevel.clear();
}
}
public String getName() {
if (MyCircuit!=null)
return MyCircuit.getName();
else
return "Unknown";
}
public void ConstructHierarchyTree(Set<String> ProcessedCircuits,
ArrayList<String> HierarchyName, Integer GlobalInputID,
Integer GlobalOutputID, Integer GlobalInOutID) {
if (ProcessedCircuits == null) {
ProcessedCircuits = new HashSet<String>();
}
/*
* The first step is to go down to the leaves and visit all involved
* sub-circuits to construct the local bubble information and form the
* Mappable components tree
*/
LocalNrOfInportBubles = 0;
LocalNrOfOutportBubles = 0;
LocalNrOfInOutBubles = 0;
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()));
boolean FirstTime = !ProcessedCircuits.contains(sub.getName()
.toString());
if (FirstTime) {
ProcessedCircuits.add(sub.getName());
sub.getSubcircuit()
.getNetList()
.ConstructHierarchyTree(ProcessedCircuits,
MyHierarchyName, GlobalInputID, GlobalOutputID,
GlobalInOutID);
}
int subInputBubbles = sub.getSubcircuit().getNetList()
.NumberOfInputBubbles();
int subInOutBubbles = sub.getSubcircuit().getNetList()
.NumberOfInOutBubbles();
int subOutputBubbles = sub.getSubcircuit().getNetList()
.NumberOfOutputBubbles();
comp.SetLocalBubbleID(LocalNrOfInportBubles, subInputBubbles,
LocalNrOfOutportBubles, subOutputBubbles,
LocalNrOfInOutBubles, subInOutBubbles);
LocalNrOfInportBubles += subInputBubbles;
LocalNrOfInOutBubles += subInOutBubbles;
LocalNrOfOutportBubles += subOutputBubbles;
comp.AddGlobalBubbleID(MyHierarchyName, GlobalInputID,
subInputBubbles, GlobalOutputID, subOutputBubbles,
GlobalInOutID, subInOutBubbles);
if (!FirstTime) {
sub.getSubcircuit()
.getNetList()
.EnumerateGlobalBubbleTree(MyHierarchyName,
GlobalInputID, GlobalOutputID, GlobalInOutID);
}
GlobalInputID += subInputBubbles;
GlobalInOutID += subInOutBubbles;
GlobalOutputID += subOutputBubbles;
}
/*
* Here we processed all sub-circuits of the local hierarchy level, now
* we have to process the IO components
*/
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();
if (comp.GetComponent().getFactory() instanceof DipSwitch) {
subInputBubbles = comp.GetComponent().getAttributeSet()
.getValue(DipSwitch.ATTR_SIZE);
}
int subInOutBubbles = comp.GetIOInformationContainer()
.GetNrOfInOutports();
int subOutputBubbles = comp.GetIOInformationContainer()
.GetNrOfOutports();
comp.SetLocalBubbleID(LocalNrOfInportBubles, subInputBubbles,
LocalNrOfOutportBubles, subOutputBubbles,
LocalNrOfInOutBubles, subInOutBubbles);
LocalNrOfInportBubles += subInputBubbles;
LocalNrOfInOutBubles += subInOutBubbles;
LocalNrOfOutportBubles += subOutputBubbles;
comp.AddGlobalBubbleID(MyHierarchyName, GlobalInputID,
subInputBubbles, GlobalOutputID, subOutputBubbles,
GlobalInOutID, subInOutBubbles);
GlobalInputID += subInputBubbles;
GlobalInOutID += subInOutBubbles;
GlobalOutputID += subOutputBubbles;
}
}
}
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;
}
private boolean DetectClockTree(FPGAReport Reporter) {
/*
* First pass, we remove all information of previously detected
* clock-trees
*/
ClockSourceContainer ClockSources = MyClockInformation
.GetSourceContainer();
cleanClockTree(ClockSources);
/* Second pass, we build the clock tree */
ArrayList<Netlist> HierarchyNetlists = new ArrayList<Netlist>();
HierarchyNetlists.add(this);
return MarkClockSourceComponents(new ArrayList<String>(),
HierarchyNetlists, ClockSources, Reporter);
}
/* 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);
}
}
}
private Net FindConnectedNet(Location loc) {
for (Net Current : MyNets) {
if (Current.contains(loc)) {
return Current;
}
}
return null;
}
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();
}
}
/*
* We are going to iterate through all components and their respective
* pins to see if they are connected to a net, and if yes if they
* present a source or sink. We omit the splitter and tunnel as we
* already processed those
*/
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;
}
public ArrayList<Component> GetAllClockSources() {
return MyClockInformation.GetSourceContainer().getSources();
}
public ArrayList<Net> GetAllNets() {
return MyNets;
}
public Circuit getCircuit() {
return MyCircuit;
}
public String getCircuitName() {
return CircuitName;
}
public int GetClockSourceId(ArrayList<String> HierarchyLevel, Net WhichNet,
Byte Bitid) {
return MyClockInformation.GetClockSourceId(HierarchyLevel, WhichNet,
Bitid);
}
public int GetClockSourceId(Component comp) {
return MyClockInformation.GetClockSourceId(comp);
}
public ArrayList<NetlistComponent> GetClockSources() {
return MyClockGenerators;
}
public ArrayList<String> GetCurrentHierarchyLevel() {
return CurrentHierarchyLevel;
}
public int GetEndIndex(NetlistComponent comp, String PinLabel,
boolean IsOutputPort) {
String label = CorrectLabel.getCorrectLabel(PinLabel);
SubcircuitFactory sub = (SubcircuitFactory) comp.GetComponent()
.getFactory();
for (int end = 0; end < comp.NrOfEnds(); end++) {
if (comp.getEnd(end).IsOutputEnd() == IsOutputPort) {
if (comp.getEnd(end).GetConnection((byte) 0)
.getChildsPortIndex() == sub.getSubcircuit()
.getNetList().GetPortInfo(label)) {
return end;
}
}
}
return -1;
}
private ArrayList<ConnectionPoint> GetHiddenSinkNets(Net thisNet,
Byte bitIndex, ArrayList<Component> SplitterList,
Component ActiveSplitter, Set<String> HandledNets,
Boolean isSourceNet) {
ArrayList<ConnectionPoint> result = new ArrayList<ConnectionPoint>();
/*
* to prevent deadlock situations we check if we already looked at this
* net
*/
String NetId = Integer.toString(MyNets.indexOf(thisNet)) + "-"
+ Byte.toString(bitIndex);
if (HandledNets.contains(NetId)) {
return result;
} else {
HandledNets.add(NetId);
}
if (thisNet.hasBitSinks(bitIndex) && !isSourceNet) {
ConnectionPoint SolderPoint = new ConnectionPoint(null);
SolderPoint.SetParrentNet(thisNet, bitIndex);
result.add(SolderPoint);
}
/* Check if we have a connection to another splitter */
for (Component currentSplitter : SplitterList) {
if (ActiveSplitter != null) {
if (currentSplitter.equals(ActiveSplitter)) {
continue;
}
}
List<EndData> ends = currentSplitter.getEnds();
for (byte end = 0; end < ends.size(); end++) {
if (thisNet.contains(ends.get(end).getLocation())) {
/* Here we have to process the inherited bits of the parent */
byte[] BusBitConnection = ((Splitter) currentSplitter)
.GetEndpoints();
if (end == 0) {
/* this is a main net, find the connected end */
Byte SplitterEnd = BusBitConnection[bitIndex];
/* Find the corresponding Net index */
Byte Netindex = 0;
for (int index = 0; index < bitIndex; index++) {
if (BusBitConnection[index] == SplitterEnd) {
Netindex++;
}
}
/* Find the connected Net */
Net SlaveNet = null;
for (Net thisnet : MyNets) {
if (thisnet.contains(ends.get(SplitterEnd)
.getLocation())) {
SlaveNet = thisnet;
}
}
if (SlaveNet != null) {
if (SlaveNet.IsRootNet()) {
/* Trace down the slavenet */
result.addAll(GetHiddenSinkNets(SlaveNet,
Netindex, SplitterList,
currentSplitter, HandledNets, false));
} else {
result.addAll(GetHiddenSinkNets(
SlaveNet.getParent(),
SlaveNet.getBit(Netindex),
SplitterList, currentSplitter,
HandledNets, false));
}
}
} else {
ArrayList<Byte> Rootindices = new ArrayList<Byte>();
for (byte b = 0; b < BusBitConnection.length; b++) {
if (BusBitConnection[b] == end) {
Rootindices.add(b);
}
}
Net RootNet = null;
for (Net thisnet : MyNets) {
if (thisnet.contains(currentSplitter.getEnd(0)
.getLocation())) {
RootNet = thisnet;
}
}
if (RootNet != null) {
if (RootNet.IsRootNet()) {
result.addAll(GetHiddenSinkNets(RootNet,
Rootindices.get(bitIndex),
SplitterList, currentSplitter,
HandledNets, false));
} else {
result.addAll(GetHiddenSinkNets(RootNet
.getParent(), RootNet
.getBit(Rootindices.get(bitIndex)),
SplitterList, currentSplitter,
HandledNets, false));
}
}
}
}
}
}
return result;
}
private ArrayList<ConnectionPoint> GetHiddenSinks(Net thisNet,
Byte bitIndex, ArrayList<Component> SplitterList,
Component ActiveSplitter, Set<String> HandledNets,
Boolean isSourceNet) {
ArrayList<ConnectionPoint> result = new ArrayList<ConnectionPoint>();
/*
* to prevent deadlock situations we check if we already looked at this
* net
*/
String NetId = Integer.toString(MyNets.indexOf(thisNet)) + "-"
+ Byte.toString(bitIndex);
if (HandledNets.contains(NetId)) {
return result;
} else {
HandledNets.add(NetId);
}
if (thisNet.hasBitSinks(bitIndex) && !isSourceNet) {
result.addAll(thisNet.GetBitSinks(bitIndex));
}
/* Check if we have a connection to another splitter */
for (Component currentSplitter : SplitterList) {
if (ActiveSplitter != null) {
if (currentSplitter.equals(ActiveSplitter)) {
continue;
}
}
List<EndData> ends = currentSplitter.getEnds();
for (byte end = 0; end < ends.size(); end++) {
if (thisNet.contains(ends.get(end).getLocation())) {
/* Here we have to process the inherited bits of the parent */
byte[] BusBitConnection = ((Splitter) currentSplitter)
.GetEndpoints();
if (end == 0) {
/* this is a main net, find the connected end */
Byte SplitterEnd = BusBitConnection[bitIndex];
/* Find the corresponding Net index */
Byte Netindex = 0;
for (int index = 0; index < bitIndex; index++) {
if (BusBitConnection[index] == SplitterEnd) {
Netindex++;
}
}
/* Find the connected Net */
Net SlaveNet = null;
for (Net thisnet : MyNets) {
if (thisnet.contains(ends.get(SplitterEnd)
.getLocation())) {
SlaveNet = thisnet;
}
}
if (SlaveNet != null) {
if (SlaveNet.IsRootNet()) {
/* Trace down the slavenet */
result.addAll(GetHiddenSinks(SlaveNet,
Netindex, SplitterList,
currentSplitter, HandledNets, false));
} else {
result.addAll(GetHiddenSinks(
SlaveNet.getParent(),
SlaveNet.getBit(Netindex),
SplitterList, currentSplitter,
HandledNets, false));
}
}
} else {
ArrayList<Byte> Rootindices = new ArrayList<Byte>();
for (byte b = 0; b < BusBitConnection.length; b++) {
if (BusBitConnection[b] == end) {
Rootindices.add(b);
}
}
Net RootNet = null;
for (Net thisnet : MyNets) {
if (thisnet.contains(currentSplitter.getEnd(0)
.getLocation())) {
RootNet = thisnet;
}
}
if (RootNet != null) {
if (RootNet.IsRootNet()) {
result.addAll(GetHiddenSinks(RootNet,
Rootindices.get(bitIndex),
SplitterList, currentSplitter,
HandledNets, false));
} else {
result.addAll(GetHiddenSinks(RootNet
.getParent(), RootNet
.getBit(Rootindices.get(bitIndex)),
SplitterList, currentSplitter,
HandledNets, false));
}
}
}
}
}
}
return result;
}
public NetlistComponent GetInOutPin(int index) {
if ((index < 0) || (index >= MyInOutPorts.size())) {
return null;
}
return MyInOutPorts.get(index);
}
public NetlistComponent GetInOutPort(int Index) {
if ((Index < 0) || (Index >= MyInOutPorts.size())) {
return null;
}
return MyInOutPorts.get(Index);
}
public NetlistComponent GetInputPin(int index) {
if ((index < 0) || (index >= MyInputPorts.size())) {
return null;
}
return MyInputPorts.get(index);
}
public NetlistComponent GetInputPort(int Index) {
if ((Index < 0) || (Index >= MyInputPorts.size())) {
return null;
}
return MyInputPorts.get(Index);
}
public Map<ArrayList<String>, NetlistComponent> GetMappableResources(
ArrayList<String> Hierarchy, boolean toplevel) {
Map<ArrayList<String>, NetlistComponent> Components = new HashMap<ArrayList<String>, NetlistComponent>();
/* First we search through my sub-circuits and add those IO components */
for (NetlistComponent comp : MySubCircuits) {
SubcircuitFactory sub = (SubcircuitFactory) comp.GetComponent()
.getFactory();
ArrayList<String> MyHierarchyName = new ArrayList<String>();
MyHierarchyName.addAll(Hierarchy);
MyHierarchyName.add(CorrectLabel.getCorrectLabel(comp
.GetComponent().getAttributeSet().getValue(StdAttr.LABEL)
.toString()));
Components.putAll(sub.getSubcircuit().getNetList()
.GetMappableResources(MyHierarchyName, false));
}
/* Now we search for all local IO components */
for (NetlistComponent comp : MyComponents) {
if (comp.GetIOInformationContainer() != null) {
ArrayList<String> MyHierarchyName = new ArrayList<String>();
MyHierarchyName.addAll(Hierarchy);
MyHierarchyName.add(CorrectLabel.getCorrectLabel(comp
.GetComponent().getAttributeSet()
.getValue(StdAttr.LABEL).toString()));
Components.put(MyHierarchyName, comp);
}
}
/* On the toplevel we have to add the pins */
if (toplevel) {
for (NetlistComponent comp : MyInputPorts) {
ArrayList<String> MyHierarchyName = new ArrayList<String>();
MyHierarchyName.addAll(Hierarchy);
MyHierarchyName.add(CorrectLabel.getCorrectLabel(comp
.GetComponent().getAttributeSet()
.getValue(StdAttr.LABEL).toString()));
Components.put(MyHierarchyName, comp);
}
for (NetlistComponent comp : MyInOutPorts) {
ArrayList<String> MyHierarchyName = new ArrayList<String>();
MyHierarchyName.addAll(Hierarchy);
MyHierarchyName.add(CorrectLabel.getCorrectLabel(comp
.GetComponent().getAttributeSet()
.getValue(StdAttr.LABEL).toString()));
Components.put(MyHierarchyName, comp);
}
for (NetlistComponent comp : MyOutputPorts) {
ArrayList<String> MyHierarchyName = new ArrayList<String>();
MyHierarchyName.addAll(Hierarchy);
MyHierarchyName.add(CorrectLabel.getCorrectLabel(comp
.GetComponent().getAttributeSet()
.getValue(StdAttr.LABEL).toString()));
Components.put(MyHierarchyName, comp);
}
}
return Components;
}
private void GetNet(Wire wire, Net ThisNet) {
Iterator<Wire> MyIterator = wires.iterator();
ArrayList<Wire> MatchedWires = new ArrayList<Wire>();
Wire CompWire = wire;
while (MyIterator.hasNext()) {
Wire ThisWire = MyIterator.next();
if (CompWire == null) {
CompWire = ThisWire;
ThisNet.add(ThisWire);
MyIterator.remove();
} else if (ThisWire.sharesEnd(CompWire)) {
MatchedWires.add(ThisWire);
ThisNet.add(ThisWire);
MyIterator.remove();
}
}
for (Wire matched : MatchedWires)
GetNet(matched, ThisNet);
MatchedWires.clear();
}
public Integer GetNetId(Net selectedNet) {
return MyNets.indexOf(selectedNet);
}
public ConnectionPoint GetNetlistConnectionForSubCircuit(String Label,
int PortIndex, byte bitindex) {
for (NetlistComponent search : MySubCircuits) {
String CircuitLabel = CorrectLabel.getCorrectLabel(search
.GetComponent().getAttributeSet().getValue(StdAttr.LABEL));
if (CircuitLabel.equals(Label)) {
/* Found the component, let's search the ends */
for (int i = 0; i < search.NrOfEnds(); i++) {
ConnectionEnd ThisEnd = search.getEnd(i);
if (ThisEnd.IsOutputEnd()
&& (bitindex < ThisEnd.NrOfBits())) {
if (ThisEnd.GetConnection(bitindex)
.getChildsPortIndex() == PortIndex) {
return ThisEnd.GetConnection(bitindex);
}
}
}
}
}
return null;
}
public ConnectionPoint GetNetlistConnectionForSubCircuitInput(String Label,
int PortIndex, byte bitindex) {
for (NetlistComponent search : MySubCircuits) {
String CircuitLabel = CorrectLabel.getCorrectLabel(search
.GetComponent().getAttributeSet().getValue(StdAttr.LABEL));
if (CircuitLabel.equals(Label)) {
/* Found the component, let's search the ends */
for (int i = 0; i < search.NrOfEnds(); i++) {
ConnectionEnd ThisEnd = search.getEnd(i);
if (!ThisEnd.IsOutputEnd()
&& (bitindex < ThisEnd.NrOfBits())) {
if (ThisEnd.GetConnection(bitindex)
.getChildsPortIndex() == PortIndex) {
return ThisEnd.GetConnection(bitindex);
}
}
}
}
}
return null;
}
public ArrayList<NetlistComponent> GetNormalComponents() {
return MyComponents;
}
public NetlistComponent GetOutputPin(int index) {
if ((index < 0) || (index >= MyOutputPorts.size())) {
return null;
}
return MyOutputPorts.get(index);
}
public int GetPortInfo(String Label) {
String Source = CorrectLabel.getCorrectLabel(Label);
for (NetlistComponent Inport : MyInputPorts) {
String Comp = CorrectLabel.getCorrectLabel(Inport.GetComponent()
.getAttributeSet().getValue(StdAttr.LABEL));
if (Comp.equals(Source)) {
int index = MyInputPorts.indexOf(Inport);
return index;
}
}
for (NetlistComponent InOutport : MyInOutPorts) {
String Comp = CorrectLabel.getCorrectLabel(InOutport.GetComponent()
.getAttributeSet().getValue(StdAttr.LABEL));
if (Comp.equals(Source)) {
int index = MyInOutPorts.indexOf(InOutport);
return index;
}
}
for (NetlistComponent Outport : MyOutputPorts) {
String Comp = CorrectLabel.getCorrectLabel(Outport.GetComponent()
.getAttributeSet().getValue(StdAttr.LABEL));
if (Comp.equals(Source)) {
int index = MyOutputPorts.indexOf(Outport);
return index;
}
}
return -1;
}
private Net GetRootNet(Net Child) {
if (Child == null) {
return null;
}
if (Child.IsRootNet()) {
return Child;
}
Net RootNet = Child.getParent();
while (!RootNet.IsRootNet()) {
RootNet = RootNet.getParent();
}
return RootNet;
}
private byte GetRootNetIndex(Net Child, byte BitIndex) {
if (Child == null) {
return -1;
}
if ((BitIndex < 0) || (BitIndex > Child.BitWidth())) {
return -1;
}
if (Child.IsRootNet()) {
return BitIndex;
}
Net RootNet = Child.getParent();
Byte RootIndex = Child.getBit(BitIndex);
while (!RootNet.IsRootNet()) {
RootIndex = RootNet.getBit(RootIndex);
RootNet = RootNet.getParent();
}
return RootIndex;
}
public Set<Splitter> getSplitters() {
/* This may be cause bugs due to dual splitter on same location situations */
Set<Splitter> SplitterList = new HashSet<Splitter>();
for (Component comp : MyCircuit.getNonWires()) {
if (comp.getFactory() instanceof SplitterFactory) {
SplitterList.add((Splitter) comp);
}
}
return SplitterList;
}
public ArrayList<NetlistComponent> GetSubCircuits() {
return MySubCircuits;
}
private SourceInfo GetHiddenSource(Net thisNet, Byte bitIndex,
List<Component> SplitterList, Component ActiveSplitter,
Set<String> HandledNets, Set<Wire> Segments, FPGAReport Reporter) {
/*
* to prevent deadlock situations we check if we already looked at this
* net
*/
String NetId = Integer.toString(MyNets.indexOf(thisNet)) + "-"
+ Byte.toString(bitIndex);
if (HandledNets.contains(NetId)) {
return null;
} else {
HandledNets.add(NetId);
Segments.addAll(thisNet.getWires());
}
if (thisNet.hasBitSource(bitIndex)) {
List<ConnectionPoint> sources = thisNet.GetBitSources(bitIndex);
if (sources.size()!= 1) {
Reporter.AddFatalError("BUG: Found multiple sources\n ==> "+
this.getClass().getName().replaceAll("\\.","/")+":"+Thread.currentThread().getStackTrace()[2].getLineNumber()+"\n");
return null;
}
return new SourceInfo(sources.get(0),bitIndex);
}
/* Check if we have a connection to another splitter */
for (Component currentSplitter : SplitterList) {
if (currentSplitter.equals(ActiveSplitter)) {
continue;
}
List<EndData> ends = currentSplitter.getEnds();
for (byte end = 0; end < ends.size(); end++) {
if (thisNet.contains(ends.get(end).getLocation())) {
/* Here we have to process the inherited bits of the parent */
byte[] BusBitConnection = ((Splitter) currentSplitter)
.GetEndpoints();
if (end == 0) {
/* this is a main net, find the connected end */
Byte SplitterEnd = BusBitConnection[bitIndex];
/* Find the corresponding Net index */
Byte Netindex = 0;
for (int index = 0; index < bitIndex; index++) {
if (BusBitConnection[index] == SplitterEnd) {
Netindex++;
}
}
/* Find the connected Net */
Net SlaveNet = null;
for (Net thisnet : MyNets) {
if (thisnet.contains(ends.get(SplitterEnd)
.getLocation())) {
SlaveNet = thisnet;
}
}
if (SlaveNet != null) {
if (SlaveNet.IsRootNet()) {
/* Trace down the slavenet */
SourceInfo ret = GetHiddenSource(SlaveNet, Netindex,
SplitterList, currentSplitter,
HandledNets,Segments,Reporter);
if (ret != null)
return ret;
} else {
SourceInfo ret = GetHiddenSource(SlaveNet.getParent(),
SlaveNet.getBit(Netindex),
SplitterList, currentSplitter,
HandledNets,Segments,Reporter);
if (ret != null)
return ret;
}
}
} else {
ArrayList<Byte> Rootindices = new ArrayList<Byte>();
for (byte b = 0; b < BusBitConnection.length; b++) {
if (BusBitConnection[b] == end) {
Rootindices.add(b);
}
}
Net RootNet = null;
for (Net thisnet : MyNets) {
if (thisnet.contains(currentSplitter.getEnd(0)
.getLocation())) {
RootNet = thisnet;
}
}
if (RootNet != null) {
if (RootNet.IsRootNet()) {
SourceInfo ret = GetHiddenSource(RootNet,
Rootindices.get(bitIndex),
SplitterList, currentSplitter,
HandledNets,Segments,Reporter);
if (ret != null)
return ret;
} else {
SourceInfo ret = GetHiddenSource(RootNet.getParent(),
RootNet.getBit(Rootindices
.get(bitIndex)), SplitterList,
currentSplitter, HandledNets,Segments,Reporter);
if (ret != null)
return ret;
}
}
}
}
}
}
return null;
}
private boolean HasHiddenSource(Net thisNet, Byte bitIndex,
List<Component> SplitterList, Component ActiveSplitter,
Set<String> HandledNets) {
/*
* to prevent deadlock situations we check if we already looked at this
* net
*/
String NetId = Integer.toString(MyNets.indexOf(thisNet)) + "-"
+ Byte.toString(bitIndex);
if (HandledNets.contains(NetId)) {
return false;
} else {
HandledNets.add(NetId);
}
if (thisNet.hasBitSource(bitIndex)) {
return true;
}
/* Check if we have a connection to another splitter */
for (Component currentSplitter : SplitterList) {
if (currentSplitter.equals(ActiveSplitter)) {
continue;
}
List<EndData> ends = currentSplitter.getEnds();
for (byte end = 0; end < ends.size(); end++) {
if (thisNet.contains(ends.get(end).getLocation())) {
/* Here we have to process the inherited bits of the parent */
byte[] BusBitConnection = ((Splitter) currentSplitter)
.GetEndpoints();
if (end == 0) {
/* this is a main net, find the connected end */
Byte SplitterEnd = BusBitConnection[bitIndex];
/* Find the corresponding Net index */
Byte Netindex = 0;
for (int index = 0; index < bitIndex; index++) {
if (BusBitConnection[index] == SplitterEnd) {
Netindex++;
}
}
/* Find the connected Net */
Net SlaveNet = null;
for (Net thisnet : MyNets) {
if (thisnet.contains(ends.get(SplitterEnd)
.getLocation())) {
SlaveNet = thisnet;
}
}
if (SlaveNet != null) {
if (SlaveNet.IsRootNet()) {
/* Trace down the slavenet */
if (HasHiddenSource(SlaveNet, Netindex,
SplitterList, currentSplitter,
HandledNets)) {
return true;
}
} else {
if (HasHiddenSource(SlaveNet.getParent(),
SlaveNet.getBit(Netindex),
SplitterList, currentSplitter,
HandledNets)) {
return true;
}
}
}
} else {
ArrayList<Byte> Rootindices = new ArrayList<Byte>();
for (byte b = 0; b < BusBitConnection.length; b++) {
if (BusBitConnection[b] == end) {
Rootindices.add(b);
}
}
Net RootNet = null;
for (Net thisnet : MyNets) {
if (thisnet.contains(currentSplitter.getEnd(0)
.getLocation())) {
RootNet = thisnet;
}
}
if (RootNet != null) {
if (RootNet.IsRootNet()) {
if (HasHiddenSource(RootNet,
Rootindices.get(bitIndex),
SplitterList, currentSplitter,
HandledNets)) {
return true;
}
} else {
if (HasHiddenSource(RootNet.getParent(),
RootNet.getBit(Rootindices
.get(bitIndex)), SplitterList,
currentSplitter, HandledNets)) {
return true;
}
}
}
}
}
}
}
return false;
}
public boolean IsContinuesBus(NetlistComponent comp, int EndIndex) {
boolean ContinuesBus = true;
if ((EndIndex < 0) || (EndIndex >= comp.NrOfEnds())) {
return true;
}
ConnectionEnd ConnectionInformation = comp.getEnd(EndIndex);
int NrOfBits = ConnectionInformation.NrOfBits();
if (NrOfBits == 1) {
return true;
}
Net ConnectedNet = ConnectionInformation.GetConnection((byte) 0)
.GetParrentNet();
byte ConnectedNetIndex = ConnectionInformation.GetConnection((byte) 0)
.GetParrentNetBitIndex();
for (int i = 1; (i < NrOfBits) && ContinuesBus; i++) {
if (ConnectedNet != ConnectionInformation.GetConnection((byte) i)
.GetParrentNet()) {
/* This bit is connected to another bus */
ContinuesBus = false;
}
if ((ConnectedNetIndex + 1) != ConnectionInformation.GetConnection(
(byte) i).GetParrentNetBitIndex()) {
/* Connected to a none incremental position of the bus */
ContinuesBus = false;
} else {
ConnectedNetIndex++;
}
}
return ContinuesBus;
}
public boolean IsValid() {
return DRCStatus == DRC_PASSED;
}
public void MarkClockNet(ArrayList<String> HierarchyNames,
int clocksourceid, ConnectionPoint connection) {
MyClockInformation.AddClockNet(HierarchyNames, clocksourceid,
connection);
}
public boolean MarkClockSourceComponents(ArrayList<String> HierarchyNames,
ArrayList<Netlist> HierarchyNetlists,
ClockSourceContainer ClockSources, FPGAReport Reporter) {
/* First pass: we go down the hierarchy till the leaves */
for (NetlistComponent sub : MySubCircuits) {
ArrayList<String> NewHierarchyNames = new ArrayList<String>();
ArrayList<Netlist> NewHierarchyNetlists = new ArrayList<Netlist>();
SubcircuitFactory SubFact = (SubcircuitFactory) sub.GetComponent()
.getFactory();
NewHierarchyNames.addAll(HierarchyNames);
NewHierarchyNames.add(CorrectLabel.getCorrectLabel(sub
.GetComponent().getAttributeSet().getValue(StdAttr.LABEL)));
NewHierarchyNetlists.addAll(HierarchyNetlists);
NewHierarchyNetlists.add(SubFact.getSubcircuit().getNetList());
if (!SubFact
.getSubcircuit()
.getNetList()
.MarkClockSourceComponents(NewHierarchyNames,
NewHierarchyNetlists, ClockSources, Reporter)) {
return false;
}
}
/*
* We see if some components require the Global fast FPGA
* clock
*/
for (Component comp : MyCircuit.getNonWires()) {
if (comp.getFactory().RequiresGlobalClock()) {
ClockSources.SetGloblaClockRequirement();
}
}
/* Second pass: We mark all clock sources */
for (NetlistComponent ClockSource : MyClockGenerators) {
if (ClockSource.NrOfEnds() != 1) {
Reporter.AddFatalError("BUG: Found a clock source with more than 1 connection\n ==> "+
this.getClass().getName().replaceAll("\\.","/")+":"+Thread.currentThread().getStackTrace()[2].getLineNumber()+"\n");
return false;
}
ConnectionEnd ClockConnection = ClockSource.getEnd(0);
if (ClockConnection.NrOfBits() != 1) {
Reporter.AddFatalError("BUG: Found a clock source with a bus as output\n ==> "+
this.getClass().getName().replaceAll("\\.","/")+":"+Thread.currentThread().getStackTrace()[2].getLineNumber()+"\n");
return false;
}
ConnectionPoint SolderPoint = ClockConnection
.GetConnection((byte) 0);
/* Check if the clock source is connected */
if (SolderPoint.GetParrentNet() != null) {
/* Third pass: add this clock to the list of ClockSources */
int clockid = ClockSources.getClockId(ClockSource.GetComponent());
/* Forth pass: Add this source as clock source to the tree */
MyClockInformation.AddClockSource(HierarchyNames, clockid,
SolderPoint);
/* Fifth pass: trace the clock net all the way */
if (!TraceClockNet(SolderPoint.GetParrentNet(),
SolderPoint.GetParrentNetBitIndex(), clockid,
HierarchyNames, HierarchyNetlists, Reporter)) {
return false;
}
/*
* Sixth pass: We have to account for the complex splitters;
* therefore we have also to trace through our own netlist to
* find the clock connections
*/
ArrayList<ConnectionPoint> HiddenSinks = GetHiddenSinkNets(
SolderPoint.GetParrentNet(),
SolderPoint.GetParrentNetBitIndex(), MyComplexSplitters,
null, new HashSet<String>(), true);
for (ConnectionPoint thisNet : HiddenSinks) {
MarkClockNet(HierarchyNames, clockid, thisNet);
if (!TraceClockNet(thisNet.GetParrentNet(),
thisNet.GetParrentNetBitIndex(), clockid,
HierarchyNames, HierarchyNetlists, Reporter)) {
return false;
}
}
}
}
return true;
}
public boolean NetlistHasShortCircuits(FPGAReport Reporter) {
boolean ret = false;
for (Net net : MyNets) {
if (net.IsRootNet()) {
if (net.hasShortCircuit()) {
SimpleDRCContainer error = new SimpleDRCContainer(MyCircuit,Strings.get("NetList_ShortCircuit"),SimpleDRCContainer.LEVEL_FATAL,SimpleDRCContainer.MARK_WIRE);
error.AddMarkComponents(net.getWires());
Reporter.AddError(error);
ret = true;
}
}
}
return ret;
}
public boolean NetlistHasSinksWithoutSource(FPGAReport Reporter) {
/* First pass: we make a set with all sinks */
Set<ConnectionPoint> MySinks = new HashSet<ConnectionPoint>();
for (Net ThisNet : MyNets) {
if (ThisNet.IsRootNet()) {
MySinks.addAll(ThisNet.GetSinks());
}
}
/* Second pass: we iterate along all the sources */
for (Net ThisNet : MyNets) {
if (ThisNet.IsRootNet()) {
for (int i = 0 ; i < ThisNet.BitWidth() ; i++) {
if (ThisNet.hasBitSource(i)) {
boolean HasSink = false;
ArrayList<ConnectionPoint> Sinks = ThisNet.GetBitSinks(i);
HasSink |= !Sinks.isEmpty();
MySinks.removeAll(Sinks);
ArrayList<ConnectionPoint> HiddenSinkNets = GetHiddenSinks(
ThisNet, (byte) i, MyComplexSplitters,
null, new HashSet<String>(), true);
HasSink |= !HiddenSinkNets.isEmpty();
MySinks.removeAll(HiddenSinkNets);
if (!HasSink) {
SimpleDRCContainer warn = new SimpleDRCContainer(MyCircuit,
Strings.get("NetList_SourceWithoutSink"),
SimpleDRCContainer.LEVEL_NORMAL,
SimpleDRCContainer.MARK_WIRE);
warn.AddMarkComponents(ThisNet.getWires());
Reporter.AddWarning(warn);
}
}
}
}
}
if (MySinks.size()!= 0) {
for (ConnectionPoint Sink : MySinks) {
SimpleDRCContainer warn = new SimpleDRCContainer(MyCircuit,
Strings.get("NetList_UnsourcedSink"),
SimpleDRCContainer.LEVEL_SEVERE,
SimpleDRCContainer.MARK_INSTANCE|SimpleDRCContainer.MARK_WIRE);
warn.AddMarkComponents(Sink.GetParrentNet().getWires());
if (Sink.GetComp()!=null) {
warn.AddMarkComponent(Sink.GetComp());
}
Reporter.AddWarning(warn);
}
}
return false;
}
public int NumberOfBusses() {
int nr_of_busses = 0;
for (Net ThisNet : MyNets) {
if (ThisNet.IsRootNet() && ThisNet.isBus()) {
nr_of_busses++;
}
}
return nr_of_busses;
}
public int NumberOfClockTrees() {
return MyClockInformation.GetSourceContainer().getNrofSources();
}
public int NumberOfInOutBubbles() {
return LocalNrOfInOutBubles;
}
public int NumberOfInOutPortBits() {
int count = 0;
for (NetlistComponent inp : MyInOutPorts) {
count += inp.getEnd(0).NrOfBits();
}
return count;
}
public int NumberOfInOutPorts() {
return MyInOutPorts.size();
}
public int NumberOfInputBubbles() {
return LocalNrOfInportBubles;
}
public int NumberOfInputPortBits() {
int count = 0;
for (NetlistComponent inp : MyInputPorts) {
count += inp.getEnd(0).NrOfBits();
}
return count;
}
public int NumberOfInputPorts() {
return MyInputPorts.size();
}
public int NumberOfNets() {
int nr_of_nets = 0;
for (Net ThisNet : MyNets) {
if (ThisNet.IsRootNet() && !ThisNet.isBus()) {
nr_of_nets++;
}
}
return nr_of_nets;
}
public int NumberOfOutputBubbles() {
return LocalNrOfOutportBubles;
}
public int NumberOfOutputPortBits() {
int count = 0;
for (NetlistComponent outp : MyOutputPorts) {
count += outp.getEnd(0).NrOfBits();
}
return count;
}
public int NumberOfOutputPorts() {
return MyOutputPorts.size();
}
private boolean ProcessNormalComponent(Component comp, FPGAReport Reporter) {
NetlistComponent NormalComponent = new NetlistComponent(comp);
for (EndData ThisPin : comp.getEnds()) {
Net Connection = FindConnectedNet(ThisPin.getLocation());
if (Connection != null) {
int PinId = comp.getEnds().indexOf(ThisPin);
boolean PinIsSink = ThisPin.isInput();
ConnectionEnd ThisEnd = NormalComponent.getEnd(PinId);
Net RootNet = GetRootNet(Connection);
if (RootNet == null) {
Reporter.AddFatalError("BUG: Unable to find a root net for a normal component\n ==> "+
this.getClass().getName().replaceAll("\\.","/")+":"+Thread.currentThread().getStackTrace()[2].getLineNumber()+"\n");
return false;
}
for (byte bitid = 0; bitid < ThisPin.getWidth().getWidth(); bitid++) {
Byte RootNetBitIndex = GetRootNetIndex(Connection, bitid);
if (RootNetBitIndex < 0) {
Reporter.AddFatalError("BUG: Unable to find a root-net bit-index for a normal component\n ==> "+
this.getClass().getName().replaceAll("\\.","/")+":"+Thread.currentThread().getStackTrace()[2].getLineNumber()+"\n");
return false;
}
ConnectionPoint ThisSolderPoint = ThisEnd.GetConnection(bitid);
ThisSolderPoint.SetParrentNet(RootNet, RootNetBitIndex);
if (PinIsSink) {
RootNet.addSink(RootNetBitIndex, ThisSolderPoint);
} else {
RootNet.addSource(RootNetBitIndex, ThisSolderPoint);
}
}
}
}
if (comp.getFactory() instanceof Clock) {
MyClockGenerators.add(NormalComponent);
} else if (comp.getFactory() instanceof Pin) {
if (comp.getEnd(0).isInput()) {
MyOutputPorts.add(NormalComponent);
} else {
MyInputPorts.add(NormalComponent);
}
} else if (comp.getFactory() instanceof ReptarLocalBus) {
MyInOutPorts.add(NormalComponent);
MyInputPorts.add(NormalComponent);
MyOutputPorts.add(NormalComponent);
MyComponents.add(NormalComponent);
} else {
MyComponents.add(NormalComponent);
}
return true;
}
private boolean ProcessSubcircuit(Component comp, FPGAReport Reporter) {
NetlistComponent Subcircuit = new NetlistComponent(comp);
SubcircuitFactory sub = (SubcircuitFactory) comp.getFactory();
Instance[] subPins = ((CircuitAttributes) comp.getAttributeSet())
.getPinInstances();
Netlist subNetlist = sub.getSubcircuit().getNetList();
for (EndData ThisPin : comp.getEnds()) {
Net Connection = FindConnectedNet(ThisPin.getLocation());
int PinId = comp.getEnds().indexOf(ThisPin);
int SubPortIndex = subNetlist.GetPortInfo(subPins[PinId]
.getAttributeValue(StdAttr.LABEL));
if (SubPortIndex < 0) {
Reporter.AddFatalError("BUG: Unable to find pin in sub-circuit\n ==> "+
this.getClass().getName().replaceAll("\\.","/")+":"+Thread.currentThread().getStackTrace()[2].getLineNumber()+"\n");
return false;
}
if (Connection != null) {
boolean PinIsSink = ThisPin.isInput();
Net RootNet = GetRootNet(Connection);
if (RootNet == null) {
Reporter.AddFatalError("BUG: Unable to find a root net for sub-circuit\n ==> "+
this.getClass().getName().replaceAll("\\.","/")+":"+Thread.currentThread().getStackTrace()[2].getLineNumber()+"\n");
return false;
}
for (byte bitid = 0; bitid < ThisPin.getWidth().getWidth(); bitid++) {
Byte RootNetBitIndex = GetRootNetIndex(Connection, bitid);
if (RootNetBitIndex < 0) {
Reporter.AddFatalError("BUG: Unable to find a root-net bit-index for sub-circuit\n ==> "+
this.getClass().getName().replaceAll("\\.","/")+":"+Thread.currentThread().getStackTrace()[2].getLineNumber()+"\n");
return false;
}
Subcircuit.getEnd(PinId).GetConnection(bitid)
.SetParrentNet(RootNet, RootNetBitIndex);
if (PinIsSink) {
RootNet.addSink(RootNetBitIndex,
Subcircuit.getEnd(PinId).GetConnection(bitid));
} else {
RootNet.addSource(RootNetBitIndex,
Subcircuit.getEnd(PinId).GetConnection(bitid));
}
/*
* Special handling for sub-circuits; we have to find out
* the connection to the corresponding net in the underlying
* net-list; At this point the underlying net-lists have
* already been generated.
*/
Subcircuit.getEnd(PinId).GetConnection(bitid)
.setChildsPortIndex(SubPortIndex);
}
} else {
for (byte bitid = 0; bitid < ThisPin.getWidth().getWidth(); bitid++) {
Subcircuit.getEnd(PinId).GetConnection(bitid)
.setChildsPortIndex(SubPortIndex);
}
}
}
MySubCircuits.add(Subcircuit);
return true;
}
public String projName() {
return MyCircuit.getProjName();
}
public boolean RequiresGlobalClockConnection() {
return MyClockInformation.GetSourceContainer()
.RequiresFPGAGlobalClock();
}
public void SetCurrentHierarchyLevel(ArrayList<String> Level) {
CurrentHierarchyLevel.clear();
CurrentHierarchyLevel.addAll(Level);
}
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;
}
private boolean DetectGatedClocks(FPGAReport Reporter) {
/* First Pass: We gather a complete information tree about components with clock inputs and their connected nets in
* case it is not a clock net. The moment we call this function the clock tree has been marked already !*/
ArrayList<Netlist> root = new ArrayList<Netlist>();
root.add(this);
Map<String,Map<NetlistComponent,Circuit>> NotGatedSet = new HashMap<String,Map<NetlistComponent,Circuit>>();
Map<String,Map<NetlistComponent,Circuit>> GatedSet = new HashMap<String,Map<NetlistComponent,Circuit>>();
SetCurrentHierarchyLevel(new ArrayList<String>());
GetGatedClockComponents(root,null,NotGatedSet,GatedSet,new HashSet<NetlistComponent>(),Reporter);
boolean error = false;
for (String key : NotGatedSet.keySet()) {
if (GatedSet.keySet().contains(key)) {
/* big Problem, we have a component that is used with and without gated clocks */
error = true;
Reporter.AddFatalError(Strings.get("NetList_CircuitGatedNotGated"));
Reporter.AddErrorIncrement(Strings.get("NetList_TraceListBegin"));
Map<NetlistComponent,Circuit> instances = NotGatedSet.get(key);
for (NetlistComponent comp : instances.keySet()) {
SimpleDRCContainer warn = new SimpleDRCContainer(instances.get(comp),
Strings.get("NetList_CircuitNotGated"),
SimpleDRCContainer.LEVEL_NORMAL,
SimpleDRCContainer.MARK_INSTANCE,true);
warn.AddMarkComponent(comp.GetComponent());
Reporter.AddError(warn);
}
instances = GatedSet.get(key);
for (NetlistComponent comp : instances.keySet()) {
SimpleDRCContainer warn = new SimpleDRCContainer(instances.get(comp),
Strings.get("NetList_CircuitGated"),
SimpleDRCContainer.LEVEL_NORMAL,
SimpleDRCContainer.MARK_INSTANCE,true);
warn.AddMarkComponent(comp.GetComponent());
Reporter.AddError(warn);
}
Reporter.AddErrorIncrement(Strings.get("NetList_TraceListEnd"));
}
}
return !error;
}
public void GetGatedClockComponents(ArrayList<Netlist> HierarchyNetlists,
NetlistComponent SubCircuit,
Map<String,Map<NetlistComponent,Circuit>> NotGatedSet,
Map<String,Map<NetlistComponent,Circuit>> GatedSet,
Set<NetlistComponent> WarnedComponents,
FPGAReport Reporter) {
/* First pass: we go down the tree */
for (NetlistComponent SubCirc : MySubCircuits) {
SubcircuitFactory sub = (SubcircuitFactory) SubCirc.GetComponent().getFactory();
ArrayList<String> NewHierarchyNames = new ArrayList<String>();
ArrayList<Netlist> NewHierarchyNetlists = new ArrayList<Netlist>();
NewHierarchyNames.addAll(GetCurrentHierarchyLevel());
NewHierarchyNames.add(CorrectLabel.getCorrectLabel(SubCirc
.GetComponent().getAttributeSet()
.getValue(StdAttr.LABEL)));
NewHierarchyNetlists.addAll(HierarchyNetlists);
NewHierarchyNetlists.add(sub.getSubcircuit().getNetList());
sub.getSubcircuit().getNetList().SetCurrentHierarchyLevel(NewHierarchyNames);
sub.getSubcircuit().getNetList().GetGatedClockComponents(NewHierarchyNetlists,SubCirc,NotGatedSet,GatedSet,WarnedComponents,Reporter);
}
/* Second pass: we find all components with a clock input and see if they are connected to a clock */
boolean GatedClock = false;
List<SourceInfo> PinSources = new ArrayList<SourceInfo>();
List<Set<Wire>> PinWires = new ArrayList<Set<Wire>>();
List<Set<NetlistComponent>> PinGatedComponents = new ArrayList<Set<NetlistComponent>>();
List<SourceInfo> NonPinSources = new ArrayList<SourceInfo>();
List<Set<Wire>> NonPinWires = new ArrayList<Set<Wire>>();
List<Set<NetlistComponent>> NonPinGatedComponents = new ArrayList<Set<NetlistComponent>>();
for (NetlistComponent comp : MyComponents) {
ComponentFactory fact = comp.GetComponent().getFactory();
if (fact instanceof DFlipFlop ||
fact instanceof JKFlipFlop ||
fact instanceof SRFlipFlop ||
fact instanceof TFlipFlop) {
AttributeSet attrs = comp.GetComponent().getAttributeSet();
if (IsFlipFlop(attrs)) {
GatedClock |= HasGatedClock(comp,comp.NrOfEnds()-5,
PinSources,PinWires,PinGatedComponents,
NonPinSources,NonPinWires,NonPinGatedComponents,
WarnedComponents,Reporter);
}
} else
if (fact instanceof Counter) {
GatedClock |= HasGatedClock(comp,Counter.CK,
PinSources,PinWires,PinGatedComponents,
NonPinSources,NonPinWires,NonPinGatedComponents,
WarnedComponents,Reporter);
} else
if (fact instanceof Ram) {
if (IsFlipFlop(comp.GetComponent().getAttributeSet()))
GatedClock |= HasGatedClock(comp,Ram.CLK,
PinSources,PinWires,PinGatedComponents,
NonPinSources,NonPinWires,NonPinGatedComponents,
WarnedComponents,Reporter);
} else
if (fact instanceof Random) {
GatedClock |= HasGatedClock(comp,Random.CK,
PinSources,PinWires,PinGatedComponents,
NonPinSources,NonPinWires,NonPinGatedComponents,
WarnedComponents,Reporter);
} else
if (fact instanceof Register) {
if (IsFlipFlop(comp.GetComponent().getAttributeSet()))
GatedClock |= HasGatedClock(comp,Register.CK,
PinSources,PinWires,PinGatedComponents,
NonPinSources,NonPinWires,NonPinGatedComponents,
WarnedComponents,Reporter);
} else
if (fact instanceof ShiftRegister) {
GatedClock |= HasGatedClock(comp,ShiftRegister.CK,
PinSources,PinWires,PinGatedComponents,
NonPinSources,NonPinWires,NonPinGatedComponents,
WarnedComponents,Reporter);
}
}
/* We have two situations:
* 1) The gated clock net is generated locally, in this case we can mark them and add the current system to the non-gated set as
* each instance will be equal at higher/lower levels.
* 2) The gated clock nets are connected to a pin, in this case each instance of this circuit could be either gated or non-gated,
* we have to do something on the level higher and we mark this in the sets to be processed later.
*/
String MyName = CorrectLabel.getCorrectLabel(CircuitName);
if (HierarchyNetlists.size()>1) {
if (GatedClock&&PinSources.isEmpty()) {
GatedClock = false; /* we have only non-pin driven gated clocks */
WarningForGatedClock(NonPinSources,NonPinGatedComponents,NonPinWires,WarnedComponents,HierarchyNetlists,Reporter,Strings.get("NetList_GatedClock"));
}
if (GatedClock&&!PinSources.isEmpty()) {
for (int i = 0 ; i < PinSources.size() ; i++) {
Reporter.AddSevereWarning(Strings.get("NetList_GatedClock"));
Reporter.AddWarningIncrement(Strings.get("NetList_TraceListBegin"));
SimpleDRCContainer warn = new SimpleDRCContainer(MyCircuit,
Strings.get("NetList_GatedClockSink"),
SimpleDRCContainer.LEVEL_NORMAL,
SimpleDRCContainer.MARK_INSTANCE|SimpleDRCContainer.MARK_WIRE,true);
warn.AddMarkComponents(PinWires.get(i));
for (NetlistComponent comp : PinGatedComponents.get(i))
warn.AddMarkComponent(comp.GetComponent());
Reporter.AddWarning(warn);
WarningTraceForGatedClock(PinSources.get(i).getSource(),PinSources.get(i).getIndex(),HierarchyNetlists,CurrentHierarchyLevel,Reporter);
Reporter.AddWarningIncrement(Strings.get("NetList_TraceListEnd"));
}
}
/* we only mark if we are not at top-level */
if (GatedClock) {
if (GatedSet.containsKey(MyName))
GatedSet.get(MyName).put(SubCircuit,HierarchyNetlists.get(HierarchyNetlists.size()-2).getCircuit());
else {
Map<NetlistComponent,Circuit> newList = new HashMap<NetlistComponent,Circuit>();
newList.put(SubCircuit,HierarchyNetlists.get(HierarchyNetlists.size()-2).getCircuit());
GatedSet.put(MyName,newList);
}
} else {
if (NotGatedSet.containsKey(MyName))
NotGatedSet.get(MyName).put(SubCircuit,HierarchyNetlists.get(HierarchyNetlists.size()-2).getCircuit());
else {
Map<NetlistComponent,Circuit> newList = new HashMap<NetlistComponent,Circuit>();
newList.put(SubCircuit,HierarchyNetlists.get(HierarchyNetlists.size()-2).getCircuit());
NotGatedSet.put(MyName,newList);
}
}
} else {
/* At toplevel we warn for all possible gated clocks */
WarningForGatedClock(NonPinSources,NonPinGatedComponents,NonPinWires,WarnedComponents,HierarchyNetlists,Reporter,Strings.get("NetList_GatedClock"));
WarningForGatedClock(PinSources,PinGatedComponents,PinWires,WarnedComponents,HierarchyNetlists,Reporter,Strings.get("NetList_PossibleGatedClock"));
}
}
private boolean HasGatedClock(NetlistComponent comp,
int ClockPinIndex,
List<SourceInfo> PinSources,
List<Set<Wire>> PinWires,
List<Set<NetlistComponent>> PinGatedComponents,
List<SourceInfo> NonPinSources,
List<Set<Wire>> NonPinWires,
List<Set<NetlistComponent>> NonPinGatedComponents,
Set<NetlistComponent> WarnedComponents,
FPGAReport Reporter) {
boolean GatedClock = false;
String ClockNetName = AbstractHDLGeneratorFactory.GetClockNetName(comp,ClockPinIndex, this);
if (ClockNetName.isEmpty()) {
/* we search for the source in case it is connected otherwise we ignore */
ConnectionPoint connection = comp.getEnd(ClockPinIndex).GetConnection((byte) 0);
Net connectedNet = connection.GetParrentNet();
byte connectedNetindex = connection.GetParrentNetBitIndex();
if (connectedNet != null) {
GatedClock = true;
if (connectedNet.IsForcedRootNet()) {
Set<Wire> Segments = new HashSet<Wire>();
Location loc = comp.GetComponent().getEnd(ClockPinIndex).getLocation();
for (Net thisOne : MyNets)
if (thisOne.contains(loc)) {
if (!thisOne.IsRootNet())
Segments.addAll(thisOne.getWires());
}
SourceInfo SourceList = GetHiddenSource(connectedNet, connectedNetindex,
MyComplexSplitters, null,new HashSet<String>(),Segments,Reporter);
ConnectionPoint source = SourceList.getSource();
if (source.GetComp().getFactory() instanceof Pin) {
int index = IndexOfEntry(PinSources,source,(int)connectedNetindex);
if (index < 0) {
PinSources.add(SourceList);
PinWires.add(Segments);
Set<NetlistComponent> comps = new HashSet<NetlistComponent>();
comps.add(comp);
comps.add(new NetlistComponent(source.GetComp()));
PinGatedComponents.add(comps);
} else {
PinGatedComponents.get(index).add(comp);
}
} else {
int index = IndexOfEntry(NonPinSources,source,(int)connectedNetindex);
if (index < 0) {
NonPinSources.add(SourceList);
NonPinWires.add(Segments);
Set<NetlistComponent> comps = new HashSet<NetlistComponent>();
comps.add(comp);
NonPinGatedComponents.add(comps);
} else {
NonPinGatedComponents.get(index).add(comp);
}
}
} else {
ArrayList<ConnectionPoint> SourceList = connectedNet.GetBitSources(connectedNetindex);
if (SourceList.size()!= 1) {
Reporter.AddFatalError("BUG: Found multiple sources\n ==> "+
this.getClass().getName().replaceAll("\\.","/")+":"+Thread.currentThread().getStackTrace()[2].getLineNumber()+"\n");
return GatedClock;
}
ConnectionPoint source = SourceList.get(0);
if (source.GetComp().getFactory() instanceof Pin) {
int index = IndexOfEntry(PinSources,source,(int)connectedNetindex);
if (index < 0) {
SourceInfo NewEntry = new SourceInfo(source,connectedNetindex);
PinSources.add(NewEntry);
PinWires.add(connectedNet.getWires());
Set<NetlistComponent> comps = new HashSet<NetlistComponent>();
comps.add(comp);
PinGatedComponents.add(comps);
} else {
PinGatedComponents.get(index).add(comp);
}
} else {
int index = IndexOfEntry(NonPinSources,source,(int)connectedNetindex);
if (index < 0) {
SourceInfo NewEntry = new SourceInfo(source,connectedNetindex);
NonPinSources.add(NewEntry);
NonPinWires.add(connectedNet.getWires());
Set<NetlistComponent> comps = new HashSet<NetlistComponent>();
comps.add(comp);
NonPinGatedComponents.add(comps);
} else {
NonPinGatedComponents.get(index).add(comp);
}
}
}
} else {
/* Add severe warning, we found a memory with an unconnected clock input */
if (!WarnedComponents.contains(comp)) {
SimpleDRCContainer warn = new SimpleDRCContainer(MyCircuit,
Strings.get("NetList_NoClockConnection"),
SimpleDRCContainer.LEVEL_SEVERE,
SimpleDRCContainer.MARK_INSTANCE);
warn.AddMarkComponent(comp.GetComponent());
Reporter.AddWarning(warn);
WarnedComponents.add(comp);
}
}
}
return GatedClock;
}
private int IndexOfEntry(List<SourceInfo> SearchList,
ConnectionPoint Connection,
Integer index) {
int result = -1;
for (int i = 0 ; i < SearchList.size() ; i++) {
SourceInfo thisEntry = SearchList.get(i);
if (thisEntry.getSource().equals(Connection)&&
thisEntry.getIndex().equals(index))
result = i;
}
return result;
}
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);
}
}
}
}
private void WarningForGatedClock(List<SourceInfo> Sources,
List<Set<NetlistComponent>> Components,
List<Set<Wire>> Wires,
Set<NetlistComponent> WarnedComponents,
ArrayList<Netlist> HierarchyNetlists,
FPGAReport Reporter,
String Warning) {
for (int i = 0 ; i < Sources.size() ; i++) {
boolean AlreadyWarned = false;
for (NetlistComponent comp : Components.get(i))
AlreadyWarned |= WarnedComponents.contains(comp);
if (!AlreadyWarned) {
if (Sources.get(i).getSource().GetComp().getFactory() instanceof SubcircuitFactory) {
Reporter.AddSevereWarning(Strings.get("NetList_GatedClock"));
Reporter.AddWarningIncrement(Strings.get("NetList_TraceListBegin"));
SimpleDRCContainer warn = new SimpleDRCContainer(MyCircuit,
Strings.get("NetList_GatedClockSink"),
SimpleDRCContainer.LEVEL_NORMAL,
SimpleDRCContainer.MARK_INSTANCE|SimpleDRCContainer.MARK_WIRE,true);
warn.AddMarkComponents(Wires.get(i));
for (NetlistComponent comp : Components.get(i))
warn.AddMarkComponent(comp.GetComponent());
Reporter.AddWarning(warn);
WarningTraceForGatedClock(Sources.get(i).getSource(),Sources.get(i).getIndex(),HierarchyNetlists,CurrentHierarchyLevel,Reporter);
Reporter.AddWarningIncrement(Strings.get("NetList_TraceListEnd"));
} else {
SimpleDRCContainer warn = new SimpleDRCContainer(MyCircuit,
Warning,
SimpleDRCContainer.LEVEL_SEVERE,
SimpleDRCContainer.MARK_INSTANCE|SimpleDRCContainer.MARK_WIRE);
for (NetlistComponent comp : Components.get(i))
warn.AddMarkComponent(comp.GetComponent());
warn.AddMarkComponents(Wires.get(i));
Reporter.AddWarning(warn);
}
WarnedComponents.addAll(Components.get(i));
}
}
}
static public boolean IsFlipFlop(AttributeSet attrs) {
if (attrs.containsAttribute(StdAttr.EDGE_TRIGGER))
return true;
if (attrs.containsAttribute(StdAttr.TRIGGER)) {
return ((attrs.getValue(StdAttr.TRIGGER) == StdAttr.TRIG_FALLING) || (attrs
.getValue(StdAttr.TRIGGER) == StdAttr.TRIG_RISING));
}
return false;
}
}