void read_net (char *net_file, t_subblock_data *subblock_data_ptr) { /* Main routine that parses a netlist file in my (.net) format. */ char buf[BUFSIZE], *ptr; int doall; FILE *fp_net; /* Make two variables below accessible anywhere in the module because I'm * * too lazy to pass them all over the place. */ max_subblocks_per_block = subblock_data_ptr->max_subblocks_per_block; subblock_lut_size = subblock_data_ptr->subblock_lut_size; fp_net = my_fopen (net_file, "r", 0); /* First pass builds the symbol table and counts the number of pins * * on each net. Then I allocate exactly the right amount of storage * * for each net. Finally, the second pass loads the block and net * * arrays. */ for (doall=0;doall<=1;doall++) { /* Pass number. */ init_parse(doall); linenum = 0; /* Reset line number. */ ptr = my_fgets (buf, BUFSIZE, fp_net); while (ptr != NULL) { ptr = get_tok (buf, doall, fp_net); } rewind (fp_net); /* Start at beginning of file again */ } fclose(fp_net); /* Return the three data structures below through subblock_data_ptr. */ subblock_data_ptr->subblock_inf = subblock_inf; subblock_data_ptr->num_subblocks_per_block = num_subblocks_per_block; subblock_data_ptr->chunk_head_ptr = ch_subblock_head_ptr; check_netlist (subblock_data_ptr, num_driver); free_parse(); }
/*--------------------------------------------------------------------------- * (function: do_high_level_synthesis) *-------------------------------------------------------------------------*/ void do_high_level_synthesis() { double elaboration_time = wall_time(); printf("--------------------------------------------------------------------\n"); printf("High-level synthesis Begin\n"); /* Perform any initialization routines here */ #ifdef VPR6 find_hard_multipliers(); find_hard_adders(); //find_hard_adders_for_sub(); register_hard_blocks(); #endif global_param_table_sc = sc_new_string_cache(); /* parse to abstract syntax tree */ printf("Parser starting - we'll create an abstract syntax tree. " "Note this tree can be viewed using GraphViz (see documentation)\n"); parse_to_ast(); /* Note that the entry point for ast optimzations is done per module with the * function void next_parsed_verilog_file(ast_node_t *file_items_list) */ /* after the ast is made potentiatlly do tagging for downstream links to verilog */ if (global_args.high_level_block != NULL) { add_tag_data(); } /* Now that we have a parse tree (abstract syntax tree [ast]) of * the Verilog we want to make into a netlist. */ printf("Converting AST into a Netlist. " "Note this netlist can be viewed using GraphViz (see documentation)\n"); create_netlist(); // Can't levelize yet since the large muxes can look like combinational loops when they're not check_netlist(verilog_netlist); /* point for all netlist optimizations. */ printf("Performing Optimizations of the Netlist\n"); netlist_optimizations_top(verilog_netlist); if (configuration.output_netlist_graphs ) { /* Path is where we are */ graphVizOutputNetlist(configuration.debug_output_path, "optimized", 1, verilog_netlist); } /* point where we convert netlist to FPGA or other hardware target compatible format */ printf("Performing Partial Map to target device\n"); partial_map_top(verilog_netlist); #ifdef VPR5 /* check for problems in the partial mapped netlist */ printf("Check for liveness and combinational loops\n"); levelize_and_check_for_combinational_loop_and_liveness(TRUE, verilog_netlist); #endif /* point for outputs. This includes soft and hard mapping all structures to the * target format. Some of these could be considred optimizations */ printf("Outputting the netlist to the specified output format\n"); output_top(verilog_netlist); elaboration_time = wall_time() - elaboration_time; printf("Successful High-level synthesis by Odin in "); print_time(elaboration_time); printf("\n"); printf("--------------------------------------------------------------------\n"); // FIXME: free contents? sc_free_string_cache(global_param_table_sc); }
/* * 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); } }