📄 libtotech.java
字号:
{ error.markError(null, np, "Need 2 gate (poly) and 2 gated (active) ports on field-effect transistor"); return null; } // also make sure that dif1Port is positive and dif2Port is negative double x1Pos = (nIn.nodePortDetails[dif1Port].values[0].getX().getMultiplier() * nIn.xSize + nIn.nodePortDetails[dif1Port].values[0].getX().getAdder() + nIn.nodePortDetails[dif1Port].values[1].getX().getMultiplier() * nIn.xSize + nIn.nodePortDetails[dif1Port].values[1].getX().getAdder()) / 2; double x2Pos = (nIn.nodePortDetails[dif2Port].values[0].getX().getMultiplier() * nIn.xSize + nIn.nodePortDetails[dif2Port].values[0].getX().getAdder() + nIn.nodePortDetails[dif2Port].values[1].getX().getMultiplier() * nIn.xSize + nIn.nodePortDetails[dif2Port].values[1].getX().getAdder()) / 2; double y1Pos = (nIn.nodePortDetails[dif1Port].values[0].getY().getMultiplier() * nIn.ySize + nIn.nodePortDetails[dif1Port].values[0].getY().getAdder() + nIn.nodePortDetails[dif1Port].values[1].getY().getMultiplier() * nIn.ySize + nIn.nodePortDetails[dif1Port].values[1].getY().getAdder()) / 2; double y2Pos = (nIn.nodePortDetails[dif2Port].values[0].getY().getMultiplier() * nIn.ySize + nIn.nodePortDetails[dif2Port].values[0].getY().getAdder() + nIn.nodePortDetails[dif2Port].values[1].getY().getMultiplier() * nIn.ySize + nIn.nodePortDetails[dif2Port].values[1].getY().getAdder()) / 2; if (Math.abs(x1Pos-x2Pos) > Math.abs(y1Pos-y2Pos)) { if (x1Pos < x2Pos) { int k = dif1Port; dif1Port = dif2Port; dif2Port = k; } } else { if (y1Pos < y2Pos) { int k = dif1Port; dif1Port = dif2Port; dif2Port = k; } } // also make sure that pol1Port is negative and pol2Port is positive x1Pos = (nIn.nodePortDetails[pol1Port].values[0].getX().getMultiplier() * nIn.xSize + nIn.nodePortDetails[pol1Port].values[0].getX().getAdder() + nIn.nodePortDetails[pol1Port].values[1].getX().getMultiplier() * nIn.xSize + nIn.nodePortDetails[pol1Port].values[1].getX().getAdder()) / 2; x2Pos = (nIn.nodePortDetails[pol2Port].values[0].getX().getMultiplier() * nIn.xSize + nIn.nodePortDetails[pol2Port].values[0].getX().getAdder() + nIn.nodePortDetails[pol2Port].values[1].getX().getMultiplier() * nIn.xSize + nIn.nodePortDetails[pol2Port].values[1].getX().getAdder()) / 2; y1Pos = (nIn.nodePortDetails[pol1Port].values[0].getY().getMultiplier() * nIn.ySize + nIn.nodePortDetails[pol1Port].values[0].getY().getAdder() + nIn.nodePortDetails[pol1Port].values[1].getY().getMultiplier() * nIn.ySize + nIn.nodePortDetails[pol1Port].values[1].getY().getAdder()) / 2; y2Pos = (nIn.nodePortDetails[pol2Port].values[0].getY().getMultiplier() * nIn.ySize + nIn.nodePortDetails[pol2Port].values[0].getY().getAdder() + nIn.nodePortDetails[pol2Port].values[1].getY().getMultiplier() * nIn.ySize + nIn.nodePortDetails[pol2Port].values[1].getY().getAdder()) / 2; if (Math.abs(x1Pos-x2Pos) > Math.abs(y1Pos-y2Pos)) { if (x1Pos > x2Pos) { int k = pol1Port; pol1Port = pol2Port; pol2Port = k; } } else { if (y1Pos > y2Pos) { int k = pol1Port; pol1Port = pol2Port; pol2Port = k; } } // gather extra ports that go at the end List<NodeInfo.PortDetails> extras = new ArrayList<NodeInfo.PortDetails>(); for(int j=0; j<ports.size(); j++) { if (j != pol1Port && j != dif1Port && j != pol2Port && j != dif2Port) extras.add(ports.get(j)); } // rearrange the ports NodeInfo.PortDetails port0 = nIn.nodePortDetails[pol1Port]; NodeInfo.PortDetails port1 = nIn.nodePortDetails[dif1Port]; NodeInfo.PortDetails port2 = nIn.nodePortDetails[pol2Port]; NodeInfo.PortDetails port3 = nIn.nodePortDetails[dif2Port]; nIn.nodePortDetails[pol1Port=0] = port0; nIn.nodePortDetails[dif1Port=1] = port1; nIn.nodePortDetails[pol2Port=2] = port2; nIn.nodePortDetails[dif2Port=3] = port3; for(int j=0; j<extras.size(); j++) nIn.nodePortDetails[j+4] = extras.get(j); // make sure implant layers are not connected to ports for(int k=0; k<nIn.nodeLayers.length; k++) { NodeInfo.LayerDetails nld = nIn.nodeLayers[k]; if (nld.layer.fun.isSubstrate()) nld.portIndex = -1; } } if (nIn.serp) { // finish up serpentine transistors nIn.specialType = PrimitiveNode.SERPTRANS; // determine port numbers for serpentine transistors int polIndex = -1, difIndex = -1; for(int k=0; k<nIn.nodeLayers.length; k++) { NodeInfo.LayerDetails nld = nIn.nodeLayers[k]; if (nld.layer.fun.isPoly()) { polIndex = k; } else if (nld.layer.fun.isDiff()) { if (difIndex >= 0) { // figure out which layer is the basic active layer int funExtraOld = nIn.nodeLayers[difIndex].layer.funExtra; int funExtraNew = nld.layer.funExtra; if (funExtraOld == funExtraNew) continue; if (funExtraOld == 0) continue; } difIndex = k; } } if (difIndex < 0 || polIndex < 0) { error.markError(null, np, "No diffusion and polysilicon layers in serpentine transistor"); return null; } // find width and extension from comparison to poly layer Sample polNs = nIn.nodeLayers[polIndex].ns; Rectangle2D polNodeBounds = polNs.node.getBounds(); Sample difNs = nIn.nodeLayers[difIndex].ns; Rectangle2D difNodeBounds = difNs.node.getBounds(); for(int k=0; k<nIn.nodeLayers.length; k++) { NodeInfo.LayerDetails nld = nIn.nodeLayers[k]; Sample ns = nld.ns; Rectangle2D nodeBounds = ns.node.getBounds(); if (polNodeBounds.getWidth() > polNodeBounds.getHeight()) { // horizontal layer nld.lWidth = nodeBounds.getMaxY() - (ns.parent.ly + ns.parent.hy)/2; nld.rWidth = (ns.parent.ly + ns.parent.hy)/2 - nodeBounds.getMinY(); nld.extendT = difNodeBounds.getMinX() - nodeBounds.getMinX(); } else { // vertical layer nld.lWidth = nodeBounds.getMaxX() - (ns.parent.lx + ns.parent.hx)/2; nld.rWidth = (ns.parent.lx + ns.parent.hx)/2 - nodeBounds.getMinX(); nld.extendT = difNodeBounds.getMinY() - nodeBounds.getMinY(); } nld.extendB = nld.extendT; } // add in electrical layers for diffusion NodeInfo.LayerDetails [] addedLayers = new NodeInfo.LayerDetails[nIn.nodeLayers.length+2]; for(int k=0; k<nIn.nodeLayers.length; k++) addedLayers[k] = nIn.nodeLayers[k]; NodeInfo.LayerDetails diff1 = nIn.nodeLayers[difIndex].duplicate(); NodeInfo.LayerDetails diff2 = nIn.nodeLayers[difIndex].duplicate(); addedLayers[nIn.nodeLayers.length] = diff1; addedLayers[nIn.nodeLayers.length+1] = diff2; nIn.nodeLayers = addedLayers; diff1.inLayers = diff2.inLayers = false; nIn.nodeLayers[difIndex].inElectricalLayers = false; diff1.portIndex = dif1Port; diff2.portIndex = dif2Port; // compute port extension factors nIn.specialValues = new double[6]; int layerCount = 0; for(Sample ns : firstEx.samples) { if (ns.values != null && ns.layer != Generic.tech().portNode && ns.layer != Generic.tech().cellCenterNode && ns.layer != null) layerCount++; } nIn.specialValues[0] = layerCount+1; if (nIn.nodePortDetails[dif1Port].values[0].getX().getAdder() > nIn.nodePortDetails[dif1Port].values[0].getY().getAdder()) { // vertical diffusion layer: determine polysilicon width nIn.specialValues[3] = (nIn.ySize * nIn.nodeLayers[polIndex].values[1].getY().getMultiplier() + nIn.nodeLayers[polIndex].values[1].getY().getAdder()) - (nIn.ySize * nIn.nodeLayers[polIndex].values[0].getY().getMultiplier() + nIn.nodeLayers[polIndex].values[0].getY().getAdder()); // determine diffusion port rule nIn.specialValues[1] = (nIn.xSize * nIn.nodePortDetails[dif1Port].values[0].getX().getMultiplier() + nIn.nodePortDetails[dif1Port].values[0].getX().getAdder()) - (nIn.xSize * nIn.nodeLayers[difIndex].values[0].getX().getMultiplier() + nIn.nodeLayers[difIndex].values[0].getX().getAdder()); nIn.specialValues[2] = (nIn.ySize * nIn.nodePortDetails[dif1Port].values[0].getY().getMultiplier() + nIn.nodePortDetails[dif1Port].values[0].getY().getAdder()) - (nIn.ySize * nIn.nodeLayers[polIndex].values[1].getY().getMultiplier() + nIn.nodeLayers[polIndex].values[1].getY().getAdder()); // determine polysilicon port rule nIn.specialValues[4] = (nIn.ySize * nIn.nodePortDetails[pol1Port].values[0].getY().getMultiplier() + nIn.nodePortDetails[pol1Port].values[0].getY().getAdder()) - (nIn.ySize * nIn.nodeLayers[polIndex].values[0].getY().getMultiplier() + nIn.nodeLayers[polIndex].values[0].getY().getAdder()); nIn.specialValues[5] = (nIn.xSize * nIn.nodeLayers[difIndex].values[0].getX().getMultiplier() + nIn.nodeLayers[difIndex].values[0].getX().getAdder()) - (nIn.xSize * nIn.nodePortDetails[pol1Port].values[1].getX().getMultiplier() + nIn.nodePortDetails[pol1Port].values[1].getX().getAdder()); // setup electrical layers for diffusion diff1.values[0].getY().setMultiplier(0); diff1.values[0].getY().setAdder(0); diff1.rWidth = 0; diff2.values[1].getY().setMultiplier(0); diff2.values[1].getY().setAdder(0); diff2.lWidth = 0; } else { // horizontal diffusion layer: determine polysilicon width nIn.specialValues[3] = (nIn.xSize * nIn.nodeLayers[polIndex].values[1].getX().getMultiplier() + nIn.nodeLayers[polIndex].values[1].getX().getAdder()) - (nIn.xSize * nIn.nodeLayers[polIndex].values[0].getX().getMultiplier() + nIn.nodeLayers[polIndex].values[0].getX().getAdder()); // determine diffusion port rule nIn.specialValues[1] = (nIn.ySize * nIn.nodePortDetails[dif1Port].values[0].getY().getMultiplier() + nIn.nodePortDetails[dif1Port].values[0].getY().getAdder()) - (nIn.ySize * nIn.nodeLayers[difIndex].values[0].getY().getMultiplier() + nIn.nodeLayers[difIndex].values[0].getY().getAdder()); nIn.specialValues[2] = (nIn.xSize * nIn.nodeLayers[polIndex].values[0].getX().getMultiplier() + nIn.nodeLayers[polIndex].values[0].getX().getAdder()) - (nIn.xSize * nIn.nodePortDetails[dif1Port].values[1].getX().getMultiplier() + nIn.nodePortDetails[dif1Port].values[1].getX().getAdder()); // determine polysilicon port rule nIn.specialValues[4] = (nIn.xSize * nIn.nodePortDetails[pol1Port].values[0].getX().getMultiplier() + nIn.nodePortDetails[pol1Port].values[0].getX().getAdder()) - (nIn.xSize * nIn.nodeLayers[polIndex].values[0].getX().getMultiplier() + nIn.nodeLayers[polIndex].values[0].getX().getAdder()); nIn.specialValues[5] = (nIn.ySize * nIn.nodeLayers[difIndex].values[0].getY().getMultiplier() + nIn.nodeLayers[difIndex].values[0].getY().getAdder()) - (nIn.ySize * nIn.nodePortDetails[pol1Port].values[1].getY().getMultiplier() + nIn.nodePortDetails[pol1Port].values[1].getY().getAdder()); // setup electrical layers for diffusion diff1.values[0].getX().setMultiplier(0); diff1.values[0].getX().setAdder(0); diff1.rWidth = 0; diff2.values[1].getX().setMultiplier(0); diff2.values[1].getX().setAdder(0); diff2.lWidth = 0; } } // extract width offset information from highlight box double lX = 0, hX = 0, lY = 0, hY = 0; boolean found = false; for(Sample ns : firstEx.samples) { if (ns.layer != null) continue; found = true; if (ns.values != null) { boolean err = false; if (ns.values[0].getX().getMultiplier() == -0.5) // left edge offset { lX = ns.values[0].getX().getAdder(); } else if (ns.values[0].getX().getMultiplier() == 0.5) { lX = nIn.xSize + ns.values[0].getX().getAdder(); } else err = true; if (ns.values[0].getY().getMultiplier() == -0.5) // bottom edge offset { lY = ns.values[0].getY().getAdder(); } else if (ns.values[0].getY().getMultiplier() == 0.5) { lY = nIn.ySize + ns.values[0].getY().getAdder();; } else err = true; if (ns.values[1].getX().getMultiplier() == 0.5) // right edge offset { hX = -ns.values[1].getX().getAdder(); } else if (ns.values[1].getX().getMultiplier() == -0.5) { hX = nIn.xSize - ns.values[1].getX().getAdder(); } else err = true; if (ns.values[1].getY().getMultiplier() == 0.5) // top edge offset { hY = -ns.values[1].getY().getAdder(); } else if (ns.values[1].getY().getMultiplier() == -0.5) { hY = nIn.ySize - ns.values[1].getY().getAdder(); } else err = true; if (err) { error.markError(ns.node, np, "Highlighting cannot scale from center"); return null; } } else { error.markError(ns.node, np, "No rule found for highlight"); return null; } } if (!found) { error.markError(null, np, "No highlight found"); return null; } if (lX != 0 || hX != 0 || lY != 0 || hY != 0) { nList[nodeIndex].so = new SizeOffset(lX, hX, lY, hY); }// // get grab point information// for(ns = neList.firstSample; ns != NOSAMPLE; ns = ns.nextSample)// if (ns.layer == Generic.tech.cellCenterNode) break;// if (ns != NOSAMPLE)// {// us_tecnode_grab[us_tecnode_grabcount++] = nodeindex+1;// us_tecnode_grab[us_tecnode_grabcount++] = (ns.node.geom.lowx +// ns.node.geom.highx - neList.lx - neList.hx)/2 *// el_curlib.lambda[tech.techindex] / lambda;// us_tecnode_grab[us_tecnode_grabcount++] = (ns.node.geom.lowy +// ns.node.geom.highy - neList.ly - neList.hy)/2 *// el_curlib.lambda[tech.techindex] / lambda;// us_tecflags |= HASGRAB;// } // advance the fill pointer nodeIndex++; } return nList; } private NodeInfo.LayerDetails [] makePrimitiveNodeLayers(List<Example> neList, Cell np, LayerInfo [] lis) { // if there is only one example: make sample scale with edge Example firstEx = neList.get(0); if (neList.size() <= 1) { return makeNodeScaledUniformly(neList, np, lis); } // count the number of real layers in the node int count = 0; for(Sample ns : firstEx.samples) { if (ns.layer != null && ns.layer != Generic.tech().portNode) count++; } NodeInfo.LayerDetails [] nodeLayers = new NodeInfo.LayerDetails[count]; count = 0; // look at every sample "ns" in the main example "neList" for(Sample ns : firstEx.samples) { // ignore grab point specification
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -