/** * Method to tell whether this NodeInst is an icon of its parent. Electric does not allow * recursive circuit hierarchies (instances of Cells inside of themselves). However, it does allow * one exception: a schematic may contain its own icon for documentation purposes. This method * determines whether this NodeInst is such an icon. * * @return true if this NodeInst is an icon of its parent. */ private boolean isIconOfParent(ImmutableNodeInst n) { if (!(n.protoId instanceof CellId)) { return false; } CellBackup subCell = snapshot.getCell((CellId) n.protoId); CellId subCellId = subCell.cellRevision.d.cellId; return subCellId.isIcon() && cellId.isSchematic() && subCellId.libId == cellId.libId && subCell.cellRevision.d.groupName.equals(cellRevision.d.groupName); }
private EquivalentSchematicExports getEquivExports(CellId cellId) { if (!(cellId.isIcon() || cellId.isSchematic())) { throw new IllegalArgumentException(); } EquivalentSchematicExports eq = snapshot.equivSchemExports[cellId.cellIndex]; if (eq == null) { ImmutableNetSchem netSchem = new ImmutableNetSchem(snapshot, cellId); eq = new EquivalentSchematicExports(netSchem); snapshot.equivSchemExports[cellId.cellIndex] = eq; } return eq; }
private void localConnections(int netMap[]) { // Exports for (int k = 0; k < numExports; k++) { ImmutableExport e = exports.get(k); int portOffset = portOffsets[k]; Name expNm = e.name; int busWidth = expNm.busWidth(); int drawn = drawns[k]; int drawnOffset = drawnOffsets[drawn]; for (int i = 0; i < busWidth; i++) { ImmutableNetLayout.connectMap( netMap, portOffset + i, drawnOffset + (busWidth == drawnWidths[drawn] ? i : i % drawnWidths[drawn])); GenMath.MutableInteger nn = netNames.get(expNm.subname(i)); ImmutableNetLayout.connectMap(netMap, portOffset + i, netNamesOffset + nn.intValue()); } } // PortInsts for (int k = 0; k < numNodes; k++) { ImmutableNodeInst n = nodes.get(k); if (isIconOfParent(n)) { continue; } // NodeProto np = ni.getProto(); if (n.protoId instanceof PrimitiveNodeId) { // Connect global primitives Global g = globalInst(n); if (g != null) { int drawn = drawns[ni_pi[k]]; ImmutableNetLayout.connectMap(netMap, globals.indexOf(g), drawnOffsets[drawn]); } if (n.protoId == schem.wireConNode.getId()) { connectWireCon(netMap, n); } continue; } IconInst iconInst = iconInsts[k]; if (iconInst == null || iconInst.iconOfParent) { continue; } assert iconInst.nodeInst == n; CellId subCellId = (CellId) n.protoId; assert subCellId.isIcon() || subCellId.isSchematic(); EquivalentSchematicExports iconEq = iconInst.eq; EquivalentSchematicExports schemEq = iconEq.implementation; assert schemEq != null; Name nodeName = n.name; int arraySize = nodeName.busWidth(); int numPorts = getNumPorts(n.protoId); CellBackup subCell = snapshot.getCell(subCellId); for (int m = 0; m < numPorts; m++) { ImmutableExport e = subCell.cellRevision.exports.get(m); Name busExportName = e.name; int busWidth = busExportName.busWidth(); int drawn = drawns[ni_pi[k] + m]; if (drawn < 0) { continue; } int width = drawnWidths[drawn]; if (width != busWidth && width != busWidth * arraySize) { continue; } for (int arrayIndex = 0; arrayIndex < arraySize; arrayIndex++) { int nodeOffset = iconInst.netMapOffset + arrayIndex * iconInst.numExtendedExports; int busOffset = drawnOffsets[drawn]; if (width != busWidth) { busOffset += busWidth * arrayIndex; } for (int j = 0; j < busWidth; j++) { Name exportName = busExportName.subname(j); int portOffset = schemEq.getExportNameMapOffset(exportName); if (portOffset < 0) { continue; } ImmutableNetLayout.connectMap(netMap, busOffset + j, nodeOffset + portOffset); } } } } // Arcs for (int arcIndex = 0; arcIndex < numArcs; arcIndex++) { ImmutableArcInst a = arcs.get(arcIndex); int drawn = drawns[arcsOffset + arcIndex]; if (drawn < 0) { continue; } if (!a.isUsernamed()) { continue; } int busWidth = drawnWidths[drawn]; Name arcNm = a.name; if (arcNm.busWidth() != busWidth) { continue; } int drawnOffset = drawnOffsets[drawn]; for (int i = 0; i < busWidth; i++) { GenMath.MutableInteger nn = netNames.get(arcNm.subname(i)); ImmutableNetLayout.connectMap(netMap, drawnOffset + i, netNamesOffset + nn.intValue()); } } // Globals of proxies for (IconInst iconInst : iconInsts) { if (iconInst == null || iconInst.iconOfParent) { continue; } Set<Global> excludeGlobals = null; if (iconInstExcludeGlobals != null) { excludeGlobals = iconInstExcludeGlobals.get(iconInst); } for (int k = 0; k < iconInst.nodeInst.name.busWidth(); k++) { EquivalentSchematicExports eq = iconInst.eq.implementation; assert eq.implementation == eq; int numGlobals = eq.portOffsets[0]; if (numGlobals == 0) { continue; } int nodableOffset = iconInst.netMapOffset + k * iconInst.numExtendedExports; for (int i = 0; i < numGlobals; i++) { Global g = eq.globals.get(i); if (excludeGlobals != null && excludeGlobals.contains(g)) { continue; } ImmutableNetLayout.connectMap(netMap, this.globals.indexOf(g), nodableOffset + i); } } } ImmutableNetLayout.closureMap(netMap); }
private void initNodables() { Global.Buf globalBuf = new Global.Buf(); Map<ImmutableNodeInst, Set<Global>> nodeInstExcludeGlobal = null; for (int i = 0; i < numNodes; i++) { ImmutableNodeInst n = nodes.get(i); // NodeProto np = ni.getProto(); // NetCell netCell = null; // if (ni.isCellInstance()) { // netCell = networkManager.getNetCell((Cell) np); // } if (n.protoId instanceof CellId && (((CellId) n.protoId).isIcon() || ((CellId) n.protoId).isSchematic())) { if (n.name.hasDuplicates()) { String msg = cellId + ": Node name <" + n.name + "> has duplicate subnames"; System.out.println(msg); // networkManager.pushHighlight(ni); // networkManager.logError(msg, NetworkTool.errorSortNodes); } } else { if (n.name.isBus()) { String msg = cellId + ": Array name <" + n.name + "> can be assigned only to icon nodes"; System.out.println(msg); // networkManager.pushHighlight(ni); // networkManager.logError(msg, NetworkTool.errorSortNodes); } } if (n.protoId instanceof CellId) { CellId subCellId = (CellId) n.protoId; if (!(subCellId.isIcon() || subCellId.isSchematic())) { continue; } if (isIconOfParent(n)) { continue; } EquivalentSchematicExports netEq = getEquivExports((CellId) n.protoId); EquivalentSchematicExports schemEq = netEq.implementation; assert schemEq != null && schemEq.getCellId() != cellId; Global.Set gs = schemEq.getGlobals(); // Check for rebinding globals if (schemEq.implementation.globalPartitions != null) { int numPortInsts = getNumPorts(n.protoId); Set<Global> gb = null; for (int j = 0; j < numPortInsts; j++) { PortInst pi = new PortInst(n.nodeId, getPortIdByIndex(n.protoId, j)); int piOffset = pi.getPortInstOffset(); int drawn = drawns[piOffset]; if (drawn < 0 || drawn >= numConnectedDrawns) { continue; } ImmutableExport e = netEq.exports.get(j); assert e.exportId == pi.portId; Name busName = e.name; for (int busIndex = 0; busIndex < busName.busWidth(); busIndex++) { Name exportName = busName.subname(busIndex); Global.Set globalsOnElement = schemEq.globalPartitions.get(exportName); if (globalsOnElement == null) { continue; } if (gb == null) { gb = new HashSet<Global>(); } for (int l = 0; l < globalsOnElement.size(); l++) { Global g = globalsOnElement.get(l); gb.add(g); } } } if (gb != null) { // remember excluded globals for this NodeInst if (nodeInstExcludeGlobal == null) { nodeInstExcludeGlobal = new HashMap<ImmutableNodeInst, Set<Global>>(); } nodeInstExcludeGlobal.put(n, gb); // fix Set of globals gs = gs.remove(gb.iterator()); } } String errorMsg = globalBuf.addToBuf(gs); if (errorMsg != null) { String msg = "Network: " + cellId + " has globals with conflicting characteristic " + errorMsg; System.out.println(msg); // networkManager.logError(msg, NetworkTool.errorSortNetworks); // TODO: what to highlight? // log.addGeom(shared[i].nodeInst, true, 0, null); } } else { Global g = globalInst(n); if (g != null) { PortCharacteristic characteristic; if (g == Global.ground) { characteristic = PortCharacteristic.GND; } else if (g == Global.power) { characteristic = PortCharacteristic.PWR; } else { characteristic = PortCharacteristic.findCharacteristic(n.techBits); if (characteristic == null) { String msg = "Network: " + cellId + " has global " + g.getName() + " with unknown characteristic bits"; System.out.println(msg); // networkManager.pushHighlight(ni); // networkManager.logError(msg, // NetworkTool.errorSortNetworks); characteristic = PortCharacteristic.UNKNOWN; } } String errorMsg = globalBuf.addToBuf(g, characteristic); if (errorMsg != null) { String msg = "Network: " + cellId + " has global with conflicting characteristic " + errorMsg; System.out.println(msg); // networkManager.logError(msg, NetworkTool.errorSortNetworks); // log.addGeom(shared[i].nodeInst, true, 0, null); } } } } globals = globalBuf.getBuf(); // boolean changed = false; // if (globals != newGlobals) { // changed = true; // globals = newGlobals; // if (NetworkTool.debug) { // System.out.println(cell + " has " + globals); // } // } int mapOffset = portOffsets[0] = globals.size(); for (int i = 1; i <= numExports; i++) { ImmutableExport export = exports.get(i - 1); if (DEBUG) { System.out.println(export + " " + portOffsets[i - 1]); } mapOffset += export.name.busWidth(); // if (portOffsets[i] != mapOffset) { // changed = true; portOffsets[i] = mapOffset; // } } equivPortsN = new int[mapOffset]; equivPortsP = new int[mapOffset]; equivPortsA = new int[mapOffset]; for (int i = 0; i < numDrawns; i++) { drawnOffsets[i] = mapOffset; mapOffset += drawnWidths[i]; if (DEBUG) { System.out.println("Drawn " + i + " has offset " + drawnOffsets[i]); } } iconInsts = new IconInst[numNodes]; iconInstExcludeGlobals = null; for (int nodeIndex = 0; nodeIndex < numNodes; nodeIndex++) { ImmutableNodeInst n = nodes.get(nodeIndex); if (!(n.protoId instanceof CellId)) { continue; } CellId subCellId = (CellId) n.protoId; if (!subCellId.isIcon() && !subCellId.isSchematic()) { continue; } IconInst iconInst = new IconInst(n, mapOffset); iconInsts[nodeIndex] = iconInst; if (isIconOfParent(n)) { continue; } EquivalentSchematicExports netEq = iconInst.eq; EquivalentSchematicExports schemEq = netEq.implementation; assert schemEq != null; Set<Global> gs = nodeInstExcludeGlobal != null ? nodeInstExcludeGlobal.get(n) : null; // exclude set of globals if (gs != null) { if (iconInstExcludeGlobals == null) { iconInstExcludeGlobals = new IdentityHashMap<IconInst, Set<Global>>(); } iconInstExcludeGlobals.put(iconInst, gs); } assert iconInst.numExtendedExports == schemEq.equivPortsN.length; mapOffset += iconInst.numExtendedExports * n.name.busWidth(); } netNamesOffset = mapOffset; if (DEBUG) { System.out.println("netNamesOffset=" + netNamesOffset); } }
void calcDrawnWidths() { Arrays.fill(drawnNames, null); Arrays.fill(drawnWidths, -1); for (int i = 0; i < numExports; i++) { int drawn = drawns[i]; Name name = exports.get(i).name; int newWidth = name.busWidth(); int oldWidth = drawnWidths[drawn]; if (oldWidth < 0) { drawnNames[drawn] = name; drawnWidths[drawn] = newWidth; continue; } if (oldWidth != newWidth) { reportDrawnWidthError( /*cell.getPort(i), null,*/ drawnNames[drawn].toString(), name.toString()); if (oldWidth < newWidth) { drawnNames[drawn] = name; drawnWidths[drawn] = newWidth; } } } for (int arcIndex = 0; arcIndex < numArcs; arcIndex++) { ImmutableArcInst a = arcs.get(arcIndex); int drawn = drawns[arcsOffset + arcIndex]; if (drawn < 0) { continue; } Name name = a.name; if (name.isTempname()) { continue; } int newWidth = name.busWidth(); int oldWidth = drawnWidths[drawn]; if (oldWidth < 0) { drawnNames[drawn] = name; drawnWidths[drawn] = newWidth; continue; } if (oldWidth != newWidth) { reportDrawnWidthError(/*null, ai,*/ drawnNames[drawn].toString(), name.toString()); if (oldWidth < newWidth) { drawnNames[drawn] = name; drawnWidths[drawn] = newWidth; } } } for (int arcIndex = 0; arcIndex < numArcs; arcIndex++) { int drawn = drawns[arcsOffset + arcIndex]; if (drawn < 0) { continue; } ImmutableArcInst a = arcs.get(arcIndex); Name name = a.name; if (!name.isTempname()) { continue; } int oldWidth = drawnWidths[drawn]; if (oldWidth < 0) { drawnNames[drawn] = name; if (a.protoId != busArc.getId()) { drawnWidths[drawn] = 1; } } } for (int i = 0; i < numNodes; i++) { ImmutableNodeInst n = nodes.get(i); // NodeProto np = ni.getProto(); if (n.protoId instanceof PrimitiveNodeId) { PrimitiveNode pn = techPool.getPrimitiveNode((PrimitiveNodeId) n.protoId); if (pn.getFunction().isPin()) { continue; } if (pn == Schematics.tech().offpageNode) { continue; } } int numPortInsts = getNumPorts(n.protoId); for (int j = 0; j < numPortInsts; j++) { PortInst pi = new PortInst(n.nodeId, getPortIdByIndex(n.protoId, j)); int drawn = drawns[pi.getPortInstOffset()]; if (drawn < 0) { continue; } int oldWidth = drawnWidths[drawn]; int newWidth = 1; if (n.protoId instanceof CellId) { CellBackup subCell = snapshot.getCell((CellId) n.protoId); CellId subCellId = subCell.cellRevision.d.cellId; if (subCellId.isIcon() || subCellId.isSchematic()) { int arraySize = subCellId.isIcon() ? n.name.busWidth() : 1; int portWidth = subCell.cellRevision.exports.get(j).name.busWidth(); if (oldWidth == portWidth) { continue; } newWidth = arraySize * portWidth; } } if (oldWidth < 0) { drawnWidths[drawn] = newWidth; continue; } if (oldWidth != newWidth) { String msg = "Network: Schematic " + cellId + " has net <" + drawnNames[drawn] + "> with width conflict in connection " + pi.n.name + " " + pi.portId; System.out.println(msg); // networkManager.pushHighlight(pi); // networkManager.logError(msg, NetworkTool.errorSortNetworks); } } } for (int i = 0; i < drawnWidths.length; i++) { if (drawnWidths[i] < 1) { drawnWidths[i] = 1; } if (DEBUG) { System.out.println( "Drawn " + i + " " + (drawnNames[i] != null ? drawnNames[i].toString() : "") + " has width " + drawnWidths[i]); } } }
ImmutableNetSchem(Snapshot snapshot, CellId cellId) { assert cellId.isIcon() || cellId.isSchematic(); this.snapshot = snapshot; this.cellId = cellId; // System.out.println("begin ImmutableNetSchem " + cellId); techPool = snapshot.techPool; schem = techPool.getSchematics(); busPinPortId = schem != null ? schem.busPinNode.getPort(0).getId() : null; busArc = schem != null ? schem.bus_arc : null; cellTree = snapshot.getCellTree(cellId); cellBackup = cellTree.top; m = cellBackup.getMemoization(); cellRevision = cellBackup.cellRevision; exports = cellRevision.exports; nodes = cellRevision.nodes; arcs = cellRevision.arcs; numExports = cellRevision.exports.size(); numNodes = cellRevision.nodes.size(); numArcs = cellRevision.arcs.size(); CellId implementationCellId = cellId; if (cellId.isIcon()) { CellId mainSchemId = snapshot.getMainSchematics(cellId); if (mainSchemId != null) { getEquivExports(mainSchemId); implementationCellId = mainSchemId; } } this.implementationCellId = implementationCellId; // init connections ni_pi = new int[numNodes]; int offset = numExports; for (int i = 0; i < numNodes; i++) { ImmutableNodeInst n = nodes.get(i); ni_pi[i] = offset; offset += getNumPorts(n.protoId); } arcsOffset = offset; offset += numArcs; headConn = new int[offset]; tailConn = new int[offset]; drawns = new int[offset]; for (int i = numExports; i < arcsOffset; i++) { headConn[i] = i; tailConn[i] = i; } for (int i = 0; i < numExports; i++) { int portOffset = i; ImmutableExport export = exports.get(i); int orig = getPortInstOffset(export.originalNodeId, export.originalPortId); headConn[portOffset] = headConn[orig]; headConn[orig] = portOffset; tailConn[portOffset] = -1; } for (int arcIndex = 0; arcIndex < numArcs; arcIndex++) { ImmutableArcInst a = arcs.get(arcIndex); int arcOffset = arcsOffset + arcIndex; int head = getPortInstOffset(a.headNodeId, a.headPortId); headConn[arcOffset] = headConn[head]; headConn[head] = arcOffset; int tail = getPortInstOffset(a.tailNodeId, a.tailPortId); tailConn[arcOffset] = tailConn[tail]; tailConn[tail] = arcOffset; } makeDrawns(); initNetnames(); portOffsets = new int[numExports + 1]; drawnNames = new Name[numDrawns]; drawnWidths = new int[numDrawns]; drawnOffsets = new int[numDrawns]; calcDrawnWidths(); initNodables(); int mapSize = netNamesOffset + netNames.size(); int[] netMapN = ImmutableNetLayout.initMap(mapSize); localConnections(netMapN); int[] netMapP = netMapN.clone(); int[] netMapA = netMapN.clone(); internalConnections(netMapN, netMapP, netMapA); ImmutableNetLayout.closureMap(netMapN); ImmutableNetLayout.closureMap(netMapP); ImmutableNetLayout.closureMap(netMapA); // updatePortImplementation(); updateInterface(netMapN, netMapP, netMapA); // System.out.println("end ImmutableNetSchem " + cellId); }
private void internalConnections(int[] netMapF, int[] netMapP, int[] netMapA) { for (int k = 0; k < numNodes; k++) { ImmutableNodeInst n = nodes.get(k); int nodeOffset = ni_pi[k]; if (n.protoId instanceof PrimitiveNodeId) { PrimitiveNode.Function fun = getFunction(n); if (fun == PrimitiveNode.Function.RESIST) { ImmutableNetLayout.connectMap( netMapP, drawnOffsets[drawns[nodeOffset]], drawnOffsets[drawns[nodeOffset + 1]]); ImmutableNetLayout.connectMap( netMapA, drawnOffsets[drawns[nodeOffset]], drawnOffsets[drawns[nodeOffset + 1]]); } else if (fun.isComplexResistor()) { ImmutableNetLayout.connectMap( netMapA, drawnOffsets[drawns[nodeOffset]], drawnOffsets[drawns[nodeOffset + 1]]); } continue; } IconInst iconInst = iconInsts[k]; if (iconInst != null) { continue; } CellId subCellId = (CellId) n.protoId; assert !subCellId.isIcon() && !subCellId.isSchematic(); EquivPorts eq = snapshot.getCellTree(subCellId).getEquivPorts(); int[] eqN = eq.getEquivPortsN(); int[] eqP = eq.getEquivPortsP(); int[] eqA = eq.getEquivPortsA(); int numPorts = eq.getNumExports(); assert eqN.length == numPorts && eqP.length == numPorts && eqA.length == numPorts; for (int i = 0; i < numPorts; i++) { int di = drawns[nodeOffset + i]; if (di < 0) { continue; } int jN = eqN[i]; if (i != jN) { int dj = drawns[nodeOffset + jN]; if (dj >= 0) { ImmutableNetLayout.connectMap(netMapF, drawnOffsets[di], drawnOffsets[dj]); } } int jP = eqP[i]; if (i != jP) { int dj = drawns[nodeOffset + jP]; if (dj >= 0) { ImmutableNetLayout.connectMap(netMapP, drawnOffsets[di], drawnOffsets[dj]); } } int jA = eqA[i]; if (i != jA) { int dj = drawns[nodeOffset + jA]; if (dj >= 0) { ImmutableNetLayout.connectMap(netMapA, drawnOffsets[di], drawnOffsets[dj]); } } } } for (IconInst iconInst : iconInsts) { if (iconInst == null || iconInst.iconOfParent) { continue; } for (int k = 0; k < iconInst.nodeInst.name.busWidth(); k++) { EquivalentSchematicExports eq = iconInst.eq.implementation; assert eq.implementation == eq; int[] eqN = eq.getEquivPortsN(); int[] eqP = eq.getEquivPortsP(); int[] eqA = eq.getEquivPortsA(); int nodableOffset = iconInst.netMapOffset + k * iconInst.numExtendedExports; for (int i = 0; i < eqN.length; i++) { int io = nodableOffset + i; int jF = eqN[i]; if (i != jF) { ImmutableNetLayout.connectMap(netMapF, io, nodableOffset + jF); } int jP = eqP[i]; if (i != jP) { ImmutableNetLayout.connectMap(netMapP, io, nodableOffset + jP); } int jA = eqA[i]; if (i != jA) { ImmutableNetLayout.connectMap(netMapA, io, nodableOffset + jA); } } } } }