Beispiel #1
0
static void
check_locally_used_fb_opins(t_ivec ** fb_opins_used_locally,
			    enum e_route_type route_type)
{

/* Checks that enough OPINs on CLBs have been set aside (used up) to make a *
 * legal routing if subblocks connect to OPINs directly.                    */

    int iclass, iblk, num_local_opins, inode, ipin;
    t_rr_type rr_type;

    for(iblk = 0; iblk < num_blocks; iblk++)
	{
	    for(iclass = 0; iclass < block[iblk].type->num_class; iclass++)
		{
		    num_local_opins =
			fb_opins_used_locally[iblk][iclass].nelem;
		    /* Always 0 for pads and for SINK classes */

		    for(ipin = 0; ipin < num_local_opins; ipin++)
			{
			    inode =
				fb_opins_used_locally[iblk][iclass].
				list[ipin];
			    check_node_and_range(inode, route_type);	/* Node makes sense? */

			    /* Now check that node is an OPIN of the right type. */

			    rr_type = rr_node[inode].type;
			    if(rr_type != OPIN)
				{
				    printf
					("Error in check_locally_used_opins:  Block #%d (%s)\n"
					 "\tclass %d locally used OPIN is of the wrong rr_type --\n"
					 "\tit is rr_node #%d of type %d.\n",
					 iblk, block[iblk].name, iclass,
					 inode, rr_type);
				    exit(1);
				}

			    ipin = rr_node[inode].ptc_num;
			    if(block[iblk].type->pin_class[ipin] != iclass)
				{
				    printf
					("Error in check_locally_used_opins:  Block #%d (%s):\n"
					 "\tExpected class %d locally used OPIN, got class %d."
					 "\trr_node #: %d.\n", iblk,
					 block[iblk].name, iclass,
					 block[iblk].type->pin_class[ipin],
					 inode);
				    exit(1);
				}
			}
		}
	}
}
Beispiel #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");
}