📄 fpga.java
字号:
numSegs += fn.netList[i].segFrom.length; } break; } int total = 1 + numPips + numSegs; if ((internalDisplay&TEXTDISPLAY) != 0) { total++; if (wnd != null) total += ni.numDisplayableVariables(true); } // construct the polygon array Poly [] polys = new Poly[total]; // add the basic box layer double xCenter = ni.getTrueCenterX(); double yCenter = ni.getTrueCenterY(); double xSize = ni.getXSize(); double ySize = ni.getYSize(); Point2D [] pointList = Poly.makePoints(xCenter - xSize/2, xCenter + xSize/2, yCenter - ySize/2, yCenter + ySize/2); polys[0] = new Poly(pointList); polys[0].setStyle(fn.getLayers()[0].getStyle()); polys[0].setLayer(componentLayer); int fillPos = 1; // add in the pips for(int i=0; i<fn.numPips(); i++) { if ((fn.pipList[i].pipActive&ACTIVESAVE) == 0) continue; double x = xCenter + fn.pipList[i].posX; double y = yCenter + fn.pipList[i].posY; polys[fillPos] = new Poly(Poly.makePoints(x-1, x+1, y-1, y+1)); polys[fillPos].setStyle(Poly.Type.FILLED); polys[fillPos].setLayer(pipLayer); fillPos++; } // add in the network segments for(int i=0; i<fn.numNets(); i++) { if ((fn.netList[i].segActive&ACTIVESAVE) == 0) continue; for(int j=0; j<fn.netList[i].segFrom.length; j++) { double fX = xCenter + fn.netList[i].segFrom[j].getX(); double fY = yCenter + fn.netList[i].segFrom[j].getY(); double tX = xCenter + fn.netList[i].segTo[j].getX(); double tY = yCenter + fn.netList[i].segTo[j].getY(); Point2D [] line = new Point2D[2]; line[0] = new Point2D.Double(fX, fY); line[1] = new Point2D.Double(tX, tY); polys[fillPos] = new Poly(line); polys[fillPos].setStyle(Poly.Type.OPENED); polys[fillPos].setLayer(wireLayer); fillPos++; } } // add the primitive name if requested if ((internalDisplay&TEXTDISPLAY) != 0) { polys[fillPos] = new Poly(pointList); polys[fillPos].setStyle(Poly.Type.TEXTBOX); polys[fillPos].setLayer(componentLayer); polys[fillPos].setString(fn.getName()); TextDescriptor td = TextDescriptor.EMPTY.withRelSize(3); polys[fillPos].setTextDescriptor(td); fillPos++; // add in displayable variables if (wnd != null) { Rectangle2D rect = ni.getUntransformedBounds(); ni.addDisplayableVariables(rect, polys, fillPos, wnd, true); } } return polys; } return super.getShapeOfNode(ni, electrical, reasonable, primLayers, layerOverride); } /** * Fill the polygons that describe arc "a". * @param b AbstractShapeBuilder to fill polygons. * @param a the ImmutableArcInst that is being described. */ @Override protected void getShapeOfArc(AbstractShapeBuilder b, ImmutableArcInst a) { super.getShapeOfArc(b, a); } /** * Tells if arc can be drawn by simplified algorithm * FPGA arcs are not easy * @param a arc to test * @param explain if true then print explanation why arc is not easy * @return false */ @Override public boolean isEasyShape(ImmutableArcInst a, boolean explain) { return false; } /******************** TECHNOLOGY INTERFACE SUPPORT ********************/ private boolean arcEndActive(ArcInst ai, int j, VarContext curContext) { // examine end PortInst pi = ai.getPortInst(j); NodeInst ni = pi.getNodeInst(); PortProto pp = pi.getPortProto(); NodeProto np = ni.getProto(); if (ni.isCellInstance()) { // follow down into cell VarContext down = curContext.push(ni); NodeInst subni = ((Export)pp).getOriginalPort().getNodeInst(); for(Iterator<Connection> it = subni.getConnections(); it.hasNext(); ) { Connection nextCon = it.next(); ArcInst oAi = nextCon.getArc(); int newEnd = 0; if (oAi.getPortInst(0).getNodeInst() == subni) newEnd = 1; if (arcEndActive(oAi, newEnd, down)) return true; } return false; } // primitive: see if it is one of ours if (np instanceof FPGANode) { FPGANode fn = (FPGANode)np; reEvaluatePips(ni, fn, curContext); for(int i = 0; i < fn.numPorts(); i++) { if (fn.portList[i].pp != pp) continue; int index = fn.portList[i].con; if (index >= 0 && fn.netList != null) { if ((fn.netList[index].segActive&ACTIVEPART) != 0) return true; } break; } } // propagate Cell parent = ai.getParent(); if (parent != null) { Netlist nl = parent.acquireUserNetlist(); Network net = nl.getNetwork(ni, pp, 0); if (net != null) { for(Iterator<Connection> it = ni.getConnections(); it.hasNext(); ) { Connection nextCon = it.next(); ArcInst oAi = nextCon.getArc(); if (oAi == ai) continue; Network oNet = nl.getNetwork(oAi, 0); if (oNet != net) continue; int newEnd = 1 - nextCon.getEndIndex(); if (arcEndActive(oAi, newEnd, curContext)) return true; } VarContext higher = curContext.pop(); if (higher != null && higher.getNodable() != null) { NodeInst oNi = (NodeInst)higher.getNodable(); for (Iterator<Export> it = ni.getExports(); it.hasNext(); ) { Export opp = it.next(); Network oNet = nl.getNetwork(opp, 0); if (oNet != net) continue; for(Iterator<Connection> uIt = oNi.getConnections(); uIt.hasNext(); ) { Connection nextCon = uIt.next(); ArcInst oAi = nextCon.getArc(); if (nextCon.getPortInst().getPortProto() != opp) continue; int newEnd = 1 - nextCon.getEndIndex(); if (arcEndActive(oAi, newEnd, higher)) return true; } } } } } return false; } /** * Method to reevaluate primitive node "ni" (which is associated with internal * structure "fn"). Finds programming of pips and sets pip and net activity. */ private void reEvaluatePips(NodeInst ni, FPGANode fn, VarContext context) { // primitives with no pips or nets need no evaluation if (fn.numNets() == 0 && fn.numPips() == 0) return; // reevaluate: presume all nets and pips are inactive for(int i=0; i<fn.numNets(); i++) fn.netList[i].segActive &= ~ACTIVEPART; for(int i=0; i<fn.numPips(); i++) fn.pipList[i].pipActive &= ~ACTIVEPART; // look for pip programming findVariableObjects(fn, ni, ACTIVEPIPS_KEY, true, context); // set nets active where they touch active pips for(int i=0; i<fn.numPips(); i++) { FPGAPip fPip = fn.pipList[i]; if ((fPip.pipActive&ACTIVEPART) == 0) continue; if (fPip.con1 > 0) fn.netList[fPip.con1].segActive |= ACTIVEPART; if (fPip.con2 > 0) fn.netList[fPip.con2].segActive |= ACTIVEPART; } } /** * Method to examine primitive node "ni" and return true if the repeater is active. */ private boolean repeaterActive(NodeInst ni) { repeaterName = ni.getName(); repeaterActive = false; findVariableObjects(null, ni, ACTIVEREPEATERS_KEY, false, null); return repeaterActive; } Nodable [] path = new Nodable[100]; private void findVariableObjects(FPGANode fn, NodeInst ni, Variable.Key varKey, boolean setPips, VarContext context) { // search hierarchical path int depth = 0; path[depth++] = ni; while (context != null) { Nodable niClimb = context.getNodable(); if (niClimb == null) break; path[depth++] = niClimb; context = context.pop(); } // look for programming variables on the nodes for(int c=0; c<depth; c++) { Nodable niClimb = path[c]; Variable var = niClimb.getVar(varKey); if (var == null) continue; // found pip settings: evaluate them String pt = (String)var.getObject(); String [] pipNames = pt.split(" "); for(int i=0; i<pipNames.length; i++) { String start = pipNames[i]; if (start.length() == 0) continue; // find pip name in "start" String [] pipParts = start.split("\\."); if (pipParts.length == 0 || pipParts.length > depth) continue; boolean pathGood = true; for(int j=0; j<pipParts.length-1; j++) { if (!pipParts[j].equalsIgnoreCase(path[depth-2-j].getName())) { pathGood = false; break; } } if (pathGood) { String lastPart = pipParts[pipParts.length-1]; if (setPips) { for(int k=0; k<fn.numPips(); k++) if (fn.pipList[k].name.equalsIgnoreCase(lastPart)) { fn.pipList[k].pipActive |= ACTIVEPART; } } else { if (repeaterName.equalsIgnoreCase(lastPart)) repeaterActive = true; } } } break; } } /******************** TECHNOLOGY CONTROL ********************/ /** * Method to read an architecture file and customize the FPGA technology. * Prompts for a file and reads it. * @param placeAndWire true to build the primitives and structures; false to simply build the primitives. */ public void readArchitectureFile(boolean placeAndWire) { if (defined) { System.out.println("This technology already has primitives defined"); return; } // get architecture file String fileName = OpenFile.chooseInputFile(FileType.FPGA, null); if (fileName == null) return; // turn the tree into primitives new BuildTechnology(this, fileName, placeAndWire); } /** * Method to set the wire display level. * @param level 0 to show no wires; 1 to show active wires; 2 to show all wires. */ public void setWireDisplay(int level) { switch (level) { case 0: // no wires internalDisplay = (internalDisplay & ~DISPLAYLEVEL) | NOPRIMDISPLAY; break; case 1: // active wires internalDisplay = (internalDisplay & ~DISPLAYLEVEL) | ACTIVEPRIMDISPLAY; break; case 2: // all wires internalDisplay = (internalDisplay & ~DISPLAYLEVEL) | FULLPRIMDISPLAY; break; } UserInterface ui = Job.getUserInterface(); ui.repaintAllWindows(); } /** * Method to set the text display level. * @param show true to see text, false to hide text. */ public void setTextDisplay(boolean show) { if (show) internalDisplay |= TEXTDISPLAY; else internalDisplay &= ~TEXTDISPLAY; UserInterface ui = Job.getUserInterface(); ui.repaintAllWindows(); } /** * Method to program the currently selected PIPs. */ public void programPips() { UserInterface ui = Job.getUserInterface(); EditWindow_ wnd = ui.getCurrentEditWindow_(); if (wnd == null) return; ElectricObject eObj = wnd.getOneElectricObject(NodeInst.class); if (eObj == null) return; NodeInst ni = (NodeInst)eObj; String pips = ""; Variable var = ni.getVar(ACTIVEPIPS_KEY); if (var != null) pips = (String)var.getObject(); String newPips = PromptAt.showPromptAt(wnd, ni, "Edit Pips", "Pips on this node:", pips); if (newPips == null) return; new SetPips(ni, newPips); } /** * This class sets pip programming on a node. */ private static class SetPips extends Job { private NodeInst ni; private String newPips; private SetPips(NodeInst ni, String newPips) { super("Program Pips", User.getUserTool(), Job.Type.CHANGE, null, null, Job.Priority.USER); this.ni = ni; this.newPips = newPips; startJob(); } public boolean doIt() throws JobException { ni.newVar(ACTIVEPIPS_KEY, newPips); return true; } public void terminateOK() { UserInterface ui = Job.getUserInterface(); ui.repaintAllWindows(); } } /** * This class implement the command to build an FPGA technology. */ private static class BuildTechnology extends Job { private FPGA tech; private String fileName; private boolean placeAndWire; private Cell topCell; private BuildTechnology(FPGA tech, String fileName, boolean placeAndWire) { super("Build FPGA Technology", User.getUserTool(), Job.Type.CHANGE, null, null, Job.Priority.USER); this.tech = tech; this.fileName = fileName; this.placeAndWire = placeAndWire; startJob(); } public boolean doIt() throws JobException { // read the file LispTree lt = tech.readFile(fileName); if (lt == null) throw new JobException("Error reading file"); int total = tech.makePrimitives(lt); System.out.println("Created " + total + " primitives"); // place and wire the primitives if (placeAndWire) { topCell = tech.placePrimitives(lt); fieldVariableChanged("topCell"); } return true;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -