package com.sun.electric.tool.generator.flag.scan; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import com.sun.electric.database.topology.NodeInst; import com.sun.electric.database.topology.PortInst; import com.sun.electric.tool.generator.flag.FlagConfig; import com.sun.electric.tool.generator.flag.Utils; import com.sun.electric.tool.generator.flag.router.Router; import com.sun.electric.tool.generator.layout.LayoutLib; import com.sun.electric.tool.generator.layout.TechType; public class Scan { private final List<ScanChain> chains = new ArrayList<ScanChain>(); private final Set<String> SCAN_PORT_NAME_SET = new HashSet<String>(); private final FlagConfig config; private static void prln(String s) {Utils.prln(s);} private static void error(boolean cond, String msg) {Utils.error(cond, msg);} private TechType tech() {return config.techTypeEnum.getTechType();} private boolean vertOrHorizAligned(PortInst p1, PortInst p2) { double x1 = p1.getCenter().getX(); double y1 = p1.getCenter().getY(); double x2 = p2.getCenter().getX(); double y2 = p2.getCenter().getY(); return x1==x2 || y1==y2; } private void connectScanPorts(NodeInst niOut, NodeInst niIn, List<String> outPortNm, List<String> inPortNm, Router router) { for (int i=0; i<outPortNm.size(); i++) { PortInst piOut = niOut.findPortInst(outPortNm.get(i)); PortInst piIn = niIn.findPortInst(inPortNm.get(i)); if (!vertOrHorizAligned(piOut, piIn)) { prln("Can't connect scan ports with horizontal or vertical wire:"); prln(" "+piOut+" "+piIn); continue; } LayoutLib.newArcInst(tech().m3(), config.signalWid, router.raiseToM3(piOut), router.raiseToM3(piIn)); //prln("Scan chain connect: "+piOut+" to "+piIn); } } public Scan(List<ScanChain> chains, FlagConfig config) { this.chains.addAll(chains); this.config = config; for (ScanChain chain : chains) { SCAN_PORT_NAME_SET.addAll(chain.getInputNames()); SCAN_PORT_NAME_SET.addAll(chain.getOutputNames()); SCAN_PORT_NAME_SET.addAll(chain.getFeedthroughNames()); } } public void stitchScanChains(List<NodeInst> layInsts, Router router) { for (ScanChain chain : chains) { NodeInst prevOut = null; List<String> prevOutPorts = null; for (NodeInst ni : layInsts) { List<String> inOrFeed = chain.getInputOrFeedNames(ni); if (inOrFeed!=null && prevOut!=null) { connectScanPorts(prevOut, ni, prevOutPorts, inOrFeed, router); prevOut = null; } List<String> newPrevOutPorts = chain.getOutputOrFeedNames(ni); if (newPrevOutPorts!=null) { if (prevOut!=null) { prln("Error: Dangling scan chain output. "); prln(" NodeInst: "+prevOut.getName()); prln(" Port: "+prevOutPorts.get(0)); } prevOutPorts = newPrevOutPorts; prevOut = ni; } } } } public boolean isScan(PortInst pi) { String nm = pi.getPortProto().getName(); return SCAN_PORT_NAME_SET.contains(nm); } }