/* -*- tab-width: 4 -*- * * Electric(tm) VLSI Design System * * File: DetailedRouter.java * Written by: Alexander Herzog, Martin Fietz (Team 4) * * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. * * 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.routing.experimentalLeeMoore2; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import com.sun.electric.tool.routing.RoutingFrame.RoutingLayer; import com.sun.electric.tool.routing.experimentalLeeMoore2.GlobalRouterV3.RegionToRoute; import com.sun.electric.tool.routing.experimentalLeeMoore2.RoutingFrameLeeMoore.Coordinate; public final class DetailedRouter { private final int numThreads; private long timeout; private RegionToRoute[] regions; private DetailedRoutingSolution solutions; private List<Integer> unrouted; private List<DetailedRouterWorker> workers; public DetailedRouter(int numThreads, RoutingLayer[] metalLayers, RegionToRoute[] regions, double tileSize, boolean debug ) { this.numThreads = numThreads; unrouted = new ArrayList<Integer>(); workers = new ArrayList<DetailedRouterWorker>(regions.length); solutions = new DetailedRoutingSolution(); for (int i = 0; i < regions.length; i++) { DetailedRouterWorker d = new DetailedRouterWorker(regions[i], metalLayers, tileSize); if( debug ) { d.enableOutput(); } workers.add(d); } } public void start() { unrouted.clear(); for (int i = 0; i < regions.length; i++) { workers.get(i).setRegion(regions[i]); } // debug("\n"); ExecutorService es = Executors.newFixedThreadPool(numThreads); for (DetailedRouterWorker w : workers) { es.submit(w); //w.run(); } es.shutdown(); try { es.awaitTermination(timeout, TimeUnit.SECONDS); } catch (InterruptedException e) { e.printStackTrace(); } //get all routed patches for( DetailedRouterWorker w : workers ) { if( w.isDone() ) { // for(SegPart sp : w.getSolution().keySet()){ // assert(!solutions.containsKey(sp)); // } solutions.putAll( w.getSolution() ); } } // debug("\n"); //recognize each routes not completed for (RegionToRoute region : regions) { for (SegPart segment : region.segments_to_route) { // assert(segment.segment_part.size() == 2); if (!solutions.containsKey(segment) && !unrouted.contains(segment.id)) { unrouted.add(segment.id); } } } // propagate findings to all workers and clean them for (DetailedRouterWorker w : workers) { w.removeSolutions( unrouted ); } // clean solutions for( Iterator<Map.Entry<SegPart, List<Coordinate>>> it = solutions.entrySet().iterator(); it.hasNext(); ) { Map.Entry<SegPart,List<Coordinate>> s = it.next(); if( unrouted.contains( s.getKey().id ) ) { it.remove(); } } // clean region for (RegionToRoute region : regions) { for (Iterator<SegPart> itr = region.segments_to_route.iterator(); itr.hasNext(); ) { SegPart segment = itr.next(); if (unrouted.contains(segment.id)) { itr.remove(); } } } } public void setTimeout(long seconds) { this.timeout = seconds; } public void setRegions(RegionToRoute[] regions) { this.regions = regions; } public List<Integer> getUnroutables() { return unrouted; } public void writeSolution() { for (Map.Entry<SegPart, List<Coordinate>> s : solutions.entrySet()) { SegPart toRoute = s.getKey(); List<Coordinate> routed = s.getValue(); if (routed.size() > 2 && toRoute.segment_part.size() <= 2) { //pay attention not to refill an earlier routed patch // assert(toRoute.segment_part.size() == 2); toRoute.segment_part.addAll( 1, routed ); } } solutions.clear(); } // public void debugPrintCoordinateList(List<Coordinate> cs) { // for (Coordinate c : cs) // debugPrintCoordinate(c); // debug(".\n"); // } // // public void debugPrintCoordinate(Coordinate c) { // debug("(" + c.x + "," + c.y + "," + c.layer + ") "); // } // // private void debug( String s ) { // if( this.enableOutput ) { // System.out.print( s ); // } // } public static final class DetailedRoutingSolution extends HashMap<SegPart, List<Coordinate>> { /** * */ private static final long serialVersionUID = -3806453821768987428L; @Override public DetailedRoutingSolution clone() { return (DetailedRoutingSolution) super.clone(); } } } //class FailReport{ // Rectangle2D bounds; // int seg_id; // // public FailReport(int seg_id, Rectangle2D bounds){ // this.bounds = bounds; // this.seg_id = seg_id; // } //}