Beispiel #1
0
static void check_source(int inode, int inet) {

	/* Checks that the node passed in is a valid source for this net.        */

	t_rr_type rr_type;
	t_type_ptr type;
	int i, j, ptc_num, bnum, node_block_pin, iclass;

	rr_type = rr_node[inode].type;
	if (rr_type != SOURCE) {
		vpr_printf(TIO_MESSAGE_ERROR, "in check_source: net %d begins with a node of type %d.\n", inet, rr_type);
		exit(1);
	}

	i = rr_node[inode].xlow;
	j = rr_node[inode].ylow;
	ptc_num = rr_node[inode].ptc_num; /* for sinks and sources, ptc_num is class */
	bnum = clb_net[inet].node_block[0]; /* First node_block for net is the source */
	type = grid[i][j].type;

	if (block[bnum].x != i || block[bnum].y != j) {
		vpr_printf(TIO_MESSAGE_ERROR, "in check_source: net SOURCE is in wrong location (%d,%d).\n", i, j);
		exit(1);
	}

	node_block_pin = clb_net[inet].node_block_pin[0];
	iclass = type->pin_class[node_block_pin];

	if (ptc_num != iclass) {
		vpr_printf(TIO_MESSAGE_ERROR, "in check_source: net SOURCE is of wrong class (%d).\n", ptc_num);
		exit(1);
	}
}
Beispiel #2
0
static void check_switch(struct s_trace *tptr, int num_switch) {

	/* Checks that the switch leading from this traceback element to the next *
	 * one is a legal switch type.                                            */

	int inode;
	short switch_type;

	inode = tptr->index;
	switch_type = tptr->iswitch;

	if (rr_node[inode].type != SINK) {
		if (switch_type < 0 || switch_type >= num_switch) {
			vpr_printf(TIO_MESSAGE_ERROR, "in check_switch: rr_node %d left via switch type %d.\n", inode, switch_type);
			vpr_printf(TIO_MESSAGE_ERROR, "\tSwitch type is out of range.\n");
			exit(1);
		}
	}

	else { /* Is a SINK */

		/* Without feedthroughs, there should be no switch.  If feedthroughs are    *
		 * allowed, change to treat a SINK like any other node (as above).          */

		if (switch_type != OPEN) {
			vpr_printf(TIO_MESSAGE_ERROR, "in check_switch: rr_node %d is a SINK, but attempts to use a switch of type %d.\n", 
					inode, switch_type);
			exit(1);
		}
	}
}
Beispiel #3
0
static void CheckGrid() {
	int i, j;

	/* Check grid is valid */
	for (i = 0; i <= (nx + 1); ++i) {
		for (j = 0; j <= (ny + 1); ++j) {
			if (NULL == grid[i][j].type) {
				vpr_printf(TIO_MESSAGE_ERROR, "grid[%d][%d] has no type.\n", i, j);
				exit(1);
			}

			if (grid[i][j].usage != 0) {
				vpr_printf(TIO_MESSAGE_ERROR, "grid[%d][%d] has non-zero usage (%d) before netlist load.\n", i, j, grid[i][j].usage);
				exit(1);
			}

			if ((grid[i][j].offset < 0)
					|| (grid[i][j].offset >= grid[i][j].type->height)) {
				vpr_printf(TIO_MESSAGE_ERROR, "grid[%d][%d] has invalid offset (%d).\n", i, j, grid[i][j].offset);
				exit(1);
			}

			if ((NULL == grid[i][j].blocks)
					&& (grid[i][j].type->capacity > 0)) {
				vpr_printf(TIO_MESSAGE_ERROR, "grid[%d][%d] has no block list allocated.\n", i, j);
				exit(1);
			}
		}
	}
}
Beispiel #4
0
static void compute_delta_arrays(struct s_router_opts router_opts,
		struct s_det_routing_arch det_routing_arch, t_segment_inf * segment_inf,
		t_timing_inf timing_inf, int longest_length) {

	vpr_printf(TIO_MESSAGE_INFO, "Computing delta_io_to_io lookup matrix, may take a few seconds, please wait...\n");
	compute_delta_io_to_io(router_opts, det_routing_arch, segment_inf, timing_inf);
	vpr_printf(TIO_MESSAGE_INFO, "Computing delta_io_to_clb lookup matrix, may take a few seconds, please wait...\n");
	compute_delta_io_to_clb(router_opts, det_routing_arch, segment_inf, timing_inf);
	vpr_printf(TIO_MESSAGE_INFO, "Computing delta_clb_to_io lookup matrix, may take a few seconds, please wait...\n");
	compute_delta_clb_to_io(router_opts, det_routing_arch, segment_inf, timing_inf);
	vpr_printf(TIO_MESSAGE_INFO, "Computing delta_clb_to_clb lookup matrix, may take a few seconds, please wait...\n");
	compute_delta_clb_to_clb(router_opts, det_routing_arch, segment_inf, timing_inf, longest_length);

#ifdef PRINT_ARRAYS
	lookup_dump = my_fopen(DUMPFILE, "w", 0);
	fprintf(lookup_dump, "\n\nprinting delta_clb_to_clb\n");
	print_array(delta_clb_to_clb, 0, nx - 1, 0, ny - 1);
	fprintf(lookup_dump, "\n\nprinting delta_io_to_clb\n");
	print_array(delta_io_to_clb, 0, nx, 0, ny);
	fprintf(lookup_dump, "\n\nprinting delta_clb_to_io\n");
	print_array(delta_clb_to_io, 0, nx, 0, ny);
	fprintf(lookup_dump, "\n\nprinting delta_io_to_io\n");
	print_array(delta_io_to_io, 0, nx + 1, 0, ny + 1);
	fclose(lookup_dump);
#endif

}
Beispiel #5
0
void vpr_pack(INP t_vpr_setup vpr_setup, INP t_arch arch) {
	clock_t begin, end;
	float inter_cluster_delay = UNDEFINED, Tdel_opin_switch, Tdel_wire_switch,
			Tdel_wtoi_switch, R_opin_switch, R_wire_switch, R_wtoi_switch,
			Cout_opin_switch, Cout_wire_switch, Cout_wtoi_switch,
			opin_switch_del, wire_switch_del, wtoi_switch_del, Rmetal, Cmetal,
			first_wire_seg_delay, second_wire_seg_delay;
	begin = clock();
	vpr_printf(TIO_MESSAGE_INFO, "Initialize packing.\n");

	/* If needed, estimate inter-cluster delay. Assume the average routing hop goes out of 
	 a block through an opin switch to a length-4 wire, then through a wire switch to another
	 length-4 wire, then through a wire-to-ipin-switch into another block. */

	if (vpr_setup.PackerOpts.timing_driven
			&& vpr_setup.PackerOpts.auto_compute_inter_cluster_net_delay) {
		opin_switch_del = get_switch_info(arch.Segments[0].opin_switch,
				Tdel_opin_switch, R_opin_switch, Cout_opin_switch);
		wire_switch_del = get_switch_info(arch.Segments[0].wire_switch,
				Tdel_wire_switch, R_wire_switch, Cout_wire_switch);
		wtoi_switch_del = get_switch_info(
				vpr_setup.RoutingArch.wire_to_ipin_switch, Tdel_wtoi_switch,
				R_wtoi_switch, Cout_wtoi_switch); /* wire-to-ipin switch */
		Rmetal = arch.Segments[0].Rmetal;
		Cmetal = arch.Segments[0].Cmetal;

		/* The delay of a wire with its driving switch is the switch delay plus the 
		 product of the equivalent resistance and capacitance experienced by the wire. */

#define WIRE_SEGMENT_LENGTH 4
		first_wire_seg_delay = opin_switch_del
				+ (R_opin_switch + Rmetal * WIRE_SEGMENT_LENGTH / 2)
						* (Cout_opin_switch + Cmetal * WIRE_SEGMENT_LENGTH);
		second_wire_seg_delay = wire_switch_del
				+ (R_wire_switch + Rmetal * WIRE_SEGMENT_LENGTH / 2)
						* (Cout_wire_switch + Cmetal * WIRE_SEGMENT_LENGTH);
		inter_cluster_delay = 4
				* (first_wire_seg_delay + second_wire_seg_delay
						+ wtoi_switch_del); /* multiply by 4 to get a more conservative estimate */
	}

	try_pack(&vpr_setup.PackerOpts, &arch, vpr_setup.user_models,
			vpr_setup.library_models, vpr_setup.Timing, inter_cluster_delay);
	end = clock();
#ifdef CLOCKS_PER_SEC
	vpr_printf(TIO_MESSAGE_INFO, "Packing took %g seconds.\n",
			(float) (end - begin) / CLOCKS_PER_SEC);
	vpr_printf(TIO_MESSAGE_INFO, "Packing completed.\n");
#else
	vpr_printf(TIO_MESSAGE_INFO, "Packing took %g seconds.\n", (float)(end - begin) / CLK_PER_SEC);
#endif
	fflush(stdout);
}
Beispiel #6
0
/**
 * VPR program
 * Generate FPGA architecture given architecture description
 * Pack, place, and route circuit into FPGA architecture
 * Electrical timing analysis on results
 *
 * Overall steps
 * 1.  Initialization
 * 2.  Pack
 * 3.  Place-and-route and timing analysis
 * 4.  Clean up
 */
