📄 getnetlist.java
字号:
/* -*- tab-width: 4 -*- * * Electric(tm) VLSI Design System * * File: GetNetlist.java * Silicon compiler tool (QUISC): read a netlist * Written by Andrew R. Kostiuk, Queen's University. * Translated to Java by Steven M. Rubin, Sun Microsystems. * * Copyright (c) 2005 Sun Microsystems and Static Free Software * * Electric(tm) 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. * * Electric(tm) 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 Electric(tm); see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, Mass 02111-1307, USA. */package com.sun.electric.tool.sc;import com.sun.electric.database.hierarchy.Cell;import com.sun.electric.database.hierarchy.Export;import com.sun.electric.database.hierarchy.Library;import com.sun.electric.database.hierarchy.View;import com.sun.electric.database.prototype.NodeProto;import com.sun.electric.database.prototype.PortCharacteristic;import com.sun.electric.database.prototype.PortProto;import com.sun.electric.database.text.TextUtils;import java.util.ArrayList;import java.util.Iterator;import java.util.List;/** * This is the netlist reader of the Silicon Compiler tool. */public class GetNetlist{ /*********************************************************************** General Constants ------------------------------------------------------------------------*/ private static final int GND = 0; private static final int PWR = 1; /***** Directions that ports can be attached to *****/ /** mask for port direction */ public static final int PORTDIRMASK = 0x0000000F; /** port direction up */ public static final int PORTDIRUP = 0x00000001; /** port direction down */ public static final int PORTDIRDOWN = 0x00000002; /** port direction right */ public static final int PORTDIRRIGHT= 0x00000004; /** port direction left */ public static final int PORTDIRLEFT = 0x00000008; /** port type mask */ public static final int PORTTYPE = 0x000003F0; /** ground port */ public static final int GNDPORT = 0x00000010; /** power port */ public static final int PWRPORT = 0x00000020; /** bidirectional port */ public static final int BIDIRPORT = 0x00000040; /** output port */ public static final int OUTPORT = 0x00000080; /** input port */ public static final int INPORT = 0x00000100; /** unknown port */ public static final int UNPORT = 0x00000200; /*********************************************************************** QUISC Cell Structure ------------------------------------------------------------------------*/ static class SCCell { /** name of complex cell */ String name; /** maximum number of nodes */ int maxNodeNum; /** list of instances for cell */ List<SCNiTree> niList; /** extracted nodes */ ExtNode exNodes; /** flags for processing cell */ int bits; /** list of power ports */ ExtNode power; /** list of ground ports */ ExtNode ground; /** list of ports */ SCPort ports, lastPort; /** placement information of cell */ Place.SCPlace placement; /** routing information for cell */ Route.SCRoute route; /** next in list of SC cells */ SCCell next; }; static class SCPort { /** name of port */ String name; /** special node */ SCNiTree node; /** cell on which this port resides */ SCCell parent; /** port attributes */ int bits; /** pointer to next port */ SCPort next; }; static class SCCellNums { /** active area from top */ int topActive; /** active are from bottom */ int bottomActive; /** active area from left */ int leftActive; /** active are from right */ int rightActive; }; /*********************************************************************** Instance Tree Structure ------------------------------------------------------------------------*/ /***** Types of Instances *****/ public static final int LEAFCELL = 0; public static final int COMPLEXCELL = 1; public static final int SPECIALCELL = 2; public static final int FEEDCELL = 3; public static final int STITCH = 4; public static final int LATERALFEED = 5; static class SCNiTree { /** name of instance */ String name; /** alternative number of node */ int number; /** type of instance */ int type; /** leaf cell or SCCell if complex */ Object np; /** x size if leaf cell */ double size; /** pointer to connection list */ ConList connect; /** list of io ports and ext nodes */ SCNiPort ports; /** list of actual power ports */ SCNiPort power; /** list of actual ground ports */ SCNiPort ground; /** bits for silicon compiler */ int flags; /** generic temporary pointer */ Object tp; /** * Method to create a new instance with a given name and type. * @param name name of the instance. * @param type type of the instance. */ SCNiTree(String name, int type) { this.name = name; this.type = type; this.number = 0; this.np = null; this.size = 0; this.connect = null; this.ports = null; this.power = null; this.ground = null; this.flags = 0; this.tp = null; } }; static class SCNiPort { /** leaf port or SCPort if on cell */ Object port; /** extracted node */ ExtNode extNode; /** bits for processing */ int bits; /** x position if leaf port */ double xPos; /** list of instance ports */ SCNiPort next; SCNiPort() {} SCNiPort(SCNiTree instance) { this.port = null; this.extNode = null; this.bits = 0; this.xPos = 0; this.next = instance.ports; instance.ports = this; } }; /*********************************************************************** Connection Structures ------------------------------------------------------------------------*/ private static class ConList { /** pointer to port on node A */ SCNiPort portA; /** pointer to node B */ SCNiTree nodeB; /** pointer to port on node B */ SCNiPort portB; /** pointer to extracted node */ ExtNode extNode; /** pointer to next list element */ ConList next; }; /*********************************************************************** Extraction Structures ------------------------------------------------------------------------*/ private static class ExtPort { /** instance of extracted node */ SCNiTree node; /** instance port */ SCNiPort port; /** next in list of common node */ ExtPort next; }; /** * Class for communicating netlist information to the placer and router. */ public static class ExtNode { /** optional name of port */ String name; /** link list of ports */ ExtPort firstPort; /** flags for processing */ int flags; /** generic pointer for processing */ Object ptr; /** link list of nodes */ ExtNode next; }; SCCell scCells, curSCCell; /** * Read the netlist associated with the current cell. * @return true on error. */ public boolean readNetCurCell(Cell cell) { scCells = null; curSCCell = null; if (cell.getView() != View.NETLISTQUISC) { System.out.println("Current cell must have QUISC Netlist view"); return true; } String [] strings = cell.getTextViewContents(); if (strings == null) { System.out.println("Cell " + cell.describe(true) + " has no text in it"); return true; } // read entire netlist boolean errors = false; for(int i=0; i<strings.length; i++) { String inBuf = strings[i].trim(); // check for a comment line or empty line if (inBuf.length() == 0 || inBuf.charAt(0) == '!') continue; // break into keywords List<String> parameters = new ArrayList<String>(); for(int sPtr = 0; sPtr < inBuf.length(); sPtr++) { // get rid of leading white space while (sPtr < inBuf.length() && (inBuf.charAt(sPtr) == ' ' || inBuf.charAt(sPtr) == '\t')) sPtr++; if (sPtr >= inBuf.length()) break; // check for string if (inBuf.charAt(sPtr) == '"') { sPtr++; int endQuote = inBuf.indexOf('"', sPtr); if (endQuote < 0) { System.out.println("ERROR line " + (i+1) + ": Unbalanced quotes "); errors = true; break; } parameters.add(inBuf.substring(sPtr, endQuote)); sPtr = endQuote; } else { int endSpace = inBuf.indexOf(' ', sPtr); int endTab = inBuf.indexOf('\t', sPtr); if (endSpace < 0) endSpace = endTab; if (endSpace < 0) endSpace = inBuf.length(); if (endTab >= 0 && endTab < endSpace) endSpace = endTab; parameters.add(inBuf.substring(sPtr, endSpace)); sPtr = endSpace; } } String err = parse(parameters); if (err != null) { System.out.println("ERROR line " + (i+1) + ": " + err); System.out.println(" Line: " + inBuf); errors = true; break; } } // do the "pull" (extract) String err = pull(); if (err != null) { System.out.println(err); errors = true; } return errors; } /** * Main parsing routine for the Silicon Compiler. */ private String parse(List<String> keywords) { if (keywords.size() == 0) return null; String mainKeyword = keywords.get(0); if (mainKeyword.equalsIgnoreCase("connect")) return connect(keywords); if (mainKeyword.equalsIgnoreCase("create")) return create(keywords); if (mainKeyword.equalsIgnoreCase("export")) return export(keywords); if (mainKeyword.equalsIgnoreCase("extract")) return extract(keywords); if (mainKeyword.equalsIgnoreCase("set")) return xSet(keywords); return "Unknown keyword: " + mainKeyword; } /**************************************** NETLIST READING: THE CREATE KEYWORD ****************************************/ private String create(List<String> keywords) { if (keywords.size() <= 1) return "No keyword for CREATE command"; String sPtr = keywords.get(1); if (sPtr.equalsIgnoreCase("cell")) { if (keywords.size() <= 2) return "No name for CREATE CELL command"; sPtr = keywords.get(2); // check if cell already exists in cell list for(SCCell cell = scCells; cell != null; cell = cell.next) { if (sPtr.equalsIgnoreCase(cell.name)) return "Cell '" + sPtr + "' already exists in current library"; } // generate warning message if a leaf cell of the same name exists if (findLeafCell(sPtr) != null) System.out.println("WARNING - cell " + sPtr + " may be overridden by created cell"); // create new cell SCCell newCell = new SCCell(); newCell.name = sPtr; newCell.maxNodeNum = 0; newCell.niList = new ArrayList<SCNiTree>(); newCell.exNodes = null; newCell.bits = 0; newCell.power = null; newCell.ground = null; newCell.ports = null; newCell.lastPort = null; newCell.placement = null; newCell.route = null; newCell.next = scCells; scCells = newCell; curSCCell = newCell; // create dummy ground and power nodes SCNiTree ntp = findNi(curSCCell, "ground"); if (ntp != null) return "Instance 'ground' already exists"; ntp = new SCNiTree("ground", SPECIALCELL); curSCCell.niList.add(ntp); new SCNiPort(ntp); ntp.number = curSCCell.maxNodeNum++; ntp = findNi(curSCCell, "power"); if (ntp != null) return "Instance 'power' already exists"; ntp = new SCNiTree("power", SPECIALCELL); curSCCell.niList.add(ntp); new SCNiPort(ntp); ntp.number = curSCCell.maxNodeNum++; return null; } if (sPtr.equalsIgnoreCase("instance")) { if (keywords.size() <= 2) return "No instance name for CREATE INSTANCE command"; String noden = keywords.get(2); if (keywords.size() <= 3) return "No type name for CREATE INSTANCE command"; String nodep = keywords.get(3); // search for cell in cell list SCCell cell = null; for(SCCell c = scCells; c != null; c = c.next) { if (nodep.equalsIgnoreCase(c.name)) { cell = c; break; } } Object proto = cell; int type = COMPLEXCELL; double size = 0; if (cell == null) { // search for leaf cell in library Cell bc = findLeafCell(nodep); if (bc == null) return "There is no '" + nodep + "' in the standard cell library"; proto = bc; type = LEAFCELL; size = SilComp.leafCellXSize(bc); } // check if currently working in a cell if (curSCCell == null) return "No cell selected"; // check if instance name already exits SCNiTree ntp = findNi(curSCCell, noden); if (ntp != null) return "Instance '" + noden + "' already exists"; // add instance name to tree ntp = new SCNiTree(noden, type); curSCCell.niList.add(ntp); ntp.number = curSCCell.maxNodeNum++; ntp.np = proto; ntp.size = size; // create ni port list if (type == COMPLEXCELL) { SCNiPort oldNiPort = null; for (SCPort port = ((SCCell)proto).ports; port != null; port = port.next) { SCNiPort niPort = new SCNiPort(); niPort.port = port; niPort.extNode = null; niPort.bits = 0; niPort.xPos = 0; switch (port.bits & PORTTYPE) { case GNDPORT: niPort.next = ntp.ground; ntp.ground = niPort; break; case PWRPORT: niPort.next = ntp.power; ntp.power = niPort; break; default: niPort.next = null; if (oldNiPort == null) { ntp.ports = niPort; } else { oldNiPort.next = niPort; } oldNiPort = niPort; break; } } } else { SCNiPort oldNiPort = null; Cell realCell = (Cell)proto; for(Iterator<PortProto> it = realCell.getPorts(); it.hasNext(); ) { Export bp = (Export)it.next(); SCNiPort niPort = new SCNiPort(); niPort.port = bp; niPort.extNode = null; niPort.bits = 0; niPort.xPos = SilComp.leafPortXPos(bp); switch (getLeafPortType(bp)) { case GNDPORT: niPort.next = ntp.ground; ntp.ground = niPort; break; case PWRPORT: niPort.next = ntp.power; ntp.power = niPort; break; default: niPort.next = null; if (oldNiPort == null) { ntp.ports = niPort; } else { oldNiPort.next = niPort; } oldNiPort = niPort; break; } } } return null; } return "Unknown CREATE command: " + sPtr; } /** * Method to find the location in a SCNiTree where the node should be placed. * If the pointer does not have a value of null, then the object already exits. */ private SCNiTree findNi(SCCell cell, String name) { for(SCNiTree nPtr : cell.niList) { if (nPtr.name.equalsIgnoreCase(name)) return nPtr; } return null; } /**************************************** NETLIST READING: THE CONNECT KEYWORD ****************************************/ private String connect(List<String> keywords) { if (keywords.size() < 4) return "Not enough parameters for CONNECT command"; // search for the first node String node0Name = keywords.get(1); String port0Name = keywords.get(2); SCNiTree ntpA = findNi(curSCCell, node0Name); if (ntpA == null) return "Cannot find instance '" + node0Name + "'"; SCNiPort portA = findPp(ntpA, port0Name); if (portA == null) return "Cannot find port '" + port0Name + "' on instance '" + node0Name + "'"; // search for the second node String node1Name = keywords.get(3); SCNiTree ntpB = findNi(curSCCell, node1Name); if (ntpB == null) return "Cannot find instance '" + node1Name + "'"; // check for special power or ground node SCNiPort portB = ntpB.ports; if (ntpB.type != SPECIALCELL) { if (keywords.size() < 5) return "Not enough parameters for CONNECT command"; String port1Name = keywords.get(4); portB = findPp(ntpB, port1Name); if (portB == null) return "Cannot find port '" + port1Name + "' on instance '" + node1Name + "'"; } conList(ntpA, portA, ntpB, portB); return null; } /** * Method to find the port on the given node instance. * @return null if port is not found. */ private SCNiPort findPp(SCNiTree ntp, String name) { SCNiPort port = null; if (ntp == null) return null; switch (ntp.type)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -