Search in sources :

Example 1 with SplitterFactory

use of com.cburch.logisim.circuit.SplitterFactory 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;
}
Also used : GridBagConstraints(java.awt.GridBagConstraints) SplitterFactory(com.cburch.logisim.circuit.SplitterFactory) GridBagLayout(java.awt.GridBagLayout) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) JProgressBar(javax.swing.JProgressBar) Rectangle(java.awt.Rectangle) Probe(com.cburch.logisim.std.wiring.Probe) JFrame(javax.swing.JFrame) SubcircuitFactory(com.cburch.logisim.circuit.SubcircuitFactory) InstanceComponent(com.cburch.logisim.instance.InstanceComponent) Component(com.cburch.logisim.comp.Component) HashSet(java.util.HashSet) EndData(com.cburch.logisim.comp.EndData) Splitter(com.cburch.logisim.circuit.Splitter) JLabel(javax.swing.JLabel) Tunnel(com.cburch.logisim.std.wiring.Tunnel) Pin(com.cburch.logisim.std.wiring.Pin) Location(com.cburch.logisim.data.Location)

Aggregations

Splitter (com.cburch.logisim.circuit.Splitter)1 SplitterFactory (com.cburch.logisim.circuit.SplitterFactory)1 SubcircuitFactory (com.cburch.logisim.circuit.SubcircuitFactory)1 Component (com.cburch.logisim.comp.Component)1 EndData (com.cburch.logisim.comp.EndData)1 Location (com.cburch.logisim.data.Location)1 InstanceComponent (com.cburch.logisim.instance.InstanceComponent)1 Pin (com.cburch.logisim.std.wiring.Pin)1 Probe (com.cburch.logisim.std.wiring.Probe)1 Tunnel (com.cburch.logisim.std.wiring.Tunnel)1 GridBagConstraints (java.awt.GridBagConstraints)1 GridBagLayout (java.awt.GridBagLayout)1 Rectangle (java.awt.Rectangle)1 ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1 HashSet (java.util.HashSet)1 JFrame (javax.swing.JFrame)1 JLabel (javax.swing.JLabel)1 JProgressBar (javax.swing.JProgressBar)1