int main(int argc, char **argv) {
	t_options Options;
	t_arch Arch;
	t_vpr_setup vpr_setup;
	clock_t entire_flow_begin,entire_flow_end,end,begin;

	entire_flow_begin = clock();
	//end = clock();
        //begin = clock();

	/* Read options, architecture, and circuit netlist */
	vpr_init(argc, argv, &Options, &vpr_setup, &Arch);

	/* If the user requests packing, do packing */
	if (vpr_setup.PackerOpts.doPacking) {
		vpr_pack(vpr_setup, Arch);
	}

	if (vpr_setup.PlacerOpts.doPlacement || vpr_setup.RouterOpts.doRouting) {
		vpr_init_pre_place_and_route(vpr_setup, Arch);
		vpr_place_and_route(vpr_setup, Arch, Options);
#if 0
		if(vpr_setup.RouterOpts.doRouting) {
			vpr_resync_post_route_netlist_to_TI_CLAY_v1_architecture(&Arch);
		}
#endif
	}
    end = clock();
#ifdef CLOCKS_PER_SEC
    printf("Packing took %g seconds\n", (float)(end - begin) / CLOCKS_PER_SEC);
#else
    printf("Packing took %g seconds\n", (float)(end - begin) / CLK_PER_SEC);
#endif

	if (vpr_setup.PowerOpts.do_power) {
		vpr_power_estimation(vpr_setup, Arch);
	}
	
	entire_flow_end = clock();
	
	#ifdef CLOCKS_PER_SEC
		vpr_printf(TIO_MESSAGE_INFO, "The entire flow of VPR took %g seconds.\n", (float)(entire_flow_end - entire_flow_begin) / CLOCKS_PER_SEC);
	#else
		vpr_printf(TIO_MESSAGE_INFO, "The entire flow of VPR took %g seconds.\n", (float)(entire_flow_end - entire_flow_begin) / CLK_PER_SEC);
	#endif
	
	/* free data structures */
	vpr_free_all(Arch, Options, vpr_setup);

	/* Return 0 to single success to scripts */
	return 0;
}
/* count up pin classes of the same number for the given cluster */
static void sum_pin_class(INOUTP t_pb_graph_node *pb_graph_node) {
    int i, j;

    /* This is a primitive, for each pin in primitive, sum appropriate pin class */
    for (i = 0; i < pb_graph_node->num_input_ports; i++) {
        for (j = 0; j < pb_graph_node->num_input_pins[i]; j++) {
            assert(
                pb_graph_node->input_pins[i][j].pin_class < pb_graph_node->num_input_pin_class);
            if (pb_graph_node->input_pins[i][j].pin_class == OPEN) {
                vpr_printf(TIO_MESSAGE_WARNING, "%s[%d].%s[%d] unconnected pin in architecture.\n",
                           pb_graph_node->pb_type->name,
                           pb_graph_node->placement_index,
                           pb_graph_node->input_pins[i][j].port->name,
                           pb_graph_node->input_pins[i][j].pin_number);
                continue;
            }
            pb_graph_node->input_pin_class_size[pb_graph_node->input_pins[i][j].pin_class]++;
        }
    }
    for (i = 0; i < pb_graph_node->num_output_ports; i++) {
        for (j = 0; j < pb_graph_node->num_output_pins[i]; j++) {
            assert(
                pb_graph_node->output_pins[i][j].pin_class < pb_graph_node->num_output_pin_class);
            if (pb_graph_node->output_pins[i][j].pin_class == OPEN) {
                vpr_printf(TIO_MESSAGE_WARNING, "%s[%d].%s[%d] unconnected pin in architecture.\n",
                           pb_graph_node->pb_type->name,
                           pb_graph_node->placement_index,
                           pb_graph_node->output_pins[i][j].port->name,
                           pb_graph_node->output_pins[i][j].pin_number);
                continue;
            }
            pb_graph_node->output_pin_class_size[pb_graph_node->output_pins[i][j].pin_class]++;
        }
    }
    for (i = 0; i < pb_graph_node->num_clock_ports; i++) {
        for (j = 0; j < pb_graph_node->num_clock_pins[i]; j++) {
            assert(
                pb_graph_node->clock_pins[i][j].pin_class < pb_graph_node->num_input_pin_class);
            if (pb_graph_node->clock_pins[i][j].pin_class == OPEN) {
                vpr_printf(TIO_MESSAGE_WARNING, "%s[%d].%s[%d] unconnected pin in architecture.\n",
                           pb_graph_node->pb_type->name,
                           pb_graph_node->placement_index,
                           pb_graph_node->clock_pins[i][j].port->name,
                           pb_graph_node->clock_pins[i][j].pin_number);
                continue;
            }
            pb_graph_node->input_pin_class_size[pb_graph_node->clock_pins[i][j].pin_class]++;
        }
    }
}
Beispiel #8
0
static void ShowOperation(INP enum e_operation Operation) {
	vpr_printf(TIO_MESSAGE_INFO, "Operation: ");
	switch (Operation) {
	case RUN_FLOW:
		vpr_printf(TIO_MESSAGE_INFO, "RUN_FLOW\n");
		break;
	case TIMING_ANALYSIS_ONLY:
		vpr_printf(TIO_MESSAGE_INFO, "TIMING_ANALYSIS_ONLY\n");
		break;
	default:
		vpr_printf(TIO_MESSAGE_ERROR, "Unknown VPR operation\n");
	}
	vpr_printf(TIO_MESSAGE_INFO, "\n");
}
Beispiel #9
0
void ShowSetup(INP t_options options, INP t_vpr_setup vpr_setup) {
	vpr_printf(TIO_MESSAGE_INFO, "Timing analysis: %s\n", (vpr_setup.TimingEnabled? "ON" : "OFF"));

	vpr_printf(TIO_MESSAGE_INFO, "Circuit netlist file: %s\n", vpr_setup.FileNameOpts.NetFile);
	vpr_printf(TIO_MESSAGE_INFO, "Circuit placement file: %s\n", vpr_setup.FileNameOpts.PlaceFile);
	vpr_printf(TIO_MESSAGE_INFO, "Circuit routing file: %s\n", vpr_setup.FileNameOpts.RouteFile);
	vpr_printf(TIO_MESSAGE_INFO, "Circuit SDC file: %s\n", vpr_setup.Timing.SDCFile);

	ShowOperation(vpr_setup.Operation);
	vpr_printf(TIO_MESSAGE_INFO, "Packer: %s\n", (vpr_setup.PackerOpts.doPacking ? "ENABLED" : "DISABLED"));
	vpr_printf(TIO_MESSAGE_INFO, "Placer: %s\n", (vpr_setup.PlacerOpts.doPlacement ? "ENABLED" : "DISABLED"));
	vpr_printf(TIO_MESSAGE_INFO, "Router: %s\n", (vpr_setup.RouterOpts.doRouting ? "ENABLED" : "DISABLED"));

	if (vpr_setup.PackerOpts.doPacking) {
		ShowPackerOpts(vpr_setup.PackerOpts);
	}
	if (vpr_setup.PlacerOpts.doPlacement) {
		ShowPlacerOpts(options, vpr_setup.PlacerOpts, vpr_setup.AnnealSched);
	}
	if (vpr_setup.RouterOpts.doRouting) {
		ShowRouterOpts(vpr_setup.RouterOpts);
	}

	if (DETAILED == vpr_setup.RouterOpts.route_type)
		ShowRoutingArch(vpr_setup.RoutingArch);

}
Beispiel #10
0
static void check_sink(int inode, int inet, boolean * pin_done) {

	/* Checks that this SINK node is one of the terminals of inet, and marks   *
	 * the appropriate pin as being reached.                                   */

	int i, j, ipin, ifound, ptc_num, bnum, iclass, node_block_pin, iblk;
	t_type_ptr type;

	assert(rr_node[inode].type == SINK);
	i = rr_node[inode].xlow;
	j = rr_node[inode].ylow;
	type = grid[i][j].type;
	ptc_num = rr_node[inode].ptc_num; /* For sinks, ptc_num is the class */
	ifound = 0;

	for (iblk = 0; iblk < type->capacity; iblk++) {
		bnum = grid[i][j].blocks[iblk]; /* Hardcoded to one block */
		for (ipin = 1; ipin < (clb_net[inet].num_sinks + 1); ipin++) { /* All net SINKs */
			if (clb_net[inet].node_block[ipin] == bnum) {
				node_block_pin = clb_net[inet].node_block_pin[ipin];
				iclass = type->pin_class[node_block_pin];
				if (iclass == ptc_num) {
					/* Could connect to same pin class on the same clb more than once.  Only   *
					 * update pin_done for a pin that hasn't been reached yet.                 */

					if (pin_done[ipin] == FALSE) {
						ifound++;
						pin_done[ipin] = TRUE;
					}
				}
			}
		}
	}

	if (ifound > 1 && type == IO_TYPE) {
		vpr_printf(TIO_MESSAGE_ERROR, "in check_sink: found %d terminals of net %d of pad %d at location (%d, %d).\n", ifound, inet, ptc_num, i, j);
		exit(1);
	}

	if (ifound < 1) {
		vpr_printf(TIO_MESSAGE_ERROR, "in check_sink: node %d does not connect to any terminal of net %s #%d.\n"
									  "This error is usually caused by incorrectly specified logical equivalence in your architecture file.\n"
									  "You should try to respecify what pins are equivalent or turn logical equivalence off.\n", inode, clb_net[inet].name, inet);
		exit(1);
	}
}
Beispiel #11
0
/* Display general VPR information */
void vpr_print_title(void) {
	vpr_printf(TIO_MESSAGE_INFO, "\n");
	vpr_printf(TIO_MESSAGE_INFO, "VPR FPGA Placement and Routing.\n");
	vpr_printf(TIO_MESSAGE_INFO, "Version: Version " VPR_VERSION "\n");
	vpr_printf(TIO_MESSAGE_INFO, "Compiled: " __DATE__ ".\n");
	vpr_printf(TIO_MESSAGE_INFO, "University of Toronto\n");
	vpr_printf(TIO_MESSAGE_INFO, "[email protected]\n");
	vpr_printf(TIO_MESSAGE_INFO, "This is free open source code under MIT license.\n");
	vpr_printf(TIO_MESSAGE_INFO, "\n");
}
Beispiel #12
0
static void check_locally_used_clb_opins(t_ivec ** clb_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 = clb_opins_used_locally[iblk][iclass].nelem;
			/* Always 0 for pads and for SINK classes */

			for (ipin = 0; ipin < num_local_opins; ipin++) {
				inode = clb_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) {
					vpr_printf(TIO_MESSAGE_ERROR, "in check_locally_used_opins: block #%d (%s)\n",
							iblk, block[iblk].name);
					vpr_printf(TIO_MESSAGE_ERROR, "\tClass %d local OPIN is wrong rr_type -- rr_node #%d of type %d.\n",
							iclass, inode, rr_type);
					exit(1);
				}

				ipin = rr_node[inode].ptc_num;
				if (block[iblk].type->pin_class[ipin] != iclass) {
					vpr_printf(TIO_MESSAGE_ERROR, "in check_locally_used_opins: block #%d (%s):\n",
							iblk, block[iblk].name);
					vpr_printf(TIO_MESSAGE_ERROR, "\tExpected class %d local OPIN has class %d -- rr_node #: %d.\n",
							iclass,	block[iblk].type->pin_class[ipin], inode);
					exit(1);
				}
			}
		}
	}
}
Beispiel #13
0
static void check_node_and_range(int inode, enum e_route_type route_type) {

	/* Checks that inode is within the legal range, then calls check_node to    *
	 * check that everything else about the node is OK.                         */

	if (inode < 0 || inode >= num_rr_nodes) { 
		vpr_printf(TIO_MESSAGE_ERROR, "in check_node_and_range: rr_node #%d is out of legal, range (0 to %d).\n", 
				inode, num_rr_nodes - 1);
		exit(1);
	}
	check_node(inode, route_type);
}
Beispiel #14
0
void printClusteredNetlistStats() {
	int i, j, L_num_p_inputs, L_num_p_outputs;
	int *num_blocks_type;
	num_blocks_type = (int*) my_calloc(num_types, sizeof(int));

	vpr_printf(TIO_MESSAGE_INFO, "\n");
	vpr_printf(TIO_MESSAGE_INFO, "Netlist num_nets: %d\n", num_nets);
	vpr_printf(TIO_MESSAGE_INFO, "Netlist num_blocks: %d\n", num_blocks);

	for (i = 0; i < num_types; i++) {
		num_blocks_type[i] = 0;
	}
	/* Count I/O input and output pads */
	L_num_p_inputs = 0;
	L_num_p_outputs = 0;

	for (i = 0; i < num_blocks; i++) {
		num_blocks_type[block[i].type->index]++;
		if (block[i].type == IO_TYPE) {
			for (j = 0; j < IO_TYPE->num_pins; j++) {
				if (block[i].nets[j] != OPEN) {
					if (IO_TYPE->class_inf[IO_TYPE->pin_class[j]].type
							== DRIVER) {
						L_num_p_inputs++;
					} else {
						assert(
								IO_TYPE-> class_inf[IO_TYPE-> pin_class[j]]. type == RECEIVER);
						L_num_p_outputs++;
					}
				}
			}
		}
	}

	for (i = 0; i < num_types; i++) {
		if (IO_TYPE != &type_descriptors[i]) {
			vpr_printf(TIO_MESSAGE_INFO, "Netlist %s blocks: %d.\n", type_descriptors[i].name, num_blocks_type[i]);
		}
	}

	/* Print out each block separately instead */
	vpr_printf(TIO_MESSAGE_INFO, "Netlist inputs pins: %d\n", L_num_p_inputs);
	vpr_printf(TIO_MESSAGE_INFO, "Netlist output pins: %d\n", L_num_p_outputs);
	vpr_printf(TIO_MESSAGE_INFO, "\n");
	free(num_blocks_type);
}
Beispiel #15
0
static void ShowAnnealSched(INP struct s_annealing_sched AnnealSched) {

	vpr_printf(TIO_MESSAGE_INFO, "AnnealSched.type: ");
	switch (AnnealSched.type) {
	case AUTO_SCHED:
		vpr_printf(TIO_MESSAGE_INFO, "AUTO_SCHED\n");
		break;
	case USER_SCHED:
		vpr_printf(TIO_MESSAGE_INFO, "USER_SCHED\n");
		break;
	default:
		vpr_printf(TIO_MESSAGE_ERROR, "Unknown annealing schedule\n");
	}

	vpr_printf(TIO_MESSAGE_INFO, "AnnealSched.inner_num: %f\n", AnnealSched.inner_num);

	if (USER_SCHED == AnnealSched.type) {
		vpr_printf(TIO_MESSAGE_INFO, "AnnealSched.init_t: %f\n", AnnealSched.init_t);
		vpr_printf(TIO_MESSAGE_INFO, "AnnealSched.alpha_t: %f\n", AnnealSched.alpha_t);
		vpr_printf(TIO_MESSAGE_INFO, "AnnealSched.exit_t: %f\n", AnnealSched.exit_t);
	}
}
Beispiel #16
0
static void print_string(const char *str_ptr, int *column, FILE * fpout) {

    /* Prints string without making any lines longer than LINELENGTH.  Column  *
     * points to the column in which the next character will go (both used and *
     * updated), and fpout points to the output file.                          */

    int len;

    len = strlen(str_ptr);
    if (len + 3 > LINELENGTH) {
        vpr_printf(TIO_MESSAGE_ERROR, "in print_string: String %s is too long for desired maximum line length.\n", str_ptr);
        exit(1);
    }

    if (*column + len + 2 > LINELENGTH) {
        fprintf(fpout, "\\ \n");
        *column = TABLENGTH;
    }

    fprintf(fpout, "%s ", str_ptr);
    *column += len + 1;
}
Beispiel #17
0
static boolean check_adjacent(int from_node, int to_node) {

	/* This routine checks if the rr_node to_node is reachable from from_node.   *
	 * It returns TRUE if is reachable and FALSE if it is not.  Check_node has   *
	 * already been used to verify that both nodes are valid rr_nodes, so only   *
	 * adjacency is checked here.                                                
	 * Special case: direct OPIN to IPIN connections need not be adjacent.  These
	 * represent specially-crafted connections such as carry-chains or more advanced
	 * blocks where adjacency is overridden by the architect */


	int from_xlow, from_ylow, to_xlow, to_ylow, from_ptc, to_ptc, iclass;
	int num_adj, to_xhigh, to_yhigh, from_xhigh, from_yhigh, iconn;
	boolean reached;
	t_rr_type from_type, to_type;
	t_type_ptr from_grid_type, to_grid_type;

	reached = FALSE;

	for (iconn = 0; iconn < rr_node[from_node].num_edges; iconn++) {
		if (rr_node[from_node].edges[iconn] == to_node) {
			reached = TRUE;
			break;
		}
	}

	if (!reached)
		return (FALSE);

	/* Now we know the rr graph says these two nodes are adjacent.  Double  *
	 * check that this makes sense, to verify the rr graph.                 */

	num_adj = 0;

	from_type = rr_node[from_node].type;
	from_xlow = rr_node[from_node].xlow;
	from_ylow = rr_node[from_node].ylow;
	from_xhigh = rr_node[from_node].xhigh;
	from_yhigh = rr_node[from_node].yhigh;
	from_ptc = rr_node[from_node].ptc_num;
	to_type = rr_node[to_node].type;
	to_xlow = rr_node[to_node].xlow;
	to_ylow = rr_node[to_node].ylow;
	to_xhigh = rr_node[to_node].xhigh;
	to_yhigh = rr_node[to_node].yhigh;
	to_ptc = rr_node[to_node].ptc_num;

	switch (from_type) {

	case SOURCE:
		assert(to_type == OPIN);
		if (from_xlow == to_xlow && from_ylow == to_ylow
				&& from_xhigh == to_xhigh && from_yhigh == to_yhigh) {

			from_grid_type = grid[from_xlow][from_ylow].type;
			to_grid_type = grid[to_xlow][to_ylow].type;
			assert(from_grid_type == to_grid_type);

			iclass = to_grid_type->pin_class[to_ptc];
			if (iclass == from_ptc)
				num_adj++;
		}
		break;

	case SINK:
		/* SINKS are adjacent to not connected */
		break;

	case OPIN:
		if(to_type == CHANX || to_type == CHANY) {
			num_adj += pin_and_chan_adjacent(from_node, to_node);
		} else {
			assert(to_type == IPIN); /* direct OPIN to IPIN connections not necessarily adjacent */
			return TRUE; /* Special case, direct OPIN to IPIN connections need not be adjacent */
		}

		break;

	case IPIN:
		assert(to_type == SINK);
		if (from_xlow == to_xlow && from_ylow == to_ylow
				&& from_xhigh == to_xhigh && from_yhigh == to_yhigh) {

			from_grid_type = grid[from_xlow][from_ylow].type;
			to_grid_type = grid[to_xlow][to_ylow].type;
			assert(from_grid_type == to_grid_type);

			iclass = from_grid_type->pin_class[from_ptc];
			if (iclass == to_ptc)
				num_adj++;
		}
		break;

	case CHANX:
		if (to_type == IPIN) {
			num_adj += pin_and_chan_adjacent(to_node, from_node);
		} else if (to_type == CHANX) {
			from_xhigh = rr_node[from_node].xhigh;
			to_xhigh = rr_node[to_node].xhigh;
			if (from_ylow == to_ylow) {
				/* UDSD Modification by WMF Begin */
				/*For Fs > 3, can connect to overlapping wire segment */
				if (to_xhigh == from_xlow - 1 || from_xhigh == to_xlow - 1) {
					num_adj++;
				}
				/* Overlapping */
				else {
					int i;

					for (i = from_xlow; i <= from_xhigh; i++) {
						if (i >= to_xlow && i <= to_xhigh) {
							num_adj++;
							break;
						}
					}
				}
				/* UDSD Modification by WMF End */
			}
		} else if (to_type == CHANY) {
			num_adj += chanx_chany_adjacent(from_node, to_node);
		} else {
			assert(0);
		}
		break;

	case CHANY:
		if (to_type == IPIN) {
			num_adj += pin_and_chan_adjacent(to_node, from_node);
		} else if (to_type == CHANY) {
			from_yhigh = rr_node[from_node].yhigh;
			to_yhigh = rr_node[to_node].yhigh;
			if (from_xlow == to_xlow) {
				/* UDSD Modification by WMF Begin */
				if (to_yhigh == from_ylow - 1 || from_yhigh == to_ylow - 1) {
					num_adj++;
				}
				/* Overlapping */
				else {
					int j;

					for (j = from_ylow; j <= from_yhigh; j++) {
						if (j >= to_ylow && j <= to_yhigh) {
							num_adj++;
							break;
						}
					}
				}
				/* UDSD Modification by WMF End */
			}
		} else if (to_type == CHANX) {
			num_adj += chanx_chany_adjacent(to_node, from_node);
		} else {
			assert(0);
		}
		break;

	default:
		break;

	}

	if (num_adj == 1)
		return (TRUE);
	else if (num_adj == 0)
		return (FALSE);

	vpr_printf(TIO_MESSAGE_ERROR, "in check_adjacent: num_adj = %d. Expected 0 or 1.\n", num_adj);
	exit(1);
}
Beispiel #18
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");
}
Beispiel #19
0
static void ShowRouterOpts(INP struct s_router_opts RouterOpts) {

	vpr_printf(TIO_MESSAGE_INFO, "RouterOpts.route_type: ");
	switch (RouterOpts.route_type) {
	case GLOBAL:
		vpr_printf(TIO_MESSAGE_INFO, "GLOBAL\n");
		break;
	case DETAILED:
		vpr_printf(TIO_MESSAGE_INFO, "DETAILED\n");
		break;
	default:
		vpr_printf(TIO_MESSAGE_ERROR, "Unknown router opt\n");
	}

	if (DETAILED == RouterOpts.route_type) {
		vpr_printf(TIO_MESSAGE_INFO, "RouterOpts.router_algorithm: ");
		switch (RouterOpts.router_algorithm) {
		case BREADTH_FIRST:
			vpr_printf(TIO_MESSAGE_INFO, "BREADTH_FIRST\n");
			break;
		case TIMING_DRIVEN:
			vpr_printf(TIO_MESSAGE_INFO, "TIMING_DRIVEN\n");
			break;
		case NO_TIMING:
			vpr_printf(TIO_MESSAGE_INFO, "NO_TIMING\n");
			break;
		default:
			vpr_printf(TIO_MESSAGE_INFO, "<Unknown>\n");
			exit(1);
		}

		vpr_printf(TIO_MESSAGE_INFO, "RouterOpts.base_cost_type: ");
		switch (RouterOpts.base_cost_type) {
		case INTRINSIC_DELAY:
			vpr_printf(TIO_MESSAGE_INFO, "INTRINSIC_DELAY\n");
			break;
		case DELAY_NORMALIZED:
			vpr_printf(TIO_MESSAGE_INFO, "DELAY_NORMALIZED\n");
			break;
		case DEMAND_ONLY:
			vpr_printf(TIO_MESSAGE_INFO, "DEMAND_ONLY\n");
			break;
		default:
			vpr_printf(TIO_MESSAGE_ERROR, "Unknown base_cost_type\n");
		}

		vpr_printf(TIO_MESSAGE_INFO, "RouterOpts.fixed_channel_width: ");
		if (NO_FIXED_CHANNEL_WIDTH == RouterOpts.fixed_channel_width) {
			vpr_printf(TIO_MESSAGE_INFO, "NO_FIXED_CHANNEL_WIDTH\n");
		} else {
			vpr_printf(TIO_MESSAGE_INFO, "%d\n", RouterOpts.fixed_channel_width);
		}

		vpr_printf(TIO_MESSAGE_INFO, "RouterOpts.acc_fac: %f\n", RouterOpts.acc_fac);
		vpr_printf(TIO_MESSAGE_INFO, "RouterOpts.bb_factor: %d\n", RouterOpts.bb_factor);
		vpr_printf(TIO_MESSAGE_INFO, "RouterOpts.bend_cost: %f\n", RouterOpts.bend_cost);
		vpr_printf(TIO_MESSAGE_INFO, "RouterOpts.first_iter_pres_fac: %f\n", RouterOpts.first_iter_pres_fac);
		vpr_printf(TIO_MESSAGE_INFO, "RouterOpts.initial_pres_fac: %f\n", RouterOpts.initial_pres_fac);
		vpr_printf(TIO_MESSAGE_INFO, "RouterOpts.pres_fac_mult: %f\n", RouterOpts.pres_fac_mult);
		vpr_printf(TIO_MESSAGE_INFO, "RouterOpts.max_router_iterations: %d\n", RouterOpts.max_router_iterations);

		if (TIMING_DRIVEN == RouterOpts.router_algorithm) {
			vpr_printf(TIO_MESSAGE_INFO, "RouterOpts.astar_fac: %f\n", RouterOpts.astar_fac);
			vpr_printf(TIO_MESSAGE_INFO, "RouterOpts.criticality_exp: %f\n", RouterOpts.criticality_exp);
			vpr_printf(TIO_MESSAGE_INFO, "RouterOpts.max_criticality: %f\n", RouterOpts.max_criticality);
		}
	} else {
		assert(GLOBAL == RouterOpts.route_type);

		vpr_printf(TIO_MESSAGE_INFO, "RouterOpts.router_algorithm: ");
		switch (RouterOpts.router_algorithm) {
		case BREADTH_FIRST:
			vpr_printf(TIO_MESSAGE_INFO, "BREADTH_FIRST\n");
			break;
		case TIMING_DRIVEN:
			vpr_printf(TIO_MESSAGE_INFO, "TIMING_DRIVEN\n");
			break;
		case NO_TIMING:
			vpr_printf(TIO_MESSAGE_INFO, "NO_TIMING\n");
			break;
		default:
			vpr_printf(TIO_MESSAGE_ERROR, "Unknown router algorithm\n");
		}

		vpr_printf(TIO_MESSAGE_INFO, "RouterOpts.base_cost_type: ");
		switch (RouterOpts.base_cost_type) {
		case INTRINSIC_DELAY:
			vpr_printf(TIO_MESSAGE_INFO, "INTRINSIC_DELAY\n");
			break;
		case DELAY_NORMALIZED:
			vpr_printf(TIO_MESSAGE_INFO, "DELAY_NORMALIZED\n");
			break;
		case DEMAND_ONLY:
			vpr_printf(TIO_MESSAGE_INFO, "DEMAND_ONLY\n");
			break;
		default:
			vpr_printf(TIO_MESSAGE_ERROR, "Unknown router base cost type\n");
		}

		vpr_printf(TIO_MESSAGE_INFO, "RouterOpts.fixed_channel_width: ");
		if (NO_FIXED_CHANNEL_WIDTH == RouterOpts.fixed_channel_width) {
			vpr_printf(TIO_MESSAGE_INFO, "NO_FIXED_CHANNEL_WIDTH\n");
		} else {
			vpr_printf(TIO_MESSAGE_INFO, "%d\n", RouterOpts.fixed_channel_width);
		}

		vpr_printf(TIO_MESSAGE_INFO, "RouterOpts.acc_fac: %f\n", RouterOpts.acc_fac);
		vpr_printf(TIO_MESSAGE_INFO, "RouterOpts.bb_factor: %d\n", RouterOpts.bb_factor);
		vpr_printf(TIO_MESSAGE_INFO, "RouterOpts.bend_cost: %f\n", RouterOpts.bend_cost);
		vpr_printf(TIO_MESSAGE_INFO, "RouterOpts.first_iter_pres_fac: %f\n", RouterOpts.first_iter_pres_fac);
		vpr_printf(TIO_MESSAGE_INFO, "RouterOpts.initial_pres_fac: %f\n", RouterOpts.initial_pres_fac);
		vpr_printf(TIO_MESSAGE_INFO, "RouterOpts.pres_fac_mult: %f\n", RouterOpts.pres_fac_mult);
		vpr_printf(TIO_MESSAGE_INFO, "RouterOpts.max_router_iterations: %d\n", RouterOpts.max_router_iterations);
		if (TIMING_DRIVEN == RouterOpts.router_algorithm) {
			vpr_printf(TIO_MESSAGE_INFO, "RouterOpts.astar_fac: %f\n", RouterOpts.astar_fac);
			vpr_printf(TIO_MESSAGE_INFO, "RouterOpts.criticality_exp: %f\n", RouterOpts.criticality_exp);
			vpr_printf(TIO_MESSAGE_INFO, "RouterOpts.max_criticality: %f\n", RouterOpts.max_criticality);
		}
	}
	vpr_printf(TIO_MESSAGE_INFO, "\n");
}
Beispiel #20
0
static void ShowPlacerOpts(INP t_options Options,
		INP struct s_placer_opts PlacerOpts,
		INP struct s_annealing_sched AnnealSched) {

	vpr_printf(TIO_MESSAGE_INFO, "PlacerOpts.place_freq: ");
	switch (PlacerOpts.place_freq) {
	case PLACE_ONCE:
		vpr_printf(TIO_MESSAGE_INFO, "PLACE_ONCE\n");
		break;
	case PLACE_ALWAYS:
		vpr_printf(TIO_MESSAGE_INFO, "PLACE_ALWAYS\n");
		break;
	case PLACE_NEVER:
		vpr_printf(TIO_MESSAGE_INFO, "PLACE_NEVER\n");
		break;
	default:
		vpr_printf(TIO_MESSAGE_ERROR, "Unknown Place Freq\n");
	}
	if ((PLACE_ONCE == PlacerOpts.place_freq)
			|| (PLACE_ALWAYS == PlacerOpts.place_freq)) {

		vpr_printf(TIO_MESSAGE_INFO, "PlacerOpts.place_algorithm: ");
		switch (PlacerOpts.place_algorithm) {
		case BOUNDING_BOX_PLACE:
			vpr_printf(TIO_MESSAGE_INFO, "BOUNDING_BOX_PLACE\n");
			break;
		case NET_TIMING_DRIVEN_PLACE:
			vpr_printf(TIO_MESSAGE_INFO, "NET_TIMING_DRIVEN_PLACE\n");
			break;
		case PATH_TIMING_DRIVEN_PLACE:
			vpr_printf(TIO_MESSAGE_INFO, "PATH_TIMING_DRIVEN_PLACE\n");
			break;
		default:
			vpr_printf(TIO_MESSAGE_ERROR, "Unknown placement algorithm\n");
		}

		vpr_printf(TIO_MESSAGE_INFO, "PlacerOpts.pad_loc_type: ");
		switch (PlacerOpts.pad_loc_type) {
		case FREE:
			vpr_printf(TIO_MESSAGE_INFO, "FREE\n");
			break;
		case RANDOM:
			vpr_printf(TIO_MESSAGE_INFO, "RANDOM\n");
			break;
		case USER:
			vpr_printf(TIO_MESSAGE_INFO, "USER '%s'\n", PlacerOpts.pad_loc_file);
			break;
		default:
			vpr_printf(TIO_MESSAGE_INFO, "Unknown I/O pad location type\n");
			exit(1);
		}

		vpr_printf(TIO_MESSAGE_INFO, "PlacerOpts.place_cost_exp: %f\n", PlacerOpts.place_cost_exp);

		if (Options.Count[OT_PLACE_CHAN_WIDTH]) {
			vpr_printf(TIO_MESSAGE_INFO, "PlacerOpts.place_chan_width: %d\n", PlacerOpts.place_chan_width);
		}

		if ((NET_TIMING_DRIVEN_PLACE == PlacerOpts.place_algorithm)
				|| (PATH_TIMING_DRIVEN_PLACE == PlacerOpts.place_algorithm)) {
			vpr_printf(TIO_MESSAGE_INFO, "PlacerOpts.inner_loop_recompute_divider: %d\n", PlacerOpts.inner_loop_recompute_divider);
			vpr_printf(TIO_MESSAGE_INFO, "PlacerOpts.recompute_crit_iter: %d\n", PlacerOpts.recompute_crit_iter);
			vpr_printf(TIO_MESSAGE_INFO, "PlacerOpts.timing_tradeoff: %f\n", PlacerOpts.timing_tradeoff);
			vpr_printf(TIO_MESSAGE_INFO, "PlacerOpts.td_place_exp_first: %f\n", PlacerOpts.td_place_exp_first);
			vpr_printf(TIO_MESSAGE_INFO, "PlacerOpts.td_place_exp_last: %f\n", PlacerOpts.td_place_exp_last);
		}

		vpr_printf(TIO_MESSAGE_INFO, "PlaceOpts.seed: %d\n", PlacerOpts.seed);

		ShowAnnealSched(AnnealSched);
	}
	vpr_printf(TIO_MESSAGE_INFO, "\n");

}
Beispiel #21
0
static void ShowPackerOpts(INP struct s_packer_opts PackerOpts) {

	vpr_printf(TIO_MESSAGE_INFO, "PackerOpts.allow_early_exit: %s", (PackerOpts.allow_early_exit ? "TRUE\n" : "FALSE\n"));
	vpr_printf(TIO_MESSAGE_INFO, "PackerOpts.allow_unrelated_clustering: %s", (PackerOpts.allow_unrelated_clustering ? "TRUE\n" : "FALSE\n"));
	vpr_printf(TIO_MESSAGE_INFO, "PackerOpts.alpha_clustering: %f\n", PackerOpts.alpha);
	vpr_printf(TIO_MESSAGE_INFO, "PackerOpts.aspect: %f\n", PackerOpts.aspect);
	vpr_printf(TIO_MESSAGE_INFO, "PackerOpts.beta_clustering: %f\n", PackerOpts.beta);
	vpr_printf(TIO_MESSAGE_INFO, "PackerOpts.block_delay: %f\n", PackerOpts.block_delay);
	vpr_printf(TIO_MESSAGE_INFO, "PackerOpts.cluster_seed_type: ");
	switch (PackerOpts.cluster_seed_type) {
	case VPACK_TIMING:
		vpr_printf(TIO_MESSAGE_INFO, "TIMING\n");
		break;
	case VPACK_MAX_INPUTS:
		vpr_printf(TIO_MESSAGE_INFO, "MAX_INPUTS\n");
		break;
	default:
		vpr_printf(TIO_MESSAGE_INFO, "Unknown packer cluster_seed_type\n");
		exit(1);
	}
	vpr_printf(TIO_MESSAGE_INFO, "PackerOpts.connection_driven: %s", (PackerOpts.connection_driven ? "TRUE\n" : "FALSE\n"));
	vpr_printf(TIO_MESSAGE_INFO, "PackerOpts.global_clocks: %s", (PackerOpts.global_clocks ? "TRUE\n" : "FALSE\n"));
	vpr_printf(TIO_MESSAGE_INFO, "PackerOpts.hill_climbing_flag: %s", (PackerOpts.hill_climbing_flag ? "TRUE\n" : "FALSE\n"));
	vpr_printf(TIO_MESSAGE_INFO, "PackerOpts.inter_cluster_net_delay: %f\n", PackerOpts.inter_cluster_net_delay);
	vpr_printf(TIO_MESSAGE_INFO, "PackerOpts.intra_cluster_net_delay: %f\n", PackerOpts.intra_cluster_net_delay);
	vpr_printf(TIO_MESSAGE_INFO, "PackerOpts.recompute_timing_after: %d\n", PackerOpts.recompute_timing_after);
	vpr_printf(TIO_MESSAGE_INFO, "PackerOpts.sweep_hanging_nets_and_inputs: %s", (PackerOpts.sweep_hanging_nets_and_inputs ? "TRUE\n" : "FALSE\n"));
	vpr_printf(TIO_MESSAGE_INFO, "PackerOpts.timing_driven: %s", (PackerOpts.timing_driven ? "TRUE\n" : "FALSE\n"));
	vpr_printf(TIO_MESSAGE_INFO, "\n");
}
Beispiel #22
0
static int find_fanin_rr_node(t_pb *cur_pb, enum PORTS type, int rr_node_index) {
    /* finds first fanin rr_node */
    t_pb *parent, *sibling, *child;
    int net_num, irr_node;
    int i, j, k, ichild_type, ichild_inst;
    int hack_empty_route_through;
    t_pb_graph_node *hack_empty_pb_graph_node;

    hack_empty_route_through = OPEN;

    net_num = rr_node[rr_node_index].net_num;

    parent = cur_pb->parent_pb;

    if (net_num == OPEN) {
        return OPEN;
    }

    if (type == IN_PORT) {
        /* check parent inputs for valid connection */
        for (i = 0; i < parent->pb_graph_node->num_input_ports; i++) {
            for (j = 0; j < parent->pb_graph_node->num_input_pins[i]; j++) {
                irr_node =
                    parent->pb_graph_node->input_pins[i][j].pin_count_in_cluster;
                if (rr_node[irr_node].net_num == net_num) {
                    if (cur_pb->pb_graph_node->pb_type->model
                            && strcmp(
                                cur_pb->pb_graph_node->pb_type->model->name,
                                MODEL_LATCH) == 0) {
                        /* HACK: latches are special becuase LUTs can be set to route-through mode for them
                         I will assume that the input to a LATCH can always come from a parent input pin
                         this only works for hierarchical soft logic structures that follow LUT -> LATCH design
                         must do it better later
                         */
                        return irr_node;
                    }
                    hack_empty_route_through = irr_node;
                    for (k = 0; k < rr_node[irr_node].num_edges; k++) {
                        if (rr_node[irr_node].edges[k] == rr_node_index) {
                            return irr_node;
                        }
                    }
                }
            }
        }
        /* check parent clocks for valid connection */
        for (i = 0; i < parent->pb_graph_node->num_clock_ports; i++) {
            for (j = 0; j < parent->pb_graph_node->num_clock_pins[i]; j++) {
                irr_node =
                    parent->pb_graph_node->clock_pins[i][j].pin_count_in_cluster;
                if (rr_node[irr_node].net_num == net_num) {
                    for (k = 0; k < rr_node[irr_node].num_edges; k++) {
                        if (rr_node[irr_node].edges[k] == rr_node_index) {
                            return irr_node;
                        }
                    }
                }
            }
        }
        /* check siblings for connection */
        if (parent) {
            for (ichild_type = 0;
                    ichild_type
                    < parent->pb_graph_node->pb_type->modes[parent->mode].num_pb_type_children;
                    ichild_type++) {
                for (ichild_inst = 0;
                        ichild_inst
                        < parent->pb_graph_node->pb_type->modes[parent->mode].pb_type_children[ichild_type].num_pb;
                        ichild_inst++) {
                    if (parent->child_pbs[ichild_type]
                            && parent->child_pbs[ichild_type][ichild_inst].name
                            != NULL) {
                        sibling = &parent->child_pbs[ichild_type][ichild_inst];
                        for (i = 0;
                                i < sibling->pb_graph_node->num_output_ports;
                                i++) {
                            for (j = 0;
                                    j
                                    < sibling->pb_graph_node->num_output_pins[i];
                                    j++) {
                                irr_node =
                                    sibling->pb_graph_node->output_pins[i][j].pin_count_in_cluster;
                                if (rr_node[irr_node].net_num == net_num) {
                                    for (k = 0; k < rr_node[irr_node].num_edges;
                                            k++) {
                                        if (rr_node[irr_node].edges[k]
                                                == rr_node_index) {
                                            return irr_node;
                                        }
                                    }
                                }
                            }
                        }
                    } else {
                        /* hack just in case routing is down through an empty cluster */
                        hack_empty_pb_graph_node =
                            &parent->pb_graph_node->child_pb_graph_nodes[ichild_type][0][ichild_inst];
                        for (i = 0;
                                i < hack_empty_pb_graph_node->num_output_ports;
                                i++) {
                            for (j = 0;
                                    j
                                    < hack_empty_pb_graph_node->num_output_pins[i];
                                    j++) {
                                irr_node =
                                    hack_empty_pb_graph_node->output_pins[i][j].pin_count_in_cluster;
                                if (rr_node[irr_node].net_num == net_num) {
                                    for (k = 0; k < rr_node[irr_node].num_edges;
                                            k++) {
                                        if (rr_node[irr_node].edges[k]
                                                == rr_node_index) {
                                            return irr_node;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    } else {
        assert(type == OUT_PORT);

        /* check children for connection */
        for (ichild_type = 0;
                ichild_type
                < cur_pb->pb_graph_node->pb_type->modes[cur_pb->mode].num_pb_type_children;
                ichild_type++) {
            for (ichild_inst = 0;
                    ichild_inst
                    < cur_pb->pb_graph_node->pb_type->modes[cur_pb->mode].pb_type_children[ichild_type].num_pb;
                    ichild_inst++) {
                if (cur_pb->child_pbs[ichild_type]
                        && cur_pb->child_pbs[ichild_type][ichild_inst].name
                        != NULL) {
                    child = &cur_pb->child_pbs[ichild_type][ichild_inst];
                    for (i = 0; i < child->pb_graph_node->num_output_ports;
                            i++) {
                        for (j = 0;
                                j < child->pb_graph_node->num_output_pins[i];
                                j++) {
                            irr_node =
                                child->pb_graph_node->output_pins[i][j].pin_count_in_cluster;
                            if (rr_node[irr_node].net_num == net_num) {
                                for (k = 0; k < rr_node[irr_node].num_edges;
                                        k++) {
                                    if (rr_node[irr_node].edges[k]
                                            == rr_node_index) {
                                        return irr_node;
                                    }
                                }
                                hack_empty_route_through = irr_node;
                            }
                        }
                    }
                }
            }
        }

        /* If not in children, check current pb inputs for valid connection */
        for (i = 0; i < cur_pb->pb_graph_node->num_input_ports; i++) {
            for (j = 0; j < cur_pb->pb_graph_node->num_input_pins[i]; j++) {
                irr_node =
                    cur_pb->pb_graph_node->input_pins[i][j].pin_count_in_cluster;
                if (rr_node[irr_node].net_num == net_num) {
                    hack_empty_route_through = irr_node;
                    for (k = 0; k < rr_node[irr_node].num_edges; k++) {
                        if (rr_node[irr_node].edges[k] == rr_node_index) {
                            return irr_node;
                        }
                    }
                }
            }
        }
    }

    /* TODO: Once I find a way to output routing in empty blocks then code should never reach here, for now, return OPEN */
    vpr_printf(TIO_MESSAGE_INFO, "Use hack in blif dumper (do properly later): connecting net %s #%d for pb %s type %s\n",
               vpack_net[net_num].name, net_num, cur_pb->name,
               cur_pb->pb_graph_node->pb_type->name);

    assert(hack_empty_route_through != OPEN);
    return hack_empty_route_through;
}
Beispiel #23
0
static void ShowRoutingArch(INP struct s_det_routing_arch RoutingArch) {

	vpr_printf(TIO_MESSAGE_INFO, "RoutingArch.directionality: ");
	switch (RoutingArch.directionality) {
	case BI_DIRECTIONAL:
		vpr_printf(TIO_MESSAGE_INFO, "BI_DIRECTIONAL\n");
		break;
	case UNI_DIRECTIONAL:
		vpr_printf(TIO_MESSAGE_INFO, "UNI_DIRECTIONAL\n");
		break;
	default:
		vpr_printf(TIO_MESSAGE_INFO, "<Unknown>\n");
		exit(1);
	}

	vpr_printf(TIO_MESSAGE_INFO, "RoutingArch.switch_block_type: ");
	switch (RoutingArch.switch_block_type) {
	case SUBSET:
		vpr_printf(TIO_MESSAGE_INFO, "SUBSET\n");
		break;
	case WILTON:
		vpr_printf(TIO_MESSAGE_INFO, "WILTON\n");
		break;
	case UNIVERSAL:
		vpr_printf(TIO_MESSAGE_INFO, "UNIVERSAL\n");
		break;
	case FULL:
		vpr_printf(TIO_MESSAGE_INFO, "FULL\n");
		break;
	default:
		vpr_printf(TIO_MESSAGE_ERROR, "switch block type\n");
	}

	vpr_printf(TIO_MESSAGE_INFO, "RoutingArch.Fs: %d\n", RoutingArch.Fs);

	vpr_printf(TIO_MESSAGE_INFO, "\n");
}
Beispiel #24
0
/* 
 * Sets globals: nx, ny
 * Allocs globals: chan_width_x, chan_width_y, grid
 * Depends on num_clbs, pins_per_clb */
void vpr_init_pre_place_and_route(INP t_vpr_setup vpr_setup, INP t_arch Arch) {
	int *num_instances_type, *num_blocks_type;
	int i;
	int current, high, low;
	boolean fit;

	/* Read in netlist file for placement and routing */
	if (vpr_setup.FileNameOpts.NetFile) {
		read_netlist(vpr_setup.FileNameOpts.NetFile, &Arch, &num_blocks, &block,
				&num_nets, &clb_net);
		/* This is done so that all blocks have subblocks and can be treated the same */
		check_netlist();
	}

	/* Output the current settings to console. */
	printClusteredNetlistStats();

	if (vpr_setup.Operation == TIMING_ANALYSIS_ONLY) {
		do_constant_net_delay_timing_analysis(vpr_setup.Timing,
				vpr_setup.constant_net_delay);
	} else {
		current = nint((float)sqrt((float)num_blocks)); /* current is the value of the smaller side of the FPGA */
		low = 1;
		high = -1;

		num_instances_type = (int*) my_calloc(num_types, sizeof(int));
		num_blocks_type = (int*) my_calloc(num_types, sizeof(int));

		for (i = 0; i < num_blocks; i++) {
			num_blocks_type[block[i].type->index]++;
		}

		if (Arch.clb_grid.IsAuto) {
			/* Auto-size FPGA, perform a binary search */
			while (high == -1 || low < high) {
				/* Generate grid */
				if (Arch.clb_grid.Aspect >= 1.0) {
					ny = current;
					nx = nint(current * Arch.clb_grid.Aspect);
				} else {
					nx = current;
					ny = nint(current / Arch.clb_grid.Aspect);
				}
#if DEBUG
				vpr_printf(TIO_MESSAGE_INFO,
						"Auto-sizing FPGA at x = %d y = %d\n", nx, ny);
#endif
				alloc_and_load_grid(num_instances_type, &Arch);
				freeGrid();

				/* Test if netlist fits in grid */
				fit = TRUE;
				for (i = 0; i < num_types; i++) {
					if (num_blocks_type[i] > num_instances_type[i]) {
						fit = FALSE;
						break;
					}
				}

				/* get next value */
				if (!fit) {
					/* increase size of max */
					if (high == -1) {
						current = current * 2;
						if (current > MAX_SHORT) {
							vpr_printf(TIO_MESSAGE_ERROR,
									"FPGA required is too large for current architecture settings.\n");
							exit(1);
						}
					} else {
						if (low == current)
							current++;
						low = current;
						current = low + ((high - low) / 2);
					}
				} else {
					high = current;
					current = low + ((high - low) / 2);
				}
			}
			/* Generate grid */
			if (Arch.clb_grid.Aspect >= 1.0) {
				ny = current;
				nx = nint(current * Arch.clb_grid.Aspect);
			} else {
				nx = current;
				ny = nint(current / Arch.clb_grid.Aspect);
			}
			alloc_and_load_grid(num_instances_type, &Arch);
			vpr_printf(TIO_MESSAGE_INFO, "FPGA auto-sized to x = %d y = %d\n",
					nx, ny);
		} else {
			nx = Arch.clb_grid.W;
			ny = Arch.clb_grid.H;
			alloc_and_load_grid(num_instances_type, &Arch);
		}

		vpr_printf(TIO_MESSAGE_INFO,
				"The circuit will be mapped into a %d x %d array of clbs.\n",
				nx, ny);

		/* Test if netlist fits in grid */
		fit = TRUE;
		for (i = 0; i < num_types; i++) {
			if (num_blocks_type[i] > num_instances_type[i]) {
				fit = FALSE;
				break;
			}
		}
		if (!fit) {
			vpr_printf(TIO_MESSAGE_ERROR,
					"Not enough physical locations for type %s, number of blocks is %d but number of locations is %d.\n",
					type_descriptors[i].name, num_blocks_type[i],
					num_instances_type[i]);
			exit(1);
		}

		vpr_printf(TIO_MESSAGE_INFO, "\n");
		vpr_printf(TIO_MESSAGE_INFO, "Resource usage...\n");
		for (i = 0; i < num_types; i++) {
			vpr_printf(TIO_MESSAGE_INFO,
					"\tNetlist      %d\tblocks of type: %s\n",
					num_blocks_type[i], type_descriptors[i].name);
			vpr_printf(TIO_MESSAGE_INFO,
					"\tArchitecture %d\tblocks of type: %s\n",
					num_instances_type[i], type_descriptors[i].name);
		}
		vpr_printf(TIO_MESSAGE_INFO, "\n");
		chan_width_x = (int *) my_malloc((ny + 1) * sizeof(int));
		chan_width_y = (int *) my_malloc((nx + 1) * sizeof(int));

		free(num_blocks_type);
		free(num_instances_type);
	}
}
Beispiel #25
0
/* This function performs power estimation, and must be called
 * after packing, placement AND routing.  Currently, this
 * will not work when running a partial flow (ex. only routing).
 */
void vpr_power_estimation(t_vpr_setup vpr_setup, t_arch Arch) {
	e_power_ret_code power_ret_code;
	boolean power_error;

	/* Ensure we are only using 1 clock */
	assert(count_netlist_clocks() == 1);

	/* Get the critical path of this clock */
	g_solution_inf.T_crit = get_critical_path_delay() / 1e9;
	assert(g_solution_inf.T_crit > 0.);

	vpr_printf(TIO_MESSAGE_INFO, "\n\nPower Estimation:\n");
	vpr_printf(TIO_MESSAGE_INFO, "-----------------\n");

	vpr_printf(TIO_MESSAGE_INFO, "Initializing power module\n");

	/* Initialize the power module */
	power_error = power_init(vpr_setup.FileNameOpts.PowerFile,
			vpr_setup.FileNameOpts.CmosTechFile, &Arch, &vpr_setup.RoutingArch);
	if (power_error) {
		vpr_printf(TIO_MESSAGE_ERROR, "Power initialization failed.\n");
	}

	if (!power_error) {
		float power_runtime_s;

		vpr_printf(TIO_MESSAGE_INFO, "Running power estimation\n");

		/* Run power estimation */
		power_ret_code = power_total(&power_runtime_s, vpr_setup, &Arch,
				&vpr_setup.RoutingArch);

		/* Check for errors/warnings */
		if (power_ret_code == POWER_RET_CODE_ERRORS) {
			vpr_printf(TIO_MESSAGE_ERROR,
					"Power estimation failed. See power output for error details.\n");
		} else if (power_ret_code == POWER_RET_CODE_WARNINGS) {
			vpr_printf(TIO_MESSAGE_WARNING,
					"Power estimation completed with warnings. See power output for more details.\n");
		} else if (power_ret_code == POWER_RET_CODE_SUCCESS) {
		}
		vpr_printf(TIO_MESSAGE_INFO, "Power estimation took %g seconds\n",
				power_runtime_s);
	}

	/* Uninitialize power module */
	if (!power_error) {
		vpr_printf(TIO_MESSAGE_INFO, "Uninitializing power module\n");
		power_error = power_uninit();
		if (power_error) {
			vpr_printf(TIO_MESSAGE_ERROR, "Power uninitialization failed.\n");
		} else {

		}
	}
	vpr_printf(TIO_MESSAGE_INFO, "\n");
}
Beispiel #26
0
static void clay_logical_equivalence_handling(const t_arch *arch) {
	t_trace **saved_ext_rr_trace_head, **saved_ext_rr_trace_tail;
	t_rr_node *saved_ext_rr_node;
	int num_ext_rr_node, num_ext_nets;
	int i, j;

	for (i = 0; i < num_blocks; i++) {
		clay_reload_ble_locations(i);
	}

	/* Resolve logically equivalent inputs */
	saved_ext_rr_trace_head = trace_head;
	saved_ext_rr_trace_tail = trace_tail;
	saved_ext_rr_node = rr_node;
	num_ext_rr_node = num_rr_nodes;
	num_ext_nets = num_nets;
	num_rr_nodes = 0;
	rr_node = NULL;
	trace_head = NULL;
	trace_tail = NULL;
	free_rr_graph(); /* free all data structures associated with rr_graph */

	alloc_and_load_cluster_legality_checker();
	for (i = 0; i < num_blocks; i++) {
		/* Regenerate rr_graph (note, can be more runtime efficient but this allows for more code reuse)
		 */
		rr_node = block[i].pb->rr_graph;
		num_rr_nodes = block[i].pb->pb_graph_node->total_pb_pins;
		free_legalizer_for_cluster(&block[i], TRUE);
		alloc_and_load_legalizer_for_cluster(&block[i], i, arch);
		reload_intra_cluster_nets(block[i].pb);
		reload_ext_net_rr_terminal_cluster();
		force_post_place_route_cb_input_pins(i);
#ifdef HACK_LUT_PIN_SWAPPING
		/* Resolve rebalancing of LUT inputs */
		clay_lut_input_rebalancing(i, block[i].pb);
#endif

		/* reset rr_graph */
		for (j = 0; j < num_rr_nodes; j++) {
			rr_node[j].occ = 0;
			rr_node[j].prev_edge = OPEN;
			rr_node[j].prev_node = OPEN;
		}
		if (try_breadth_first_route_cluster() == FALSE) {
			vpr_printf(TIO_MESSAGE_ERROR,
					"Failed to resync post routed solution with clustered netlist.\n");
			vpr_printf(TIO_MESSAGE_ERROR, "Cannot recover from error.\n");
			exit(1);
		}
		save_cluster_solution();
		reset_legalizer_for_cluster(&block[i]);
		free_legalizer_for_cluster(&block[i], FALSE);
	}
	free_cluster_legality_checker();

	trace_head = saved_ext_rr_trace_head;
	trace_tail = saved_ext_rr_trace_tail;
	rr_node = saved_ext_rr_node;
	num_rr_nodes = num_ext_rr_node;
	num_nets = num_ext_nets;
}
Beispiel #27
0
void
print_relative_pos_distr(void)
{

	/* Prints out the probability distribution of the relative locations of *
	 * input pins on a net -- i.e. simulates 2-point net distance probability *
	 * distribution.                                                        */
#ifdef PRINT_REL_POS_DISTR
	FILE *out_bin_file;
	relapos_rec_t rp_rec;
#endif /* PRINT_REL_POS_DISTR */

	int inet, len, rp, src_x, src_y, dst_x, dst_y, del_x, del_y, min_del,
	sink_pin, sum;
	int *total_conn;
	int **relapos;
	double **relapos_distr;

	total_conn = (int *)my_malloc((nx + ny + 1) * sizeof(int));
	relapos = (int **)my_malloc((nx + ny + 1) * sizeof(int *));
	relapos_distr = (double **)my_malloc((nx + ny + 1) * sizeof(double *));
	for (len = 0; len <= nx + ny; len++)
	{
		relapos[len] = (int *)my_calloc(len / 2 + 1, sizeof(int));
		relapos_distr[len] =
		(double *)my_calloc((len / 2 + 1), sizeof(double));
	}

	for (inet = 0; inet < num_nets; inet++)
	{
		if (clb_net[inet].is_global == FALSE)
		{

			src_x = block[clb_net[inet].node_block[0]].x;
			src_y = block[clb_net[inet].node_block[0]].y;

			for (sink_pin = 1; sink_pin <= clb_net[inet].num_sinks;
					sink_pin++)
			{
				dst_x = block[clb_net[inet].node_block[sink_pin]].x;
				dst_y = block[clb_net[inet].node_block[sink_pin]].y;

				del_x = ABS_DIFF(dst_x, src_x);
				del_y = ABS_DIFF(dst_y, src_y);

				len = del_x + del_y;

				min_del = (del_x < del_y) ? del_x : del_y;

				if (!(min_del <= (len / 2)))
				{
					vpr_printf(TIO_MESSAGE_ERROR, "Error calculating relative location min_del = %d, len = %d\n",
						min_del, len);
					exit(1);
				}
				else
				{
					relapos[len][min_del]++;
				}
			}
		}
	}

#ifdef PRINT_REL_POS_DISTR
	out_bin_file =
	fopen("/jayar/b/b5/fang/vpr_test/wirelength/relapos2.bin", "rb+");
#endif /* PRINT_REL_POS_DISTR */

	for (len = 0; len <= nx + ny; len++)
	{
		sum = 0;
		for (rp = 0; rp <= len / 2; rp++)
		{
			sum += relapos[len][rp];
		}
		if (sum != 0)
		{
#ifdef PRINT_REL_POS_DISTR
			fseek(out_bin_file, sizeof(relapos_rec_t) * len,
					SEEK_SET);
			fread(&rp_rec, sizeof(relapos_rec_t), 1, out_bin_file);
#endif /* PRINT_REL_POS_DISTR */

			for (rp = 0; rp <= len / 2; rp++)
			{

				relapos_distr[len][rp] =
				(double)relapos[len][rp] / (double)sum;

				/* updating the binary record at "len" */
#ifdef PRINT_REL_POS_DISTR
				vpr_printf(TIO_MESSAGE_ERROR, "old %d increased by %d\n", rp_rec.num_rp[rp], relapos[len][rp]);
				rp_rec.num_rp[rp] += relapos[len][rp];
				vpr_printf(TIO_MESSAGE_ERROR, "becomes %d\n", rp_rec.num_rp[rp]);
#endif /* PRINT_REL_POS_DISTR */
			}
#ifdef PRINT_REL_POS_DISTR
			/* write back the updated record at "len" */
			fseek(out_bin_file, sizeof(relapos_rec_t) * len,
					SEEK_SET);
			fwrite(&rp_rec, sizeof(relapos_rec_t), 1, out_bin_file);
#endif /* PRINT_REL_POS_DISTR */

		}
		total_conn[len] = sum;
	}

	fprintf(stdout, "Source to sink relative positions:\n");
	for (len = 1; len <= nx + ny; len++)
	{
		if (total_conn[len] != 0)
		{
			fprintf(stdout, "Of 2-pin distance %d exists %d\n\n", len,
					total_conn[len]);
			for (rp = 0; rp <= len / 2; rp++)
			{
				fprintf(stdout, "\trp%d\t%d\t\t(%.5f)\n", rp,
						relapos[len][rp], relapos_distr[len][rp]);
			}
			fprintf(stdout, "----------------\n");
		}
	}

	free((void *)total_conn);
	for (len = 0; len <= nx + ny; len++)
	{
		free((void *)relapos[len]);
		free((void *)relapos_distr[len]);
	}
	free((void *)relapos);
	free((void *)relapos_distr);

#ifdef PRINT_REL_POS_DISTR
	fclose(out_bin_file);
#endif /* PRINT_REL_POS_DISTR */
}
Beispiel #28
0
/* Display help screen */
void vpr_print_usage(void) {
	vpr_printf(TIO_MESSAGE_INFO,
			"Usage:  vpr fpga_architecture.xml circuit_name [Options ...]\n");
	vpr_printf(TIO_MESSAGE_INFO, "\n");
	vpr_printf(TIO_MESSAGE_INFO,
			"General Options:  [--nodisp] [--auto <int>] [--pack]\n");
	vpr_printf(TIO_MESSAGE_INFO,
			"\t[--place] [--route] [--timing_analyze_only_with_net_delay <float>]\n");
	vpr_printf(TIO_MESSAGE_INFO,
			"\t[--fast] [--full_stats] [--timing_analysis on | off] [--outfile_prefix <string>]\n");
	vpr_printf(TIO_MESSAGE_INFO,
			"\t[--blif_file <string>][--net_file <string>][--place_file <string>]\n");
	vpr_printf(TIO_MESSAGE_INFO,
			"\t[--route_file <string>][--sdc_file <string>][--echo_file on | off]\n");
	vpr_printf(TIO_MESSAGE_INFO, "\n");
	vpr_printf(TIO_MESSAGE_INFO, "Packer Options:\n");
	/*    vpr_printf(TIO_MESSAGE_INFO, "\t[-global_clocks on|off]\n");
	 vpr_printf(TIO_MESSAGE_INFO, "\t[-hill_climbing on|off]\n");
	 vpr_printf(TIO_MESSAGE_INFO, "\t[-sweep_hanging_nets_and_inputs on|off]\n"); */
	vpr_printf(TIO_MESSAGE_INFO, "\t[--timing_driven_clustering on|off]\n");
	vpr_printf(TIO_MESSAGE_INFO,
			"\t[--cluster_seed_type timing|max_inputs] [--alpha_clustering <float>] [--beta_clustering <float>]\n");
	/*    vpr_printf(TIO_MESSAGE_INFO, "\t[-recompute_timing_after <int>] [-cluster_block_delay <float>]\n"); */
	vpr_printf(TIO_MESSAGE_INFO, "\t[--allow_unrelated_clustering on|off]\n");
	/*    vpr_printf(TIO_MESSAGE_INFO, "\t[-allow_early_exit on|off]\n"); 
	 vpr_printf(TIO_MESSAGE_INFO, "\t[-intra_cluster_net_delay <float>] \n");
	 vpr_printf(TIO_MESSAGE_INFO, "\t[-inter_cluster_net_delay <float>] \n"); */
	vpr_printf(TIO_MESSAGE_INFO,
			"\t[--connection_driven_clustering on|off] \n");
	vpr_printf(TIO_MESSAGE_INFO, "\n");
	vpr_printf(TIO_MESSAGE_INFO, "Placer Options:\n");
	vpr_printf(TIO_MESSAGE_INFO,
			"\t[--place_algorithm bounding_box | net_timing_driven | path_timing_driven]\n");
	vpr_printf(TIO_MESSAGE_INFO, "\t[--init_t <float>] [--exit_t <float>]\n");
	vpr_printf(TIO_MESSAGE_INFO,
			"\t[--alpha_t <float>] [--inner_num <float>] [--seed <int>]\n");
	vpr_printf(TIO_MESSAGE_INFO, "\t[--place_cost_exp <float>]\n");
	vpr_printf(TIO_MESSAGE_INFO, "\t[--place_chan_width <int>] \n");
	vpr_printf(TIO_MESSAGE_INFO, "\t[--fix_pins random | <file.pads>]\n");
	vpr_printf(TIO_MESSAGE_INFO, "\t[--enable_timing_computations on | off]\n");
	vpr_printf(TIO_MESSAGE_INFO, "\t[--block_dist <int>]\n");
	vpr_printf(TIO_MESSAGE_INFO, "\n");
	vpr_printf(TIO_MESSAGE_INFO,
			"Placement Options Valid Only for Timing-Driven Placement:\n");
	vpr_printf(TIO_MESSAGE_INFO, "\t[--timing_tradeoff <float>]\n");
	vpr_printf(TIO_MESSAGE_INFO, "\t[--recompute_crit_iter <int>]\n");
	vpr_printf(TIO_MESSAGE_INFO, "\t[--inner_loop_recompute_divider <int>]\n");
	vpr_printf(TIO_MESSAGE_INFO, "\t[--td_place_exp_first <float>]\n");
	vpr_printf(TIO_MESSAGE_INFO, "\t[--td_place_exp_last <float>]\n");
	vpr_printf(TIO_MESSAGE_INFO, "\n");
	vpr_printf(TIO_MESSAGE_INFO,
			"Router Options:  [-max_router_iterations <int>] [-bb_factor <int>]\n");
	vpr_printf(TIO_MESSAGE_INFO,
			"\t[--initial_pres_fac <float>] [--pres_fac_mult <float>]\n");
	vpr_printf(TIO_MESSAGE_INFO,
			"\t[--acc_fac <float>] [--first_iter_pres_fac <float>]\n");
	vpr_printf(TIO_MESSAGE_INFO,
			"\t[--bend_cost <float>] [--route_type global | detailed]\n");
	vpr_printf(TIO_MESSAGE_INFO,
			"\t[--verify_binary_search] [--route_chan_width <int>]\n");
	vpr_printf(TIO_MESSAGE_INFO,
			"\t[--router_algorithm breadth_first | timing_driven]\n");
	vpr_printf(TIO_MESSAGE_INFO,
			"\t[--router_algorithm breadth_first | timing_driven | Read_Route]\n");		
	vpr_printf(TIO_MESSAGE_INFO,
			"\t[--base_cost_type intrinsic_delay | delay_normalized | demand_only]\n");
	vpr_printf(TIO_MESSAGE_INFO, "\n");
	vpr_printf(TIO_MESSAGE_INFO,
			"Routing options valid only for timing-driven routing:\n");
	vpr_printf(TIO_MESSAGE_INFO,
			"\t[--astar_fac <float>] [--max_criticality <float>]\n");
	vpr_printf(TIO_MESSAGE_INFO, "\t[--criticality_exp <float>]\n");
	
	vpr_printf(TIO_MESSAGE_INFO, "OVERLAY NETWORK options:");
    vpr_printf(TIO_MESSAGE_INFO, "\t[--inc_instrument_type overlay]");
    vpr_printf(TIO_MESSAGE_INFO, "\t[--inc_router_algorithm breadth_first | timing_driven | directed_search | read_route]");
    vpr_printf(TIO_MESSAGE_INFO, "\t[--inc_route_file <file>.route]"); 
    vpr_printf(TIO_MESSAGE_INFO, "\t[--inc_match_file <file>.match]"); 
    vpr_printf(TIO_MESSAGE_INFO, "\t[--inc_le_symmetry on|off] [--inc_best_effort on|off] [--inc_dump_all_nets]");

	vpr_printf(TIO_MESSAGE_INFO, "\n");
}
Beispiel #29
0
static void print_complete_net_trace(t_trace* trace, const char *file_name) {
	FILE *fp;
	int iblock, inode, iprev_block;
	t_trace *current;
	t_rr_node *local_rr_graph;
	const char *name_type[] = { "SOURCE", "SINK", "IPIN", "OPIN", "CHANX",
			"CHANY", "INTRA_CLUSTER_EDGE" };
	int i;

	fp = my_fopen(file_name, "w", 0);

	for (i = 0; i < num_logical_nets; i++) {
		current = &trace[i];
		iprev_block = OPEN;

		fprintf(fp, "Net %s (%d)\n\n", vpack_net[i].name, i);
		while (current != NULL) {
			iblock = current->iblock;
			inode = current->index;
			if (iblock != OPEN) {
				if (iprev_block != iblock) {
					iprev_block = iblock;
					fprintf(fp, "Block %s (%d) (%d, %d, %d):\n",
							block[iblock].name, iblock, block[iblock].x,
							block[iblock].y, block[iblock].z);
				}
				local_rr_graph = block[iblock].pb->rr_graph;
				fprintf(fp, "\tNode:\t%d\t%s[%d].%s[%d]", inode,
						local_rr_graph[inode].pb_graph_pin->parent_node->pb_type->name,
						local_rr_graph[inode].pb_graph_pin->parent_node->placement_index,
						local_rr_graph[inode].pb_graph_pin->port->name,
						local_rr_graph[inode].pb_graph_pin->pin_number);
			} else {
				fprintf(fp, "Node:\t%d\t%6s (%d,%d) ", inode,
						name_type[(int) rr_node[inode].type],
						rr_node[inode].xlow, rr_node[inode].ylow);

				if ((rr_node[inode].xlow != rr_node[inode].xhigh)
						|| (rr_node[inode].ylow != rr_node[inode].yhigh))
					fprintf(fp, "to (%d,%d) ", rr_node[inode].xhigh,
							rr_node[inode].yhigh);

				switch (rr_node[inode].type) {

				case IPIN:
				case OPIN:
					if (grid[rr_node[inode].xlow][rr_node[inode].ylow].type
							== IO_TYPE) {
						fprintf(fp, " Pad: ");
					} else { /* IO Pad. */
						fprintf(fp, " Pin: ");
					}
					break;

				case CHANX:
				case CHANY:
					fprintf(fp, " Track: ");
					break;

				case SOURCE:
				case SINK:
					if (grid[rr_node[inode].xlow][rr_node[inode].ylow].type
							== IO_TYPE) {
						fprintf(fp, " Pad: ");
					} else { /* IO Pad. */
						fprintf(fp, " Class: ");
					}
					break;

				default:
					vpr_printf(TIO_MESSAGE_ERROR,
							"in print_route: Unexpected traceback element type: %d (%s).\n",
							rr_node[inode].type,
							name_type[rr_node[inode].type]);
					exit(1);
					break;
				}

				fprintf(fp, "%d  ", rr_node[inode].ptc_num);

				/* Uncomment line below if you're debugging and want to see the switch types *
				 * used in the routing.                                                      */
				/*          fprintf (fp, "Switch: %d", tptr->iswitch);    */

				fprintf(fp, "\n");
			}
			current = current->next;
		}
		fprintf(fp, "\n");
	}
	fclose(fp);
}
Beispiel #30
0
static void print_primitive(FILE *fpout, int iblk) {
    t_pb *pb;
    int clb_index;
    int i, j, node_index;
    int in_port_index, out_port_index, clock_port_index;
    struct s_linked_vptr *truth_table;
    const t_pb_type *pb_type;

    pb = logical_block[iblk].pb;
    pb_type = pb->pb_graph_node->pb_type;
    clb_index = logical_block[iblk].clb_index;

    if (logical_block[iblk].type == VPACK_INPAD
            || logical_block[iblk].type == VPACK_OUTPAD) {
        /* do nothing */
    } else if (logical_block[iblk].type == VPACK_LATCH) {
        fprintf(fpout, ".latch ");

        in_port_index = 0;
        out_port_index = 0;
        clock_port_index = 0;
        for (i = 0; i < pb_type->num_ports; i++) {
            if (pb_type->ports[i].type == IN_PORT
                    && pb_type->ports[i].is_clock == FALSE) {
                assert(pb_type->ports[i].num_pins == 1);
                assert(logical_block[iblk].input_nets[i][0] != OPEN);
                node_index =
                    pb->pb_graph_node->input_pins[in_port_index][0].pin_count_in_cluster;
                fprintf(fpout, "clb_%d_rr_node_%d ", clb_index,
                        find_fanin_rr_node(pb, pb_type->ports[i].type,
                                           node_index));
                in_port_index++;
            }
        }
        for (i = 0; i < pb_type->num_ports; i++) {
            if (pb_type->ports[i].type == OUT_PORT) {
                assert(pb_type->ports[i].num_pins == 1 && out_port_index == 0);
                node_index =
                    pb->pb_graph_node->output_pins[out_port_index][0].pin_count_in_cluster;
                fprintf(fpout, "clb_%d_rr_node_%d re ", clb_index, node_index);
                out_port_index++;
            }
        }
        for (i = 0; i < pb_type->num_ports; i++) {
            if (pb_type->ports[i].type == IN_PORT
                    && pb_type->ports[i].is_clock == TRUE) {
                assert(logical_block[iblk].clock_net != OPEN);
                node_index =
                    pb->pb_graph_node->clock_pins[clock_port_index][0].pin_count_in_cluster;
                fprintf(fpout, "clb_%d_rr_node_%d 2", clb_index,
                        find_fanin_rr_node(pb, pb_type->ports[i].type,
                                           node_index));
                clock_port_index++;
            }
        }
        fprintf(fpout, "\n");
    } else if (logical_block[iblk].type == VPACK_COMB) {
        if (strcmp(logical_block[iblk].model->name, "names") == 0) {
            fprintf(fpout, ".names ");
            in_port_index = 0;
            out_port_index = 0;
            for (i = 0; i < pb_type->num_ports; i++) {
                if (pb_type->ports[i].type == IN_PORT
                        && pb_type->ports[i].is_clock == FALSE) {
                    for (j = 0; j < pb_type->ports[i].num_pins; j++) {
                        if (logical_block[iblk].input_nets[in_port_index][j] != OPEN) {
                            node_index =
                                pb->pb_graph_node->input_pins[in_port_index][j].pin_count_in_cluster;
                            fprintf(fpout, "clb_%d_rr_node_%d ", clb_index,
                                    find_fanin_rr_node(pb,
                                                       pb_type->ports[i].type,
                                                       node_index));
                        }
                    }
                    in_port_index++;
                }
            }
            for (i = 0; i < pb_type->num_ports; i++) {
                if (pb_type->ports[i].type == OUT_PORT) {
                    for (j = 0; j < pb_type->ports[i].num_pins; j++) {
                        node_index =
                            pb->pb_graph_node->output_pins[out_port_index][j].pin_count_in_cluster;
                        fprintf(fpout, "clb_%d_rr_node_%d\n", clb_index,
                                node_index);
                    }
                    out_port_index++;
                }
            }
            truth_table = logical_block[iblk].truth_table;
            while (truth_table) {
                fprintf(fpout, "%s\n", (char *) truth_table->data_vptr);
                truth_table = truth_table->next;
            }
        } else {
            vpr_printf(TIO_MESSAGE_WARNING, "TODO: Implement blif dumper for subckt %s model %s", logical_block[iblk].name, logical_block[iblk].model->name);
        }
    }
}