boolean try_breadth_first_route (struct s_router_opts router_opts,
        t_ivec **clb_opins_used_locally) {

/* Iterated maze router ala Pathfinder Negotiated Congestion algorithm,  *
 * (FPGA 95 p. 111).  Returns TRUE if it can route this FPGA, FALSE if   *
 * it can't.                                                             */

 float pres_fac;
 boolean success, is_routable, rip_up_local_opins;
 int itry, inet;

/* Usually the first iteration uses a very small (or 0) pres_fac to find  *
 * the shortest path and get a congestion map.  For fast compiles, I set  *
 * pres_fac high even for the first iteration.                            */

 pres_fac = router_opts.first_iter_pres_fac;

 for (itry=1;itry<=router_opts.max_router_iterations;itry++) {

    for (inet=0;inet<num_nets;inet++) {
    	 /* Added by Wei */
      if (is_folding)
	  {
	    if (current_stage != num_stage)
		{
	      if ((inet<num_net_per_stage[current_stage-1].begin)||(inet>=num_net_per_stage[current_stage].begin))
	          continue;
	    } 
	    else 
		{
	      if (inet<num_net_per_stage[current_stage-1].begin)
	        continue;
	    }
      }
      printf("The net is %d\n",inet);
	  
       if (is_global[inet] == FALSE) {       /* Skip global nets. */

          pathfinder_update_one_cost (trace_head[inet], -1, pres_fac);

          is_routable = breadth_first_route_net (inet, router_opts.bend_cost);

          /* Impossible to route? (disconnected rr_graph) */

          if (!is_routable) {
             printf ("Routing failed.\n");
             return (FALSE);
          }
 
          pathfinder_update_one_cost (trace_head[inet], 1, pres_fac);
       }
    }

   /* Make sure any CLB OPINs used up by subblocks being hooked directly     *
    * to them are reserved for that purpose.                                 */

    if (itry == 1)
       rip_up_local_opins = FALSE;
    else
       rip_up_local_opins = TRUE;

    reserve_locally_used_opins (pres_fac, rip_up_local_opins,
                    clb_opins_used_locally);
 
    success = feasible_routing ();
    if (success) {
       printf("Successfully routed after %d routing iterations.\n", itry);
       return (TRUE);
    }
 
    if (itry == 1)
       pres_fac = router_opts.initial_pres_fac;
    else
       pres_fac *= router_opts.pres_fac_mult;

    pathfinder_update_cost (pres_fac, router_opts.acc_fac);
 }
 
 printf ("Routing failed.\n");
 return (FALSE);
}
Exemple #2
0
void check_route(enum e_route_type route_type, int num_switch,
		t_ivec ** clb_opins_used_locally) {

	/* This routine checks that a routing:  (1) Describes a properly         *
	 * connected path for each net, (2) this path connects all the           *
	 * pins spanned by that net, and (3) that no routing resources are       *
	 * oversubscribed (the occupancy of everything is recomputed from        *
	 * scratch).                                                             */

	int inet, ipin, max_pins, inode, prev_node;
	boolean valid, connects;
	boolean * connected_to_route; /* [0 .. num_rr_nodes-1] */
	struct s_trace *tptr;
	boolean * pin_done;

	vpr_printf(TIO_MESSAGE_INFO, "\n");
	vpr_printf(TIO_MESSAGE_INFO, "Checking to ensure routing is legal...\n");

	/* Recompute the occupancy from scratch and check for overuse of routing *
	 * resources.  This was already checked in order to determine that this  *
	 * is a successful routing, but I want to double check it here.          */

	recompute_occupancy_from_scratch(clb_opins_used_locally);
	valid = feasible_routing();
	if (valid == FALSE) {
		vpr_printf(TIO_MESSAGE_ERROR, "Error in check_route -- routing resources are overused.\n");
		exit(1);
	}

	check_locally_used_clb_opins(clb_opins_used_locally, route_type);

	connected_to_route = (boolean *) my_calloc(num_rr_nodes, sizeof(boolean));

	max_pins = 0;
	for (inet = 0; inet < num_nets; inet++)
		max_pins = std::max(max_pins, (clb_net[inet].num_sinks + 1));

	pin_done = (boolean *) my_malloc(max_pins * sizeof(boolean));

	/* Now check that all nets are indeed connected. */

	for (inet = 0; inet < num_nets; inet++) {

		if (clb_net[inet].is_global || clb_net[inet].num_sinks == 0) /* Skip global nets. */
			continue;

		for (ipin = 0; ipin < (clb_net[inet].num_sinks + 1); ipin++)
			pin_done[ipin] = FALSE;

		/* Check the SOURCE of the net. */

		tptr = trace_head[inet];
		if (tptr == NULL) {
			vpr_printf(TIO_MESSAGE_ERROR, "in check_route: net %d has no routing.\n", inet);
			exit(1);
		}

		inode = tptr->index;
		check_node_and_range(inode, route_type);
		check_switch(tptr, num_switch);
		connected_to_route[inode] = TRUE; /* Mark as in path. */

		check_source(inode, inet);
		pin_done[0] = TRUE;

		prev_node = inode;
		tptr = tptr->next;

		/* Check the rest of the net */

		while (tptr != NULL) {
			inode = tptr->index;
			check_node_and_range(inode, route_type);
			check_switch(tptr, num_switch);

			if (rr_node[prev_node].type == SINK) {
				if (connected_to_route[inode] == FALSE) {
					vpr_printf(TIO_MESSAGE_ERROR, "in check_route: node %d does not link into existing routing for net %d.\n", inode, inet);
					exit(1);
				}
			}

			else {
				connects = check_adjacent(prev_node, inode);
				if (!connects) {
					vpr_printf(TIO_MESSAGE_ERROR, "in check_route: found non-adjacent segments in traceback while checking net %d.\n", inet);
					exit(1);
				}

				if (connected_to_route[inode] && rr_node[inode].type != SINK) {

					/* Note:  Can get multiple connections to the same logically-equivalent     *
					 * SINK in some logic blocks.                                               */

					vpr_printf(TIO_MESSAGE_ERROR, "in check_route: net %d routing is not a tree.\n", inet);
					exit(1);
				}

				connected_to_route[inode] = TRUE; /* Mark as in path. */

				if (rr_node[inode].type == SINK)
					check_sink(inode, inet, pin_done);

			} /* End of prev_node type != SINK */
			prev_node = inode;
			tptr = tptr->next;
		} /* End while */

		if (rr_node[prev_node].type != SINK) {
			vpr_printf(TIO_MESSAGE_ERROR, "in check_route: net %d does not end with a SINK.\n", inet);
			exit(1);
		}

		for (ipin = 0; ipin < (clb_net[inet].num_sinks + 1); ipin++) {
			if (pin_done[ipin] == FALSE) {
				vpr_printf(TIO_MESSAGE_ERROR, "in check_route: net %d does not connect to pin %d.\n", inet, ipin);
				exit(1);
			}
		}

		reset_flags(inet, connected_to_route);

	} /* End for each net */

	free(pin_done);
	free(connected_to_route);
	vpr_printf(TIO_MESSAGE_INFO, "Completed routing consistency check successfully.\n");
	vpr_printf(TIO_MESSAGE_INFO, "\n");
}
boolean
try_directed_search_route(struct s_router_opts router_opts,
			  t_ivec ** fb_opins_used_locally,
			  int width_fac,
			  t_mst_edge ** mst)
{

/* Iterated maze router ala Pathfinder Negotiated Congestion algorithm,  *
 * (FPGA 95 p. 111).  Returns TRUE if it can route this FPGA, FALSE if   *
 * it can't.                                                             */

    float pres_fac;
    boolean success, is_routable, rip_up_local_opins;
    int itry, inet;

    /* char msg[100]; */

    /* mst not built as good as it should, ideally, just have it after placement once only
	 however, rr_node numbers changed when the channel width changes so forced to do it here */
    if(mst)
	{
	    for(inet = 0; inet < num_nets; inet++)
		{
		    free(mst[inet]);
		    mst[inet] = get_mst_of_net(inet);
		}
	}

/* Usually the first iteration uses a very small (or 0) pres_fac to find  *
 * the shortest path and get a congestion map.  For fast compiles, I set  *
 * pres_fac high even for the first iteration.                            */

    pres_fac = router_opts.first_iter_pres_fac;

    for(itry = 1; itry <= router_opts.max_router_iterations; itry++)
	{

	    for(inet = 0; inet < num_nets; inet++)
		{
		    if(net[inet].is_global == FALSE)
			{	/* Skip global nets. */

			    is_routable =
				directed_search_route_net(inet, pres_fac,
							  router_opts.
							  astar_fac,
							  router_opts.
							  bend_cost, mst);

			    /* Impossible to route? (disconnected rr_graph) */

			    if(!is_routable)
				{
				    printf("Routing failed.\n");
				    return (FALSE);
				}

			}
		}

	    /* Make sure any FB OPINs used up by subblocks being hooked directly     *
	     * to them are reserved for that purpose.                                 */

	    if(itry == 1)
		rip_up_local_opins = FALSE;
	    else
		rip_up_local_opins = TRUE;

	    reserve_locally_used_opins(pres_fac, rip_up_local_opins,
				       fb_opins_used_locally);

	    success = feasible_routing();
	    if(success)
		{
		    printf
			("Successfully routed after %d routing iterations by Directed Search.\n",
			 itry);
		    return (TRUE);
		}
#if 0
	    else
		{
		    sprintf(msg,
			    "After iteration %d routing failed (A*) with a channel width factor of %d and Fc_int of %d, Fs_int of %d.",
			    itry, width_fac, Fc_int, Fs_int);
		    init_draw_coords(pins_per_clb);
		    update_screen(MAJOR, msg, ROUTING, FALSE);
		}
#endif


	    if(itry == 1)
		{
		    pres_fac = router_opts.initial_pres_fac;
		    pathfinder_update_cost(pres_fac, 0.);	/* Acc_fac=0 for first iter. */
		}
	    else
		{
		    pres_fac *= router_opts.pres_fac_mult;
		    pathfinder_update_cost(pres_fac, router_opts.acc_fac);
		}

	}

    printf("Routing failed.\n");

    return (FALSE);
}
boolean
try_directed_search_route(struct s_router_opts router_opts,
			  t_ivec ** clb_opins_used_locally,
			  int width_fac,
			  t_mst_edge ** mst)
{

/* Iterated maze router ala Pathfinder Negotiated Congestion algorithm,  *
 * (FPGA 95 p. 111).  Returns TRUE if it can route this FPGA, FALSE if   *
 * it can't.                                                             */

    float pres_fac;
    boolean success, is_routable, rip_up_local_opins;
    int itry, inet, i;
	clock_t begin, end;

    int bends;
    int wirelength, total_wirelength, available_wirelength;
    int segments;

	float *sinks;
	int *net_index;

	sinks = my_malloc(sizeof(float) * num_nets);
	net_index = my_malloc(sizeof(int) * num_nets);
	for(i = 0; i < num_nets; i++) {
		sinks[i] = clb_net[i].num_sinks;
		net_index[i] = i;
	}
	heapsort(net_index, sinks, num_nets, 1);

    /* char msg[100]; */

	begin = clock();

    /* mst not built as good as it should, ideally, just have it after placement once only
	 however, rr_node numbers changed when the channel width changes so forced to do it here */
    if(mst)
	{
	    for(inet = 0; inet < num_nets; inet++)
		{
			free(mst[inet]);
		    mst[inet] = get_mst_of_net(inet);
		}
	}

	end = clock();
	#ifdef CLOCKS_PER_SEC
		printf("mst took %g seconds\n", (float)(end - begin) / CLOCKS_PER_SEC);
	#else
		printf("mst took %g seconds\n", (float)(end - begin) / CLK_PER_SEC);
	#endif


/* Usually the first iteration uses a very small (or 0) pres_fac to find  *
 * the shortest path and get a congestion map.  For fast compiles, I set  *
 * pres_fac high even for the first iteration.                            */

    pres_fac = router_opts.first_iter_pres_fac;

    for(itry = 1; itry <= router_opts.max_router_iterations; itry++)
	{
					begin = clock();

		printf("routing iteration %d\n", itry);
		for(i = 0; i < num_nets; i++)
		{
			inet = net_index[i];
	    	if(clb_net[inet].is_global == FALSE && clb_net[inet].num_sinks != 0)
			{	/* Skip global nets and empty nets (empty nets are already reserved using reserve_locally_used_opins). */
			    is_routable =
				directed_search_route_net(inet, pres_fac,
							  router_opts.
							  astar_fac,
							  router_opts.
							  bend_cost, mst);

			    /* Impossible to route? (disconnected rr_graph) */

			    if(!is_routable)
				{
				    printf("Routing failed.\n");
					free(net_index);
					free(sinks);
				    return (FALSE);
				}

			}
		}
		end = clock();
		#ifdef CLOCKS_PER_SEC
			printf("routing iteration took %g seconds\n", (float)(end - begin) / CLOCKS_PER_SEC);
		#else
			printf("routing iteration took %g seconds\n", (float)(end - begin) / CLK_PER_SEC);
		#endif
		fflush(stdout);

		if(itry == 1) {
			/* Early exit code for cases where it is obvious that a successful route will not be found 
			   Heuristic: If total wirelength used in first routing iteration is X% of total available wirelength, exit
			*/
			total_wirelength = 0;
			available_wirelength = 0;

			for(i = 0; i < num_rr_nodes; i++) {
				if(rr_node[i].type == CHANX || rr_node[i].type == CHANY)
				{
					available_wirelength += 1 + rr_node[i].xhigh - rr_node[i].xlow +
					rr_node[i].yhigh - rr_node[i].ylow;
				}
			}

			for(inet = 0; inet < num_nets; inet++)
			{
				if(clb_net[inet].is_global == FALSE && clb_net[inet].num_sinks != 0)
				{		/* Globals don't count. */
					get_num_bends_and_length(inet, &bends, &wirelength,
								 &segments);

					total_wirelength += wirelength;
				}
			}
			printf("wirelength after first iteration %d, total available wirelength %d, ratio %g\n", total_wirelength, available_wirelength, (float)(total_wirelength)/(float)(available_wirelength));
			if((float)(total_wirelength)/(float)(available_wirelength) > FIRST_ITER_WIRELENTH_LIMIT) {
				printf("Wirelength usage ratio exceeds limit of %g, fail routing\n", FIRST_ITER_WIRELENTH_LIMIT);
				free(net_index);
				free(sinks);
				return FALSE;
			}
		}


	    /* Make sure any CLB OPINs used up by subblocks being hooked directly     *
	     * to them are reserved for that purpose.                                 */

	    if(itry == 1)
		rip_up_local_opins = FALSE;
	    else
		rip_up_local_opins = TRUE;

	    reserve_locally_used_opins(pres_fac, rip_up_local_opins,
				       clb_opins_used_locally);

	    success = feasible_routing();
	    if(success)
		{
		    printf
			("Successfully routed after %d routing iterations by Directed Search.\n",
			 itry);
			free(net_index);
			free(sinks);
		    return (TRUE);
		}
#if 0
	    else
		{
		    sprintf(msg,
			    "After iteration %d routing failed (A*) with a channel width factor of %d and Fc_int of %d, Fs_int of %d.",
			    itry, width_fac, Fc_int, Fs_int);
		    init_draw_coords(pins_per_clb);
		    update_screen(MAJOR, msg, ROUTING, FALSE);
		}
#endif


	    if(itry == 1)
		{
		    pres_fac = router_opts.initial_pres_fac;
		    pathfinder_update_cost(pres_fac, 0.);	/* Acc_fac=0 for first iter. */
		}
	    else
		{
		    pres_fac *= router_opts.pres_fac_mult;
		    pathfinder_update_cost(pres_fac, router_opts.acc_fac);
		}

	}

    printf("Routing failed.\n");
	free(sinks);
	free(net_index);

    return (FALSE);
}
boolean try_breadth_first_route(struct s_router_opts router_opts,
                                t_ivec ** clb_opins_used_locally, int width_fac) {

    /* Iterated maze router ala Pathfinder Negotiated Congestion algorithm,  *
     * (FPGA 95 p. 111).  Returns TRUE if it can route this FPGA, FALSE if   *
     * it can't.                                                             */

    float pres_fac;
    boolean success, is_routable, rip_up_local_opins;
    int itry, inet;

    /* Usually the first iteration uses a very small (or 0) pres_fac to find  *
     * the shortest path and get a congestion map.  For fast compiles, I set  *
     * pres_fac high even for the first iteration.                            */

    pres_fac = router_opts.first_iter_pres_fac;

    for (itry = 1; itry <= router_opts.max_router_iterations; itry++) {

        for (inet = 0; inet < num_nets; inet++) {
            if (clb_net[inet].is_global == FALSE) { /* Skip global nets. */

                pathfinder_update_one_cost(trace_head[inet], -1, pres_fac);

                is_routable = breadth_first_route_net(inet,
                                                      router_opts.bend_cost);

                /* Impossible to route? (disconnected rr_graph) */

                if (!is_routable) {
                    vpr_printf(TIO_MESSAGE_INFO, "Routing failed.\n");
                    return (FALSE);
                }

                pathfinder_update_one_cost(trace_head[inet], 1, pres_fac);

            }
        }

        /* Make sure any CLB OPINs used up by subblocks being hooked directly     *
         * to them are reserved for that purpose.                                 */

        if (itry == 1)
            rip_up_local_opins = FALSE;
        else
            rip_up_local_opins = TRUE;

        reserve_locally_used_opins(pres_fac, rip_up_local_opins,
                                   clb_opins_used_locally);

        success = feasible_routing();
        if (success) {
            vpr_printf(TIO_MESSAGE_INFO, "Successfully routed after %d routing iterations.\n", itry);
            return (TRUE);
        }

        if (itry == 1)
            pres_fac = router_opts.initial_pres_fac;
        else
            pres_fac *= router_opts.pres_fac_mult;

        pres_fac = std::min(pres_fac, static_cast<float>(HUGE_POSITIVE_FLOAT / 1e5));

        pathfinder_update_cost(pres_fac, router_opts.acc_fac);
    }

    vpr_printf(TIO_MESSAGE_INFO, "Routing failed.\n");
    return (FALSE);
}