diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/module_builder/build_grid_modules.cpp b/vpr7_x2p/vpr/SRC/fpga_x2p/module_builder/build_grid_modules.cpp new file mode 100644 index 000000000..68579a252 --- /dev/null +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/module_builder/build_grid_modules.cpp @@ -0,0 +1,1124 @@ +/******************************************************************** + * This file includes functions to print Verilog modules for a Grid + * (CLBs, I/Os, heterogeneous blocks etc.) + *******************************************************************/ +/* System header files */ +#include + +/* Header files from external libs */ +#include "vtr_geometry.h" +#include "util.h" +#include "vtr_assert.h" +#include "circuit_library_utils.h" + +/* Header files for VPR */ +#include "vpr_types.h" +#include "globals.h" + +/* Header files for FPGA X2P tool suite */ +#include "fpga_x2p_naming.h" +#include "fpga_x2p_types.h" +#include "fpga_x2p_utils.h" +#include "fpga_x2p_pbtypes_utils.h" +#include "module_manager_utils.h" +#include "fpga_x2p_globals.h" + +/* Header files for Verilog generator */ +#include "verilog_global.h" +#include "verilog_utils.h" +#include "build_grid_modules.h" + +/******************************************************************** + * Find the side where I/O pins locate on a grid I/O block + * 1. I/O grids on the top side of FPGA only have ports on its bottom side + * 2. I/O grids on the right side of FPGA only have ports on its left side + * 3. I/O grids on the bottom side of FPGA only have ports on its top side + * 4. I/O grids on the left side of FPGA only have ports on its right side + *******************************************************************/ +static +e_side find_grid_module_pin_side(t_type_ptr grid_type_descriptor, + const e_side& border_side) { + VTR_ASSERT(IO_TYPE == grid_type_descriptor); + Side side_manager(border_side); + return side_manager.get_opposite(); +} + +/******************************************************************** + * Add ports/pins to a grid module + * This function will iterate over all the pins that are defined + * in type_descripter and give a name by its height, side and index + * + * In particular, for I/O grid, only part of the ports on required + * on a specific side. + *******************************************************************/ +static +void add_grid_module_pb_type_ports(ModuleManager& module_manager, + const ModuleId& grid_module, + t_type_ptr grid_type_descriptor, + const e_side& border_side) { + /* Ensure that we have a valid grid_type_descriptor */ + VTR_ASSERT(NULL != grid_type_descriptor); + + /* Find the pin side for I/O grids*/ + std::vector grid_pin_sides; + /* For I/O grids, we care only one side + * Otherwise, we will iterate all the 4 sides + */ + if (IO_TYPE == grid_type_descriptor) { + grid_pin_sides.push_back(find_grid_module_pin_side(grid_type_descriptor, border_side)); + } else { + grid_pin_sides = {TOP, RIGHT, BOTTOM, LEFT}; + } + + /* Create a map between pin class type and grid pin direction */ + std::map pin_type2type_map; + pin_type2type_map[RECEIVER] = ModuleManager::MODULE_INPUT_PORT; + pin_type2type_map[DRIVER] = ModuleManager::MODULE_OUTPUT_PORT; + + /* Iterate over sides, height and pins */ + for (const e_side& side : grid_pin_sides) { + for (int iheight = 0; iheight < grid_type_descriptor->height; ++iheight) { + for (int ipin = 0; ipin < grid_type_descriptor->num_pins; ++ipin) { + if (1 != grid_type_descriptor->pinloc[iheight][side][ipin]) { + continue; + } + /* Reach here, it means this pin is on this side */ + int class_id = grid_type_descriptor->pin_class[ipin]; + e_pin_type pin_class_type = grid_type_descriptor->class_inf[class_id].type; + /* Generate the pin name, + * we give a empty coordinate but it will not be used (see details in the function + */ + vtr::Point dummy_coordinate; + std::string port_name = generate_grid_port_name(dummy_coordinate, iheight, side, ipin, false); + BasicPort grid_port(port_name, 0, 0); + /* Add the port to the module */ + module_manager.add_port(grid_module, grid_port, pin_type2type_map[pin_class_type]); + } + } + } +} + +/******************************************************************** + * Add module nets to connect a port of child pb_module + * to the grid module + *******************************************************************/ +static +void add_grid_module_net_connect_pb_graph_pin(ModuleManager& module_manager, + const ModuleId& grid_module, + const ModuleId& child_module, + const size_t& child_instance, + t_type_ptr grid_type_descriptor, + t_pb_graph_pin* pb_graph_pin, + const e_side& border_side, + const enum e_spice_pin2pin_interc_type& pin2pin_interc_type) { + /* Find the pin side for I/O grids*/ + std::vector grid_pin_sides; + /* For I/O grids, we care only one side + * Otherwise, we will iterate all the 4 sides + */ + if (IO_TYPE == grid_type_descriptor) { + grid_pin_sides.push_back(find_grid_module_pin_side(grid_type_descriptor, border_side)); + } else { + grid_pin_sides.push_back(TOP); + grid_pin_sides.push_back(RIGHT); + grid_pin_sides.push_back(BOTTOM); + grid_pin_sides.push_back(LEFT); + } + + /* num_pins/capacity = the number of pins that each type_descriptor has. + * Capacity defines the number of type_descriptors in each grid + * so the pin index at grid level = pin_index_in_type_descriptor + * + type_descriptor_index_in_capacity * num_pins_per_type_descriptor + */ + size_t grid_pin_index = pb_graph_pin->pin_count_in_cluster + + child_instance * grid_type_descriptor->num_pins / grid_type_descriptor->capacity; + int pin_height = grid_type_descriptor->pin_height[grid_pin_index]; + for (const e_side& side : grid_pin_sides) { + if (1 != grid_type_descriptor->pinloc[pin_height][side][grid_pin_index]) { + continue; + } + /* Reach here, it means this pin is on this side */ + /* Create a net to connect the grid pin to child module pin */ + ModuleNetId net = module_manager.create_module_net(grid_module); + /* Find the port in grid_module */ + vtr::Point dummy_coordinate; + std::string grid_port_name = generate_grid_port_name(dummy_coordinate, pin_height, side, grid_pin_index, false); + ModulePortId grid_module_port_id = module_manager.find_module_port(grid_module, grid_port_name); + VTR_ASSERT(true == module_manager.valid_module_port_id(grid_module, grid_module_port_id)); + /* Grid port always has only 1 pin, it is assumed when adding these ports to the module + * if you need a change, please also change the port adding codes + */ + size_t grid_module_pin_id = 0; + /* Find the port in child module */ + std::string child_module_port_name = generate_pb_type_port_name(pb_graph_pin->port); + ModulePortId child_module_port_id = module_manager.find_module_port(child_module, child_module_port_name); + VTR_ASSERT(true == module_manager.valid_module_port_id(child_module, child_module_port_id)); + size_t child_module_pin_id = pb_graph_pin->pin_number; + /* Add net sources and sinks: + * For input-to-input connection, net_source is grid pin, while net_sink is pb_graph_pin + * For output-to-output connection, net_source is pb_graph_pin, while net_sink is grid pin + */ + switch (pin2pin_interc_type) { + case INPUT2INPUT_INTERC: + module_manager.add_module_net_source(grid_module, net, grid_module, 0, grid_module_port_id, grid_module_pin_id); + module_manager.add_module_net_sink(grid_module, net, child_module, child_instance, child_module_port_id, child_module_pin_id); + break; + case OUTPUT2OUTPUT_INTERC: + module_manager.add_module_net_source(grid_module, net, child_module, child_instance, child_module_port_id, child_module_pin_id); + module_manager.add_module_net_sink(grid_module, net, grid_module, 0, grid_module_port_id, grid_module_pin_id); + break; + default: + vpr_printf(TIO_MESSAGE_ERROR, + "(File:%s, [LINE%d]) Invalid pin-to-pin interconnection type!\n", + __FILE__, __LINE__); + exit(1); + } + } +} + + +/******************************************************************** + * Add module nets to connect ports/pins of a grid module + * to its child modules + * This function will iterate over all the pins that are defined + * in type_descripter and find the corresponding pin in the top + * pb_graph_node of the grid + *******************************************************************/ +static +void add_grid_module_nets_connect_pb_type_ports(ModuleManager& module_manager, + const ModuleId& grid_module, + const ModuleId& child_module, + const size_t& child_instance, + t_type_ptr grid_type_descriptor, + const e_side& border_side) { + /* Ensure that we have a valid grid_type_descriptor */ + VTR_ASSERT(NULL != grid_type_descriptor); + t_pb_graph_node* top_pb_graph_node = grid_type_descriptor->pb_graph_head; + VTR_ASSERT(NULL != top_pb_graph_node); + + for (int iport = 0; iport < top_pb_graph_node->num_input_ports; ++iport) { + for (int ipin = 0; ipin < top_pb_graph_node->num_input_pins[iport]; ++ipin) { + add_grid_module_net_connect_pb_graph_pin(module_manager, grid_module, + child_module, child_instance, + grid_type_descriptor, + &(top_pb_graph_node->input_pins[iport][ipin]), + border_side, + INPUT2INPUT_INTERC); + + } + } + + for (int iport = 0; iport < top_pb_graph_node->num_output_ports; ++iport) { + for (int ipin = 0; ipin < top_pb_graph_node->num_output_pins[iport]; ++ipin) { + add_grid_module_net_connect_pb_graph_pin(module_manager, grid_module, + child_module, child_instance, + grid_type_descriptor, + &(top_pb_graph_node->output_pins[iport][ipin]), + border_side, + OUTPUT2OUTPUT_INTERC); + } + } + + for (int iport = 0; iport < top_pb_graph_node->num_clock_ports; ++iport) { + for (int ipin = 0; ipin < top_pb_graph_node->num_clock_pins[iport]; ++ipin) { + add_grid_module_net_connect_pb_graph_pin(module_manager, grid_module, + child_module, child_instance, + grid_type_descriptor, + &(top_pb_graph_node->clock_pins[iport][ipin]), + border_side, + INPUT2INPUT_INTERC); + } + } +} + +/******************************************************************** + * Print Verilog modules of a primitive node in the pb_graph_node graph + * This generic function can support all the different types of primitive nodes + * i.e., Look-Up Tables (LUTs), Flip-flops (FFs) and hard logic blocks such as adders. + * + * The Verilog module will consist of two parts: + * 1. Logic module of the primitive node + * This module performs the logic function of the block + * 2. Memory module of the primitive node + * This module stores the configuration bits for the logic module + * if the logic module is a programmable resource, such as LUT + * + * Verilog module structure: + * + * Primitive block + * +---------------------------------------+ + * | | + * | +---------+ +---------+ | + * in |----->| |--->| |<------|configuration lines + * | | Logic |... | Memory | | + * out|<-----| |--->| | | + * | +---------+ +---------+ | + * | | + * +---------------------------------------+ + * + *******************************************************************/ +static +void build_primitive_block_module(ModuleManager& module_manager, + const CircuitLibrary& circuit_lib, + const e_sram_orgz& sram_orgz_type, + const CircuitModelId& sram_model, + t_pb_graph_node* primitive_pb_graph_node, + const e_side& io_side) { + /* Ensure a valid pb_graph_node */ + if (NULL == primitive_pb_graph_node) { + vpr_printf(TIO_MESSAGE_ERROR, + "(File:%s,[LINE%d]) Invalid primitive_pb_graph_node!\n", + __FILE__, __LINE__); + exit(1); + } + + /* Find the circuit model id linked to the pb_graph_node */ + CircuitModelId& primitive_model = primitive_pb_graph_node->pb_type->circuit_model; + + /* Generate the module name for this primitive pb_graph_node*/ + std::string primitive_module_name_prefix = generate_grid_block_prefix(std::string(grid_verilog_file_name_prefix), io_side); + std::string primitive_module_name = generate_physical_block_module_name(primitive_module_name_prefix, primitive_pb_graph_node->pb_type); + + /* Create a module of the primitive LUT and register it to module manager */ + ModuleId primitive_module = module_manager.add_module(primitive_module_name); + /* Ensure that the module has been created and thus unique! */ + VTR_ASSERT(ModuleId::INVALID() != primitive_module); + + /* Find the global ports required by the primitive node, and add them to the module */ + std::vector primitive_model_global_ports = circuit_lib.model_global_ports(primitive_model, true); + for (auto port : primitive_model_global_ports) { + /* The global I/O of the FPGA has a special name */ + BasicPort module_port(circuit_lib.port_lib_name(port), circuit_lib.port_size(port)); + module_manager.add_port(primitive_module, module_port, ModuleManager::MODULE_GLOBAL_PORT); + } + + /* Find the inout ports required by the primitive node, and add them to the module + * This is mainly due to the I/O blocks, which have inout ports for the top-level fabric + */ + if (SPICE_MODEL_IOPAD == circuit_lib.model_type(primitive_model)) { + std::vector primitive_model_inout_ports = circuit_lib.model_ports_by_type(primitive_model, SPICE_MODEL_PORT_INOUT); + for (auto port : primitive_model_inout_ports) { + BasicPort module_port(generate_fpga_global_io_port_name(std::string(gio_inout_prefix), circuit_lib, primitive_model), circuit_lib.port_size(port)); + module_manager.add_port(primitive_module, module_port, ModuleManager::MODULE_GPIO_PORT); + } + } + /* Note: to cooperate with the pb_type hierarchy and connections, we add the port of primitive pb_type here. + * Since we have linked pb_type ports to circuit models when setting up FPGA-X2P, + * no ports of the circuit model will be missing here + */ + add_primitive_pb_type_ports_to_module_manager(module_manager, primitive_module, primitive_pb_graph_node->pb_type); + + /* Add configuration ports */ + /* Shared SRAM ports*/ + size_t num_shared_config_bits = find_circuit_num_shared_config_bits(circuit_lib, primitive_model, sram_orgz_type); + if (0 < num_shared_config_bits) { + /* Check: this SRAM organization type must be memory-bank ! */ + VTR_ASSERT( SPICE_SRAM_MEMORY_BANK == sram_orgz_type ); + /* Generate a list of ports */ + add_reserved_sram_ports_to_module_manager(module_manager, primitive_module, + num_shared_config_bits); + } + + /* Regular (independent) SRAM ports */ + size_t num_config_bits = find_circuit_num_config_bits(circuit_lib, primitive_model); + if (0 < num_config_bits) { + add_sram_ports_to_module_manager(module_manager, primitive_module, + circuit_lib, sram_model, sram_orgz_type, + num_config_bits); + } + + /* Find the module id in the module manager */ + ModuleId logic_module = module_manager.find_module(circuit_lib.model_name(primitive_model)); + VTR_ASSERT(ModuleId::INVALID() != logic_module); + size_t logic_instance_id = module_manager.num_instance(primitive_module, logic_module); + /* Add the logic module as a child of primitive module */ + module_manager.add_child_module(primitive_module, logic_module); + + /* Add nets to connect the logic model ports to pb_type ports */ + add_primitive_pb_type_module_nets(module_manager, primitive_module, logic_module, logic_instance_id, circuit_lib, primitive_pb_graph_node->pb_type); + + /* Add the associated memory module as a child of primitive module */ + std::string memory_module_name = generate_memory_module_name(circuit_lib, primitive_model, sram_model, std::string(verilog_mem_posfix)); + ModuleId memory_module = module_manager.find_module(memory_module_name); + + /* Vectors to record all the memory modules have been added + * They are used to add module nets of configuration bus + */ + std::vector memory_modules; + std::vector memory_instances; + + /* If there is no memory module required, we can skip the assocated net addition */ + if (ModuleId::INVALID() != memory_module) { + size_t memory_instance_id = module_manager.num_instance(primitive_module, memory_module); + /* Add the memory module as a child of primitive module */ + module_manager.add_child_module(primitive_module, memory_module); + + /* Add nets to connect regular and mode-select SRAM ports to the SRAM port of memory module */ + add_module_nets_between_logic_and_memory_sram_bus(module_manager, primitive_module, + logic_module, logic_instance_id, + memory_module, memory_instance_id, + circuit_lib, primitive_model); + /* Record memory-related information */ + memory_modules.push_back(memory_module); + memory_instances.push_back(memory_instance_id); + } + /* Add all the nets to connect configuration ports from memory module to primitive modules + * This is a one-shot addition that covers all the memory modules in this primitive module! + */ + if (false == memory_modules.empty()) { + add_module_nets_memory_config_bus(module_manager, primitive_module, + memory_modules, memory_instances, + sram_orgz_type, circuit_lib.design_tech_type(sram_model)); + } +} + +/******************************************************************** + * This function add a net for a pin-to-pin connection defined in pb_graph + * It supports two cases for the pin-to-pin connection + * 1. The net source is a pb_graph_pin while the net sink is a pin of an interconnection + * 2. The net source is a pin of an interconnection while the net sink a pb_graph_pin + * The type is enabled by an argument pin2pin_interc_type + *******************************************************************/ +static +void add_module_pb_graph_pin2pin_net(ModuleManager& module_manager, + const ModuleId& pb_module, + const ModuleId& interc_module, + const size_t& interc_instance, + const std::string& interc_port_name, + const size_t& interc_pin_id, + const std::string& module_name_prefix, + t_pb_graph_pin* pb_graph_pin, + const enum e_spice_pin2pin_interc_type& pin2pin_interc_type) { + + ModuleNetId pin2pin_net = module_manager.create_module_net(pb_module); + + /* Find port and pin ids for the module, which is the parent of pb_graph_pin */ + t_pb_type* pin_pb_type = pb_graph_pin->parent_node->pb_type; + /* Find the module contains the source pin */ + ModuleId pin_pb_type_module = module_manager.find_module(generate_physical_block_module_name(module_name_prefix, pin_pb_type)); + VTR_ASSERT(true == module_manager.valid_module_id(pin_pb_type_module)); + size_t pin_pb_type_instance = 0; /* Deposite the instance with a zero, which is the default value is the source module is actually pb_module itself */ + if (pin_pb_type_module != pb_module) { + pin_pb_type_instance = pb_graph_pin->parent_node->placement_index; + /* Ensure this is an valid instance */ + VTR_ASSERT(pin_pb_type_instance < module_manager.num_instance(pb_module, pin_pb_type_module)); + } + ModulePortId pin_module_port_id = module_manager.find_module_port(pin_pb_type_module, generate_pb_type_port_name(pb_graph_pin->port)); + VTR_ASSERT(true == module_manager.valid_module_port_id(pin_pb_type_module, pin_module_port_id)); + size_t pin_module_pin_id = pb_graph_pin->pin_number; + /* Ensure this is an valid pin index */ + VTR_ASSERT(pin_module_pin_id < module_manager.module_port(pin_pb_type_module, pin_module_port_id).get_width()); + + /* Find port and pin ids for the interconnection module */ + ModulePortId interc_port_id = module_manager.find_module_port(interc_module, interc_port_name); + VTR_ASSERT(true == module_manager.valid_module_port_id(interc_module, interc_port_id)); + /* Ensure this is an valid pin index */ + VTR_ASSERT(interc_pin_id < module_manager.module_port(interc_module, interc_port_id).get_width()); + + /* Add net sources and sinks: + * For input-to-input connection, net_source is pin_graph_pin, while net_sink is interc pin + * For output-to-output connection, net_source is interc pin, while net_sink is pin_graph pin + */ + switch (pin2pin_interc_type) { + case INPUT2INPUT_INTERC: + module_manager.add_module_net_source(pb_module, pin2pin_net, pin_pb_type_module, pin_pb_type_instance, pin_module_port_id, pin_module_pin_id); + module_manager.add_module_net_sink(pb_module, pin2pin_net, interc_module, interc_instance, interc_port_id, interc_pin_id); + break; + case OUTPUT2OUTPUT_INTERC: + module_manager.add_module_net_source(pb_module, pin2pin_net, interc_module, interc_instance, interc_port_id, interc_pin_id); + module_manager.add_module_net_sink(pb_module, pin2pin_net, pin_pb_type_module, pin_pb_type_instance, pin_module_port_id, pin_module_pin_id); + break; + default: + vpr_printf(TIO_MESSAGE_ERROR, + "(File:%s, [LINE%d]) Invalid pin-to-pin interconnection type!\n", + __FILE__, __LINE__); + exit(1); + } +} + +/******************************************************************** + * We check output_pins of cur_pb_graph_node and its the input_edges + * Built the interconnections between outputs of cur_pb_graph_node and outputs of child_pb_graph_node + * src_pb_graph_node.[in|out]_pins -----------------> des_pb_graph_node.[in|out]pins + * /|\ + * | + * input_pins, edges, output_pins + * + * This function does the following task: + * 1. identify pin interconnection type, + * 2. Identify the number of fan-in (Consider interconnection edges of only selected mode) + * 3. Add mux/direct connection as a child module to pb_module + * 4. Add nets related to the mux/direction + *******************************************************************/ +static +void add_module_pb_graph_pin_interc(ModuleManager& module_manager, + const ModuleId& pb_module, + std::vector& memory_modules, + std::vector& memory_instances, + const CircuitLibrary& circuit_lib, + const std::string& module_name_prefix, + t_pb_graph_pin* des_pb_graph_pin, + t_mode* physical_mode) { + /* Find the number of fan-in and detailed interconnection information + * related to the destination pb_graph_pin + */ + int fan_in = 0; + t_interconnect* cur_interc = NULL; + find_interc_fan_in_des_pb_graph_pin(des_pb_graph_pin, physical_mode, &cur_interc, &fan_in); + + /* If no interconnection is needed, we can return early */ + if ((NULL == cur_interc) || (0 == fan_in)) { + return; + } + + /* Initialize the interconnection type that will be physically implemented in module */ + enum e_interconnect verilog_interc_type = determine_actual_pb_interc_type(cur_interc, fan_in); + + /* Find input ports of the wire module */ + std::vector interc_model_inputs = circuit_lib.model_ports_by_type(cur_interc->circuit_model, SPICE_MODEL_PORT_INPUT, true); /* the last argument to guarantee that we ignore any global inputs */ + /* Find output ports of the wire module */ + std::vector interc_model_outputs = circuit_lib.model_ports_by_type(cur_interc->circuit_model, SPICE_MODEL_PORT_OUTPUT, true); /* the last argument to guarantee that we ignore any global ports */ + + /* Ensure that we have only 1 input port and 1 output port, this is valid for both wire and MUX */ + VTR_ASSERT(1 == interc_model_inputs.size()); + VTR_ASSERT(1 == interc_model_outputs.size()); + + /* Branch on the type of physical implementation, + * We add instances of programmable interconnection + */ + switch (verilog_interc_type) { + case DIRECT_INTERC: { + /* Ensure direct interc has only one fan-in */ + VTR_ASSERT(1 == fan_in); + + /* For more than one mode defined, the direct interc has more than one input_edge , + * We need to find which edge is connected the pin we want + */ + int iedge = 0; + for (iedge = 0; iedge < des_pb_graph_pin->num_input_edges; iedge++) { + if (cur_interc == des_pb_graph_pin->input_edges[iedge]->interconnect) { + break; + } + } + t_pb_graph_pin* src_pb_graph_pin = des_pb_graph_pin->input_edges[iedge]->input_pins[0]; + + /* Ensure that circuit model is a wire */ + VTR_ASSERT(SPICE_MODEL_WIRE == circuit_lib.model_type(cur_interc->circuit_model)); + /* Find the wire module in the module manager */ + ModuleId wire_module = module_manager.find_module(circuit_lib.model_name(cur_interc->circuit_model)); + VTR_ASSERT(true == module_manager.valid_module_id(wire_module)); + /* Get the instance id and add an instance of wire */ + size_t wire_instance = module_manager.num_instance(pb_module, wire_module); + module_manager.add_child_module(pb_module, wire_module); + + /* Ensure input and output ports of the wire model has only 1 pin respectively */ + VTR_ASSERT(1 == circuit_lib.port_size(interc_model_inputs[0])); + VTR_ASSERT(1 == circuit_lib.port_size(interc_model_outputs[0])); + + /* Add nets to connect the wires to ports of pb_module */ + /* First net is to connect input of src_pb_graph_node to input of the wire module */ + add_module_pb_graph_pin2pin_net(module_manager, pb_module, + wire_module, wire_instance, + circuit_lib.port_lib_name(interc_model_inputs[0]), + 0, /* wire input port has only 1 pin */ + module_name_prefix, + src_pb_graph_pin, + INPUT2INPUT_INTERC); + + /* Second net is to connect output of the wire module to output of des_pb_graph_pin */ + add_module_pb_graph_pin2pin_net(module_manager, pb_module, + wire_module, wire_instance, + circuit_lib.port_lib_name(interc_model_outputs[0]), + 0, /* wire output port has only 1 pin */ + module_name_prefix, + des_pb_graph_pin, + OUTPUT2OUTPUT_INTERC); + break; + } + case COMPLETE_INTERC: + case MUX_INTERC: { + /* Check: MUX should have at least 2 fan_in */ + VTR_ASSERT((2 == fan_in)||(2 < fan_in)); + /* Ensure that circuit model is a MUX */ + VTR_ASSERT(SPICE_MODEL_MUX == circuit_lib.model_type(cur_interc->circuit_model)); + /* Find the wire module in the module manager */ + ModuleId mux_module = module_manager.find_module(generate_mux_subckt_name(circuit_lib, cur_interc->circuit_model, fan_in, std::string())); + VTR_ASSERT(true == module_manager.valid_module_id(mux_module)); + + /* Instanciate the MUX */ + size_t mux_instance = module_manager.num_instance(pb_module, mux_module); + module_manager.add_child_module(pb_module, mux_module); + + /* Instanciate a memory module for the MUX */ + std::string mux_mem_module_name = generate_mux_subckt_name(circuit_lib, + cur_interc->circuit_model, + fan_in, + std::string(verilog_mem_posfix)); + ModuleId mux_mem_module = module_manager.find_module(mux_mem_module_name); + VTR_ASSERT(true == module_manager.valid_module_id(mux_mem_module)); + size_t mux_mem_instance = module_manager.num_instance(pb_module, mux_mem_module); + module_manager.add_child_module(pb_module, mux_mem_module); + + /* Add nets to connect SRAM ports of the MUX to the SRAM port of memory module */ + add_module_nets_between_logic_and_memory_sram_bus(module_manager, pb_module, + mux_module, mux_instance, + mux_mem_module, mux_mem_instance, + circuit_lib, cur_interc->circuit_model); + + /* Update memory modules and memory instance list */ + memory_modules.push_back(mux_mem_module); + memory_instances.push_back(mux_mem_instance); + + /* Ensure output port of the MUX model has only 1 pin, + * while the input port size is dependent on the architecture conext, + * no constaints on the circuit model definition + */ + VTR_ASSERT(1 == circuit_lib.port_size(interc_model_outputs[0])); + + /* Create nets to wire between the MUX and PB module */ + /* Add a net to wire the inputs of the multiplexer to its source pb_graph_pin inside pb_module + * Here is a tricky part. + * Not every input edges from the destination pb_graph_pin is used in the physical_model of pb_type + * So, we will skip these input edges when building nets + */ + int mux_input_pin_id = 0; + for (int iedge = 0; iedge < des_pb_graph_pin->num_input_edges; iedge++) { + if (physical_mode != des_pb_graph_pin->input_edges[iedge]->interconnect->parent_mode) { + continue; + } + /* Ensure that the input edge has only 1 input pin! */ + check_pb_graph_edge(*(des_pb_graph_pin->input_edges[iedge])); + t_pb_graph_pin* src_pb_graph_pin = des_pb_graph_pin->input_edges[iedge]->input_pins[0]; + /* Add a net, set its source and sink */ + add_module_pb_graph_pin2pin_net(module_manager, pb_module, + mux_module, mux_instance, + circuit_lib.port_lib_name(interc_model_inputs[0]), + mux_input_pin_id, + module_name_prefix, + src_pb_graph_pin, + INPUT2INPUT_INTERC); + mux_input_pin_id++; + } + /* Ensure all the fan_in has been covered */ + VTR_ASSERT(mux_input_pin_id == fan_in); + + /* Add a net to wire the output of the multiplexer to des_pb_graph_pin */ + add_module_pb_graph_pin2pin_net(module_manager, pb_module, + mux_module, mux_instance, + circuit_lib.port_lib_name(interc_model_outputs[0]), + 0, /* MUX should have only 1 pin in its output port */ + module_name_prefix, + des_pb_graph_pin, + OUTPUT2OUTPUT_INTERC); + break; + } + default: + vpr_printf(TIO_MESSAGE_ERROR, + "(File:%s,[LINE%d])Invalid interconnection type for %s [at Architecture XML LINE%d]!\n", + __FILE__, __LINE__, cur_interc->name, cur_interc->line_num); + exit(1); + } +} + +/******************************************************************** + * Add modules and nets for programmable/non-programmable interconnections + * which end to a port of pb_module + * This function will add the following elements to a module + * 1. Instances of direct connections + * 2. Instances of programmable routing multiplexers + * 3. nets to connect direct connections/multiplexer + * + * +-----------------------------------------+ + * | + * | +--------------+ +------------+ + * |--->| |--->| | + * |... | Multiplexers |... | | + * |--->| |--->| | + * | +--------------+ | des_pb_ | + * | | graph_node | + * | +--------------+ | | + * |--->| |--->| | + * | ...| Direct |... | | + * |--->| Connections |--->| | + * | +--------------+ +------------+ + * | + * +----------------------------------------+ + + * + * Note: this function should be run after ALL the child pb_modules + * have been added to the pb_module and ALL the ports defined + * in pb_type have been added to the pb_module!!! + * + ********************************************************************/ +static +void add_module_pb_graph_port_interc(ModuleManager& module_manager, + const ModuleId& pb_module, + std::vector& memory_modules, + std::vector& memory_instances, + const CircuitLibrary& circuit_lib, + t_pb_graph_node* des_pb_graph_node, + const std::string& module_name_prefix, + const e_spice_pb_port_type& pb_port_type, + t_mode* physical_mode) { + switch (pb_port_type) { + case SPICE_PB_PORT_INPUT: { + for (int iport = 0; iport < des_pb_graph_node->num_input_ports; ++iport) { + for (int ipin = 0; ipin < des_pb_graph_node->num_input_pins[iport]; ++ipin) { + /* Get the selected edge of current pin*/ + add_module_pb_graph_pin_interc(module_manager, pb_module, + memory_modules, memory_instances, + circuit_lib, + module_name_prefix, + &(des_pb_graph_node->input_pins[iport][ipin]), + physical_mode); + } + } + break; + } + case SPICE_PB_PORT_OUTPUT: { + for (int iport = 0; iport < des_pb_graph_node->num_output_ports; ++iport) { + for (int ipin = 0; ipin < des_pb_graph_node->num_output_pins[iport]; ++ipin) { + add_module_pb_graph_pin_interc(module_manager, pb_module, + memory_modules, memory_instances, + circuit_lib, + module_name_prefix, + &(des_pb_graph_node->output_pins[iport][ipin]), + physical_mode); + } + } + break; + } + case SPICE_PB_PORT_CLOCK: { + for (int iport = 0; iport < des_pb_graph_node->num_clock_ports; ++iport) { + for (int ipin = 0; ipin < des_pb_graph_node->num_clock_pins[iport]; ++ipin) { + add_module_pb_graph_pin_interc(module_manager, pb_module, + memory_modules, memory_instances, + circuit_lib, + module_name_prefix, + &(des_pb_graph_node->clock_pins[iport][ipin]), + physical_mode); + } + } + break; + } + default: + vpr_printf(TIO_MESSAGE_ERROR, + "(File:%s,[LINE%d]) Invalid pb port type!\n", + __FILE__, __LINE__); + exit(1); + } +} + +/******************************************************************** + * TODO: + * Add modules and nets for programmable/non-programmable interconnections + * inside a module of pb_type + * This function will add the following elements to a module + * 1. Instances of direct connections + * 2. Instances of programmable routing multiplexers + * 3. nets to connect direct connections/multiplexer + * + * Pb_module + * +--------------------------------------------------------------+ + * | | + * | +--------------+ +------------+ +--------------+ | + * |--->| |--->| |--->| |--->| + * |... | Multiplexers |... | |... | Multiplexers |... | + * |--->| |--->| |--->| |--->| + * | +--------------+ | Child | +--------------+ | + * | | Pb_modules | | + * | +--------------+ | | +--------------+ | + * |--->| |--->| |--->| |--->| + * | ...| Direct |... | |... | Direct |... | + * |--->| Connections |--->| |--->| Connections |--->| + * | +--------------+ +------------+ +--------------+ | + * | | + * +--------------------------------------------------------------+ + * + * Note: this function should be run after ALL the child pb_modules + * have been added to the pb_module and ALL the ports defined + * in pb_type have been added to the pb_module!!! + * + ********************************************************************/ +static +void add_module_pb_graph_interc(ModuleManager& module_manager, + const ModuleId& pb_module, + std::vector& memory_modules, + std::vector& memory_instances, + const CircuitLibrary& circuit_lib, + t_pb_graph_node* physical_pb_graph_node, + const std::string& module_name_prefix, + const int& physical_mode_index) { + /* Check cur_pb_graph_node*/ + if (NULL == physical_pb_graph_node) { + vpr_printf(TIO_MESSAGE_ERROR, + "(File:%s,[LINE%d]) Invalid cur_pb_graph_node.\n", + __FILE__, __LINE__); + exit(1); + } + + /* Assign physical mode */ + t_mode* physical_mode = &(physical_pb_graph_node->pb_type->modes[physical_mode_index]); + + /* We check output_pins of cur_pb_graph_node and its the input_edges + * Built the interconnections between outputs of cur_pb_graph_node and outputs of child_pb_graph_node + * child_pb_graph_node.output_pins -----------------> cur_pb_graph_node.outpins + * /|\ + * | + * input_pins, edges, output_pins + */ + add_module_pb_graph_port_interc(module_manager, pb_module, + memory_modules, memory_instances, + circuit_lib, + physical_pb_graph_node, + module_name_prefix, + SPICE_PB_PORT_OUTPUT, + physical_mode); + + /* We check input_pins of child_pb_graph_node and its the input_edges + * Built the interconnections between inputs of cur_pb_graph_node and inputs of child_pb_graph_node + * cur_pb_graph_node.input_pins -----------------> child_pb_graph_node.input_pins + * /|\ + * | + * input_pins, edges, output_pins + */ + for (int child = 0; child < physical_pb_graph_node->pb_type->modes[physical_mode_index].num_pb_type_children; ++child) { + for (int inst = 0; inst < physical_pb_graph_node->pb_type->modes[physical_mode_index].pb_type_children[child].num_pb; ++inst) { + t_pb_graph_node* child_pb_graph_node = &(physical_pb_graph_node->child_pb_graph_nodes[physical_mode_index][child][inst]); + /* For each child_pb_graph_node input pins*/ + add_module_pb_graph_port_interc(module_manager, pb_module, + memory_modules, memory_instances, + circuit_lib, + child_pb_graph_node, + module_name_prefix, + SPICE_PB_PORT_INPUT, + physical_mode); + + /* For each child_pb_graph_node clock pins*/ + add_module_pb_graph_port_interc(module_manager, pb_module, + memory_modules, memory_instances, + circuit_lib, + child_pb_graph_node, + module_name_prefix, + SPICE_PB_PORT_CLOCK, + physical_mode); + } + } +} + +/******************************************************************** + * Print Verilog modules of physical blocks inside a grid (CLB, I/O. etc.) + * This function will traverse the graph of complex logic block (t_pb_graph_node) + * in a recursive way, using a Depth First Search (DFS) algorithm. + * As such, primitive physical blocks (LUTs, FFs, etc.), leaf node of the pb_graph + * will be printed out first, while the top-level will be printed out in the last + * + * Note: this function will print a unique Verilog module for each type of + * t_pb_graph_node, i.e., t_pb_type, in the graph, in order to enable highly + * hierarchical Verilog organization as well as simplify the Verilog file sizes. + * + * Note: DFS is the right way. Do NOT use BFS. + * DFS can guarantee that all the sub-modules can be registered properly + * to its parent in module manager + *******************************************************************/ +static +void rec_build_physical_block_modules(ModuleManager& module_manager, + const CircuitLibrary& circuit_lib, + const MuxLibrary& mux_lib, + const e_sram_orgz& sram_orgz_type, + const CircuitModelId& sram_model, + t_pb_graph_node* physical_pb_graph_node, + const e_side& io_side) { + /* Check cur_pb_graph_node*/ + if (NULL == physical_pb_graph_node) { + vpr_printf(TIO_MESSAGE_ERROR, + "(File:%s,[LINE%d]) Invalid cur_pb_graph_node.\n", + __FILE__, __LINE__); + exit(1); + } + + /* Get the pb_type definition related to the node */ + t_pb_type* physical_pb_type = physical_pb_graph_node->pb_type; + + /* Find the mode that physical implementation of a pb_type */ + int physical_mode_index = find_pb_type_physical_mode_index((*physical_pb_type)); + + /* For non-leaf node in the pb_type graph: + * Recursively Depth-First Generate all the child pb_type at the level + */ + if (FALSE == is_primitive_pb_type(physical_pb_type)) { + for (int ipb = 0; ipb < physical_pb_type->modes[physical_mode_index].num_pb_type_children; ++ipb) { + /* Go recursive to visit the children */ + rec_build_physical_block_modules(module_manager, circuit_lib, mux_lib, + sram_orgz_type, sram_model, + &(physical_pb_graph_node->child_pb_graph_nodes[physical_mode_index][ipb][0]), + io_side); + } + } + + /* For leaf node, a primitive Verilog module will be generated */ + if (TRUE == is_primitive_pb_type(physical_pb_type)) { + build_primitive_block_module(module_manager, circuit_lib, + sram_orgz_type, sram_model, + physical_pb_graph_node, + io_side); + /* Finish for primitive node, return */ + return; + } + + /* Generate the name of the Verilog module for this pb_type */ + std::string pb_module_name_prefix = generate_grid_block_prefix(std::string(grid_verilog_file_name_prefix), io_side); + std::string pb_module_name = generate_physical_block_module_name(pb_module_name_prefix, physical_pb_type); + + /* Register the Verilog module in module manager */ + ModuleId pb_module = module_manager.add_module(pb_module_name); + VTR_ASSERT(true == module_manager.valid_module_id(pb_module)); + + /* Add ports to the Verilog module */ + add_pb_type_ports_to_module_manager(module_manager, pb_module, physical_pb_type); + + /* Vectors to record all the memory modules have been added + * They are used to add module nets of configuration bus + */ + std::vector memory_modules; + std::vector memory_instances; + + /* Add all the child Verilog modules as instances */ + for (int ichild = 0; ichild < physical_pb_type->modes[physical_mode_index].num_pb_type_children; ++ichild) { + /* Get the name and module id for this child pb_type */ + std::string child_pb_module_name = generate_physical_block_module_name(pb_module_name_prefix, &(physical_pb_type->modes[physical_mode_index].pb_type_children[ichild])); + ModuleId child_pb_module = module_manager.find_module(child_pb_module_name); + /* We must have one valid id! */ + VTR_ASSERT(true == module_manager.valid_module_id(child_pb_module)); + + /* Each child may exist multiple times in the hierarchy*/ + for (int inst = 0; inst < physical_pb_type->modes[physical_mode_index].pb_type_children[ichild].num_pb; ++inst) { + size_t child_instance_id = module_manager.num_instance(pb_module, child_pb_module); + /* Ensure the instance of this child module is the same as placement index, + * This check is necessary because placement_index is used to identify instance id for children + * when adding local interconnection for this pb_type + */ + VTR_ASSERT(child_instance_id == (size_t)physical_pb_graph_node->child_pb_graph_nodes[physical_mode_index][ichild][inst].placement_index); + + /* Add the memory module as a child of primitive module */ + module_manager.add_child_module(pb_module, child_pb_module); + /* Identify if this sub module includes configuration bits, + * we will update the memory module and instance list + */ + if (0 < find_module_num_config_bits(module_manager, child_pb_module, + circuit_lib, sram_model, + sram_orgz_type)) { + memory_modules.push_back(child_pb_module); + memory_instances.push_back(child_instance_id); + } + } + } + + /* Add modules and nets for programmable/non-programmable interconnections + * inside the Verilog module + */ + add_module_pb_graph_interc(module_manager, pb_module, + memory_modules, memory_instances, + circuit_lib, physical_pb_graph_node, + pb_module_name_prefix, + physical_mode_index); + + /* Add global ports to the pb_module: + * This is a much easier job after adding sub modules (instances), + * we just need to find all the global ports from the child modules and build a list of it + */ + add_module_global_ports_from_child_modules(module_manager, pb_module); + + /* Count GPIO ports from the sub-modules under this Verilog module + * This is a much easier job after adding sub modules (instances), + * we just need to find all the I/O ports from the child modules and build a list of it + */ + add_module_gpio_ports_from_child_modules(module_manager, pb_module); + + /* Count shared SRAM ports from the sub-modules under this Verilog module + * This is a much easier job after adding sub modules (instances), + * we just need to find all the I/O ports from the child modules and build a list of it + */ + size_t module_num_shared_config_bits = find_module_num_shared_config_bits_from_child_modules(module_manager, pb_module); + if (0 < module_num_shared_config_bits) { + add_reserved_sram_ports_to_module_manager(module_manager, pb_module, module_num_shared_config_bits); + } + + /* Count SRAM ports from the sub-modules under this Verilog module + * This is a much easier job after adding sub modules (instances), + * we just need to find all the I/O ports from the child modules and build a list of it + */ + size_t module_num_config_bits = find_module_num_config_bits_from_child_modules(module_manager, pb_module, circuit_lib, sram_model, sram_orgz_type); + if (0 < module_num_config_bits) { + add_sram_ports_to_module_manager(module_manager, pb_module, circuit_lib, sram_model, sram_orgz_type, module_num_config_bits); + } + + /* Add module nets to connect memory cells inside + * This is a one-shot addition that covers all the memory modules in this pb module! + */ + if (false == memory_modules.empty()) { + add_module_nets_memory_config_bus(module_manager, pb_module, + memory_modules, memory_instances, + sram_orgz_type, circuit_lib.design_tech_type(sram_model)); + } +} + +/***************************************************************************** + * This function will create a Verilog file and print out a Verilog netlist + * for a type of physical block + * + * For IO blocks: + * The param 'border_side' is required, which is specify which side of fabric + * the I/O block locates at. + *****************************************************************************/ +static +void build_grid_module(ModuleManager& module_manager, + const MuxLibrary& mux_lib, + const CircuitLibrary& circuit_lib, + const e_sram_orgz& sram_orgz_type, + const CircuitModelId& sram_model, + t_type_ptr phy_block_type, + const e_side& border_side) { + /* Check code: if this is an IO block, the border side MUST be valid */ + if (IO_TYPE == phy_block_type) { + VTR_ASSERT(NUM_SIDES != border_side); + } + + /* Build modules for all the pb_types/pb_graph_nodes + * use a Depth-First Search Algorithm to print the sub-modules + * Note: DFS is the right way. Do NOT use BFS. + * DFS can guarantee that all the sub-modules can be registered properly + * to its parent in module manager + */ + /* Build modules starting from the top-level pb_type/pb_graph_node, and traverse the graph in a recursive way */ + rec_build_physical_block_modules(module_manager, circuit_lib, mux_lib, + sram_orgz_type, sram_model, + phy_block_type->pb_graph_head, + border_side); + + /* Create a Verilog Module for the top-level physical block, and add to module manager */ + std::string grid_module_name = generate_grid_block_module_name(std::string(grid_verilog_file_name_prefix), std::string(phy_block_type->name), IO_TYPE == phy_block_type, border_side); + ModuleId grid_module = module_manager.add_module(grid_module_name); + VTR_ASSERT(true == module_manager.valid_module_id(grid_module)); + + /* Vectors to record all the memory modules have been added + * They are used to add module nets of configuration bus + */ + std::vector memory_modules; + std::vector memory_instances; + + /* Generate the name of the Verilog module for this pb_type */ + std::string pb_module_name_prefix(grid_verilog_file_name_prefix); + std::string pb_module_name = generate_grid_physical_block_module_name(pb_module_name_prefix, phy_block_type->pb_graph_head->pb_type, border_side); + ModuleId pb_module = module_manager.find_module(pb_module_name); + VTR_ASSERT(true == module_manager.valid_module_id(pb_module)); + + /* Add all the sub modules */ + for (int iz = 0; iz < phy_block_type->capacity; ++iz) { + size_t pb_instance_id = module_manager.num_instance(grid_module, pb_module); + module_manager.add_child_module(grid_module, pb_module); + /* Identify if this sub module includes configuration bits, + * we will update the memory module and instance list + */ + if (0 < find_module_num_config_bits(module_manager, pb_module, + circuit_lib, sram_model, + sram_orgz_type)) { + memory_modules.push_back(pb_module); + memory_instances.push_back(pb_instance_id); + } + } + + /* Add grid ports(pins) to the module */ + add_grid_module_pb_type_ports(module_manager, grid_module, + phy_block_type, border_side); + + /* Add module nets to connect the pb_type ports to sub modules */ + for (const size_t& child_instance : module_manager.child_module_instances(grid_module, pb_module)) { + add_grid_module_nets_connect_pb_type_ports(module_manager, grid_module, + pb_module, child_instance, + phy_block_type, border_side); + } + + /* Add global ports to the pb_module: + * This is a much easier job after adding sub modules (instances), + * we just need to find all the global ports from the child modules and build a list of it + */ + add_module_global_ports_from_child_modules(module_manager, grid_module); + + /* Count GPIO ports from the sub-modules under this Verilog module + * This is a much easier job after adding sub modules (instances), + * we just need to find all the I/O ports from the child modules and build a list of it + */ + add_module_gpio_ports_from_child_modules(module_manager, grid_module); + + /* Count shared SRAM ports from the sub-modules under this Verilog module + * This is a much easier job after adding sub modules (instances), + * we just need to find all the I/O ports from the child modules and build a list of it + */ + size_t module_num_shared_config_bits = find_module_num_shared_config_bits_from_child_modules(module_manager, grid_module); + if (0 < module_num_shared_config_bits) { + add_reserved_sram_ports_to_module_manager(module_manager, grid_module, module_num_shared_config_bits); + } + + /* Count SRAM ports from the sub-modules under this Verilog module + * This is a much easier job after adding sub modules (instances), + * we just need to find all the I/O ports from the child modules and build a list of it + */ + size_t module_num_config_bits = find_module_num_config_bits_from_child_modules(module_manager, grid_module, circuit_lib, sram_model, sram_orgz_type); + if (0 < module_num_config_bits) { + add_sram_ports_to_module_manager(module_manager, grid_module, circuit_lib, sram_model, sram_orgz_type, module_num_config_bits); + } + + /* Add module nets to connect memory cells inside + * This is a one-shot addition that covers all the memory modules in this pb module! + */ + if (false == memory_modules.empty()) { + add_module_nets_memory_config_bus(module_manager, grid_module, + memory_modules, memory_instances, + sram_orgz_type, circuit_lib.design_tech_type(sram_model)); + } +} + +/***************************************************************************** + * Create logic block modules in a compact way: + * 1. Only one module for each I/O on each border side (IO_TYPE) + * 2. Only one module for each CLB (FILL_TYPE) + * 3. Only one module for each heterogeneous block + ****************************************************************************/ +void build_grid_modules(ModuleManager& module_manager, + const CircuitLibrary& circuit_lib, + const MuxLibrary& mux_lib, + const e_sram_orgz& sram_orgz_type, + const CircuitModelId& sram_model) { + /* Enumerate the types, dump one Verilog module for each */ + for (int itype = 0; itype < num_types; itype++) { + if (EMPTY_TYPE == &type_descriptors[itype]) { + /* Bypass empty type or NULL */ + continue; + } else if (IO_TYPE == &type_descriptors[itype]) { + /* Special for I/O block, generate one module for each border side */ + for (int iside = 0; iside < NUM_SIDES; iside++) { + Side side_manager(iside); + build_grid_module(module_manager, mux_lib, circuit_lib, + sram_orgz_type, sram_model, + &type_descriptors[itype], + side_manager.get_side()); + } + continue; + } else if (FILL_TYPE == &type_descriptors[itype]) { + /* For CLB */ + build_grid_module(module_manager, mux_lib, circuit_lib, + sram_orgz_type, sram_model, + &type_descriptors[itype], + NUM_SIDES); + continue; + } else { + /* For heterogenenous blocks */ + build_grid_module(module_manager, mux_lib, circuit_lib, + sram_orgz_type, sram_model, + &type_descriptors[itype], + NUM_SIDES); + } + } +} + diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/module_builder/build_grid_modules.h b/vpr7_x2p/vpr/SRC/fpga_x2p/module_builder/build_grid_modules.h new file mode 100644 index 000000000..ad1880e1c --- /dev/null +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/module_builder/build_grid_modules.h @@ -0,0 +1,18 @@ +/******************************************************************** + * Header file for build_grid_modules.cpp + *******************************************************************/ +#ifndef BUILD_GRID_MODULES_H +#define BUILD_GRID_MODULES_H + +/* Only include headers related to the data structures used in the following function declaration */ +#include "vpr_types.h" +#include "module_manager.h" +#include "mux_library.h" + +void build_grid_modules(ModuleManager& module_manager, + const CircuitLibrary& circuit_lib, + const MuxLibrary& mux_lib, + const e_sram_orgz& sram_orgz_type, + const CircuitModelId& sram_model); + +#endif diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/module_builder/build_memory_modules.h b/vpr7_x2p/vpr/SRC/fpga_x2p/module_builder/build_memory_modules.h index 3597c5d95..276fa4fad 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/module_builder/build_memory_modules.h +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/module_builder/build_memory_modules.h @@ -1,9 +1,9 @@ /*********************************************** - * Header file for verilog_memory.cpp + * Header file for build_memory_modules.cpp **********************************************/ -#ifndef BUILD_MEMORY_MODULE_H -#define BUILD_MEMORY_MODULE_H +#ifndef BUILD_MEMORY_MODULES_H +#define BUILD_MEMORY_MODULES_H /* Include other header files which are dependency on the function declared below */ diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/module_builder/build_module_graph.cpp b/vpr7_x2p/vpr/SRC/fpga_x2p/module_builder/build_module_graph.cpp index 666e42876..ad9ac0098 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/module_builder/build_module_graph.cpp +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/module_builder/build_module_graph.cpp @@ -16,6 +16,7 @@ #include "build_lut_modules.h" #include "build_wire_modules.h" #include "build_memory_modules.h" +#include "build_grid_modules.h" #include "build_module_graph.h" /******************************************************************** @@ -63,7 +64,7 @@ ModuleManager build_device_module_graph(const t_vpr_setup& vpr_setup, config_spice_models_sram_port_spice_model(arch.spice->num_spice_model, arch.spice->spice_models, arch.sram_inf.verilog_sram_inf_orgz->spice_model); - config_circuit_models_sram_port_to_default_sram_model(arch.spice->circuit_lib, arch.sram_inf.verilog_sram_inf_orgz->circuit_model); + config_circuit_models_sram_port_to_default_sram_model(arch.spice->circuit_lib, sram_model); /* Create a vector of segments. TODO: should come from DeviceContext */ std::vector L_segment_vec; @@ -99,7 +100,9 @@ ModuleManager build_device_module_graph(const t_vpr_setup& vpr_setup, build_memory_modules(module_manager, mux_lib, arch.spice->circuit_lib, arch.sram_inf.verilog_sram_inf_orgz->type); - /* TODO: Build grid and programmable block modules */ + /* Build grid and programmable block modules */ + build_grid_modules(module_manager, arch.spice->circuit_lib, mux_lib, + arch.sram_inf.verilog_sram_inf_orgz->type, sram_model); /* TODO: Build global routing architecture modules */ diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_api.c b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_api.c index b2ecbae94..fae787353 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_api.c +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_api.c @@ -294,8 +294,7 @@ void vpr_fpga_verilog(ModuleManager& module_manager, lb_dir_path, Arch, vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.dump_explicit_verilog); - print_verilog_grids(module_manager, Arch.spice->circuit_lib, mux_lib, - sram_verilog_orgz_info, + print_verilog_grids(module_manager, std::string(src_dir_path), std::string(lb_dir_path), TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.dump_explicit_verilog); diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_grid.cpp b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_grid.cpp index 4d377a115..a7a7f877d 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_grid.cpp +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_grid.cpp @@ -31,209 +31,6 @@ #include "verilog_module_writer.h" #include "verilog_grid.h" -/******************************************************************** - * Find the side where I/O pins locate on a grid I/O block - * 1. I/O grids on the top side of FPGA only have ports on its bottom side - * 2. I/O grids on the right side of FPGA only have ports on its left side - * 3. I/O grids on the bottom side of FPGA only have ports on its top side - * 4. I/O grids on the left side of FPGA only have ports on its right side - *******************************************************************/ -static -e_side find_grid_module_pin_side(t_type_ptr grid_type_descriptor, - const e_side& border_side) { - VTR_ASSERT(IO_TYPE == grid_type_descriptor); - Side side_manager(border_side); - return side_manager.get_opposite(); -} - -/******************************************************************** - * Add ports/pins to a grid module - * This function will iterate over all the pins that are defined - * in type_descripter and give a name by its height, side and index - * - * In particular, for I/O grid, only part of the ports on required - * on a specific side. - *******************************************************************/ -static -void add_grid_module_pb_type_ports(ModuleManager& module_manager, - const ModuleId& grid_module, - t_type_ptr grid_type_descriptor, - const e_side& border_side) { - /* Ensure that we have a valid grid_type_descriptor */ - VTR_ASSERT(NULL != grid_type_descriptor); - - /* Find the pin side for I/O grids*/ - std::vector grid_pin_sides; - /* For I/O grids, we care only one side - * Otherwise, we will iterate all the 4 sides - */ - if (IO_TYPE == grid_type_descriptor) { - grid_pin_sides.push_back(find_grid_module_pin_side(grid_type_descriptor, border_side)); - } else { - grid_pin_sides = {TOP, RIGHT, BOTTOM, LEFT}; - } - - /* Create a map between pin class type and grid pin direction */ - std::map pin_type2type_map; - pin_type2type_map[RECEIVER] = ModuleManager::MODULE_INPUT_PORT; - pin_type2type_map[DRIVER] = ModuleManager::MODULE_OUTPUT_PORT; - - /* Iterate over sides, height and pins */ - for (const e_side& side : grid_pin_sides) { - for (int iheight = 0; iheight < grid_type_descriptor->height; ++iheight) { - for (int ipin = 0; ipin < grid_type_descriptor->num_pins; ++ipin) { - if (1 != grid_type_descriptor->pinloc[iheight][side][ipin]) { - continue; - } - /* Reach here, it means this pin is on this side */ - int class_id = grid_type_descriptor->pin_class[ipin]; - e_pin_type pin_class_type = grid_type_descriptor->class_inf[class_id].type; - /* Generate the pin name, - * we give a empty coordinate but it will not be used (see details in the function - */ - vtr::Point dummy_coordinate; - std::string port_name = generate_grid_port_name(dummy_coordinate, iheight, side, ipin, false); - BasicPort grid_port(port_name, 0, 0); - /* Add the port to the module */ - module_manager.add_port(grid_module, grid_port, pin_type2type_map[pin_class_type]); - } - } - } -} - -/******************************************************************** - * Add module nets to connect a port of child pb_module - * to the grid module - *******************************************************************/ -static -void add_grid_module_net_connect_pb_graph_pin(ModuleManager& module_manager, - const ModuleId& grid_module, - const ModuleId& child_module, - const size_t& child_instance, - t_type_ptr grid_type_descriptor, - t_pb_graph_pin* pb_graph_pin, - const e_side& border_side, - const enum e_spice_pin2pin_interc_type& pin2pin_interc_type) { - /* Find the pin side for I/O grids*/ - std::vector grid_pin_sides; - /* For I/O grids, we care only one side - * Otherwise, we will iterate all the 4 sides - */ - if (IO_TYPE == grid_type_descriptor) { - grid_pin_sides.push_back(find_grid_module_pin_side(grid_type_descriptor, border_side)); - } else { - grid_pin_sides.push_back(TOP); - grid_pin_sides.push_back(RIGHT); - grid_pin_sides.push_back(BOTTOM); - grid_pin_sides.push_back(LEFT); - } - - /* num_pins/capacity = the number of pins that each type_descriptor has. - * Capacity defines the number of type_descriptors in each grid - * so the pin index at grid level = pin_index_in_type_descriptor - * + type_descriptor_index_in_capacity * num_pins_per_type_descriptor - */ - size_t grid_pin_index = pb_graph_pin->pin_count_in_cluster - + child_instance * grid_type_descriptor->num_pins / grid_type_descriptor->capacity; - int pin_height = grid_type_descriptor->pin_height[grid_pin_index]; - for (const e_side& side : grid_pin_sides) { - if (1 != grid_type_descriptor->pinloc[pin_height][side][grid_pin_index]) { - continue; - } - /* Reach here, it means this pin is on this side */ - /* Create a net to connect the grid pin to child module pin */ - ModuleNetId net = module_manager.create_module_net(grid_module); - /* Find the port in grid_module */ - vtr::Point dummy_coordinate; - std::string grid_port_name = generate_grid_port_name(dummy_coordinate, pin_height, side, grid_pin_index, false); - ModulePortId grid_module_port_id = module_manager.find_module_port(grid_module, grid_port_name); - VTR_ASSERT(true == module_manager.valid_module_port_id(grid_module, grid_module_port_id)); - /* Grid port always has only 1 pin, it is assumed when adding these ports to the module - * if you need a change, please also change the port adding codes - */ - size_t grid_module_pin_id = 0; - /* Find the port in child module */ - std::string child_module_port_name = generate_pb_type_port_name(pb_graph_pin->port); - ModulePortId child_module_port_id = module_manager.find_module_port(child_module, child_module_port_name); - VTR_ASSERT(true == module_manager.valid_module_port_id(child_module, child_module_port_id)); - size_t child_module_pin_id = pb_graph_pin->pin_number; - /* Add net sources and sinks: - * For input-to-input connection, net_source is grid pin, while net_sink is pb_graph_pin - * For output-to-output connection, net_source is pb_graph_pin, while net_sink is grid pin - */ - switch (pin2pin_interc_type) { - case INPUT2INPUT_INTERC: - module_manager.add_module_net_source(grid_module, net, grid_module, 0, grid_module_port_id, grid_module_pin_id); - module_manager.add_module_net_sink(grid_module, net, child_module, child_instance, child_module_port_id, child_module_pin_id); - break; - case OUTPUT2OUTPUT_INTERC: - module_manager.add_module_net_source(grid_module, net, child_module, child_instance, child_module_port_id, child_module_pin_id); - module_manager.add_module_net_sink(grid_module, net, grid_module, 0, grid_module_port_id, grid_module_pin_id); - break; - default: - vpr_printf(TIO_MESSAGE_ERROR, - "(File:%s, [LINE%d]) Invalid pin-to-pin interconnection type!\n", - __FILE__, __LINE__); - exit(1); - } - } -} - - -/******************************************************************** - * Add module nets to connect ports/pins of a grid module - * to its child modules - * This function will iterate over all the pins that are defined - * in type_descripter and find the corresponding pin in the top - * pb_graph_node of the grid - *******************************************************************/ -static -void add_grid_module_nets_connect_pb_type_ports(ModuleManager& module_manager, - const ModuleId& grid_module, - const ModuleId& child_module, - const size_t& child_instance, - t_type_ptr grid_type_descriptor, - const e_side& border_side) { - /* Ensure that we have a valid grid_type_descriptor */ - VTR_ASSERT(NULL != grid_type_descriptor); - t_pb_graph_node* top_pb_graph_node = grid_type_descriptor->pb_graph_head; - VTR_ASSERT(NULL != top_pb_graph_node); - - for (int iport = 0; iport < top_pb_graph_node->num_input_ports; ++iport) { - for (int ipin = 0; ipin < top_pb_graph_node->num_input_pins[iport]; ++ipin) { - add_grid_module_net_connect_pb_graph_pin(module_manager, grid_module, - child_module, child_instance, - grid_type_descriptor, - &(top_pb_graph_node->input_pins[iport][ipin]), - border_side, - INPUT2INPUT_INTERC); - - } - } - - for (int iport = 0; iport < top_pb_graph_node->num_output_ports; ++iport) { - for (int ipin = 0; ipin < top_pb_graph_node->num_output_pins[iport]; ++ipin) { - add_grid_module_net_connect_pb_graph_pin(module_manager, grid_module, - child_module, child_instance, - grid_type_descriptor, - &(top_pb_graph_node->output_pins[iport][ipin]), - border_side, - OUTPUT2OUTPUT_INTERC); - } - } - - for (int iport = 0; iport < top_pb_graph_node->num_clock_ports; ++iport) { - for (int ipin = 0; ipin < top_pb_graph_node->num_clock_pins[iport]; ++ipin) { - add_grid_module_net_connect_pb_graph_pin(module_manager, grid_module, - child_module, child_instance, - grid_type_descriptor, - &(top_pb_graph_node->clock_pins[iport][ipin]), - border_side, - INPUT2INPUT_INTERC); - } - } -} - /******************************************************************** * Print Verilog modules of a primitive node in the pb_graph_node graph * This generic function can support all the different types of primitive nodes @@ -263,8 +60,6 @@ void add_grid_module_nets_connect_pb_type_ports(ModuleManager& module_manager, static void print_verilog_primitive_block(std::fstream& fp, ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - t_sram_orgz_info* cur_sram_orgz_info, t_pb_graph_node* primitive_pb_graph_node, const e_side& io_side, const bool& use_explicit_mapping) { @@ -279,110 +74,14 @@ void print_verilog_primitive_block(std::fstream& fp, exit(1); } - /* Find the circuit model id linked to the pb_graph_node */ - CircuitModelId& primitive_model = primitive_pb_graph_node->pb_type->circuit_model; - /* Generate the module name for this primitive pb_graph_node*/ std::string primitive_module_name_prefix = generate_grid_block_prefix(std::string(grid_verilog_file_name_prefix), io_side); std::string primitive_module_name = generate_physical_block_module_name(primitive_module_name_prefix, primitive_pb_graph_node->pb_type); /* Create a module of the primitive LUT and register it to module manager */ - ModuleId primitive_module = module_manager.add_module(primitive_module_name); + ModuleId primitive_module = module_manager.find_module(primitive_module_name); /* Ensure that the module has been created and thus unique! */ - VTR_ASSERT(ModuleId::INVALID() != primitive_module); - - /* Find the global ports required by the primitive node, and add them to the module */ - std::vector primitive_model_global_ports = circuit_lib.model_global_ports(primitive_model, true); - for (auto port : primitive_model_global_ports) { - /* The global I/O of the FPGA has a special name */ - BasicPort module_port(circuit_lib.port_lib_name(port), circuit_lib.port_size(port)); - module_manager.add_port(primitive_module, module_port, ModuleManager::MODULE_GLOBAL_PORT); - } - - /* Find the inout ports required by the primitive node, and add them to the module - * This is mainly due to the I/O blocks, which have inout ports for the top-level fabric - */ - if (SPICE_MODEL_IOPAD == circuit_lib.model_type(primitive_model)) { - std::vector primitive_model_inout_ports = circuit_lib.model_ports_by_type(primitive_model, SPICE_MODEL_PORT_INOUT); - for (auto port : primitive_model_inout_ports) { - BasicPort module_port(generate_fpga_global_io_port_name(std::string(gio_inout_prefix), circuit_lib, primitive_model), circuit_lib.port_size(port)); - module_manager.add_port(primitive_module, module_port, ModuleManager::MODULE_GPIO_PORT); - } - } - /* Note: to cooperate with the pb_type hierarchy and connections, we add the port of primitive pb_type here. - * Since we have linked pb_type ports to circuit models when setting up FPGA-X2P, - * no ports of the circuit model will be missing here - */ - add_primitive_pb_type_ports_to_module_manager(module_manager, primitive_module, primitive_pb_graph_node->pb_type); - - /* Add configuration ports */ - /* Shared SRAM ports*/ - size_t num_shared_config_bits = find_circuit_num_shared_config_bits(circuit_lib, primitive_model, cur_sram_orgz_info->type); - if (0 < num_shared_config_bits) { - /* Check: this SRAM organization type must be memory-bank ! */ - VTR_ASSERT( SPICE_SRAM_MEMORY_BANK == cur_sram_orgz_info->type ); - /* Generate a list of ports */ - add_reserved_sram_ports_to_module_manager(module_manager, primitive_module, - num_shared_config_bits); - } - - /* TODO: this should be added to the cur_sram_orgz_info !!! */ - t_spice_model* mem_model = NULL; - get_sram_orgz_info_mem_model(cur_sram_orgz_info, & mem_model); - CircuitModelId sram_model = circuit_lib.model(mem_model->name); - VTR_ASSERT(CircuitModelId::INVALID() != sram_model); - - /* Regular (independent) SRAM ports */ - size_t num_config_bits = find_circuit_num_config_bits(circuit_lib, primitive_model); - if (0 < num_config_bits) { - add_sram_ports_to_module_manager(module_manager, primitive_module, - circuit_lib, sram_model, cur_sram_orgz_info->type, - num_config_bits); - } - - /* Find the module id in the module manager */ - ModuleId logic_module = module_manager.find_module(circuit_lib.model_name(primitive_model)); - VTR_ASSERT(ModuleId::INVALID() != logic_module); - size_t logic_instance_id = module_manager.num_instance(primitive_module, logic_module); - /* Add the logic module as a child of primitive module */ - module_manager.add_child_module(primitive_module, logic_module); - - /* Add nets to connect the logic model ports to pb_type ports */ - add_primitive_pb_type_module_nets(module_manager, primitive_module, logic_module, logic_instance_id, circuit_lib, primitive_pb_graph_node->pb_type); - - /* Add the associated memory module as a child of primitive module */ - std::string memory_module_name = generate_memory_module_name(circuit_lib, primitive_model, sram_model, std::string(verilog_mem_posfix)); - ModuleId memory_module = module_manager.find_module(memory_module_name); - - /* Vectors to record all the memory modules have been added - * They are used to add module nets of configuration bus - */ - std::vector memory_modules; - std::vector memory_instances; - - /* If there is no memory module required, we can skip the assocated net addition */ - if (ModuleId::INVALID() != memory_module) { - size_t memory_instance_id = module_manager.num_instance(primitive_module, memory_module); - /* Add the memory module as a child of primitive module */ - module_manager.add_child_module(primitive_module, memory_module); - - /* Add nets to connect regular and mode-select SRAM ports to the SRAM port of memory module */ - add_module_nets_between_logic_and_memory_sram_bus(module_manager, primitive_module, - logic_module, logic_instance_id, - memory_module, memory_instance_id, - circuit_lib, primitive_model); - /* Record memory-related information */ - memory_modules.push_back(memory_module); - memory_instances.push_back(memory_instance_id); - } - /* Add all the nets to connect configuration ports from memory module to primitive modules - * This is a one-shot addition that covers all the memory modules in this primitive module! - */ - if (false == memory_modules.empty()) { - add_module_nets_memory_config_bus(module_manager, primitive_module, - memory_modules, memory_instances, - cur_sram_orgz_info->type, circuit_lib.design_tech_type(sram_model)); - } + VTR_ASSERT(true == module_manager.valid_module_id(primitive_module)); /* Write the verilog module */ write_verilog_module_to_file(fp, module_manager, primitive_module, use_explicit_mapping); @@ -391,440 +90,6 @@ void print_verilog_primitive_block(std::fstream& fp, fp << std::endl; } -/******************************************************************** - * This function add a net for a pin-to-pin connection defined in pb_graph - * It supports two cases for the pin-to-pin connection - * 1. The net source is a pb_graph_pin while the net sink is a pin of an interconnection - * 2. The net source is a pin of an interconnection while the net sink a pb_graph_pin - * The type is enabled by an argument pin2pin_interc_type - *******************************************************************/ -static -void add_module_pb_graph_pin2pin_net(ModuleManager& module_manager, - const ModuleId& pb_module, - const ModuleId& interc_module, - const size_t& interc_instance, - const std::string& interc_port_name, - const size_t& interc_pin_id, - const std::string& module_name_prefix, - t_pb_graph_pin* pb_graph_pin, - const enum e_spice_pin2pin_interc_type& pin2pin_interc_type) { - - ModuleNetId pin2pin_net = module_manager.create_module_net(pb_module); - - /* Find port and pin ids for the module, which is the parent of pb_graph_pin */ - t_pb_type* pin_pb_type = pb_graph_pin->parent_node->pb_type; - /* Find the module contains the source pin */ - ModuleId pin_pb_type_module = module_manager.find_module(generate_physical_block_module_name(module_name_prefix, pin_pb_type)); - VTR_ASSERT(true == module_manager.valid_module_id(pin_pb_type_module)); - size_t pin_pb_type_instance = 0; /* Deposite the instance with a zero, which is the default value is the source module is actually pb_module itself */ - if (pin_pb_type_module != pb_module) { - pin_pb_type_instance = pb_graph_pin->parent_node->placement_index; - /* Ensure this is an valid instance */ - VTR_ASSERT(pin_pb_type_instance < module_manager.num_instance(pb_module, pin_pb_type_module)); - } - ModulePortId pin_module_port_id = module_manager.find_module_port(pin_pb_type_module, generate_pb_type_port_name(pb_graph_pin->port)); - VTR_ASSERT(true == module_manager.valid_module_port_id(pin_pb_type_module, pin_module_port_id)); - size_t pin_module_pin_id = pb_graph_pin->pin_number; - /* Ensure this is an valid pin index */ - VTR_ASSERT(pin_module_pin_id < module_manager.module_port(pin_pb_type_module, pin_module_port_id).get_width()); - - /* Find port and pin ids for the interconnection module */ - ModulePortId interc_port_id = module_manager.find_module_port(interc_module, interc_port_name); - VTR_ASSERT(true == module_manager.valid_module_port_id(interc_module, interc_port_id)); - /* Ensure this is an valid pin index */ - VTR_ASSERT(interc_pin_id < module_manager.module_port(interc_module, interc_port_id).get_width()); - - /* Add net sources and sinks: - * For input-to-input connection, net_source is pin_graph_pin, while net_sink is interc pin - * For output-to-output connection, net_source is interc pin, while net_sink is pin_graph pin - */ - switch (pin2pin_interc_type) { - case INPUT2INPUT_INTERC: - module_manager.add_module_net_source(pb_module, pin2pin_net, pin_pb_type_module, pin_pb_type_instance, pin_module_port_id, pin_module_pin_id); - module_manager.add_module_net_sink(pb_module, pin2pin_net, interc_module, interc_instance, interc_port_id, interc_pin_id); - break; - case OUTPUT2OUTPUT_INTERC: - module_manager.add_module_net_source(pb_module, pin2pin_net, interc_module, interc_instance, interc_port_id, interc_pin_id); - module_manager.add_module_net_sink(pb_module, pin2pin_net, pin_pb_type_module, pin_pb_type_instance, pin_module_port_id, pin_module_pin_id); - break; - default: - vpr_printf(TIO_MESSAGE_ERROR, - "(File:%s, [LINE%d]) Invalid pin-to-pin interconnection type!\n", - __FILE__, __LINE__); - exit(1); - } -} - -/******************************************************************** - * We check output_pins of cur_pb_graph_node and its the input_edges - * Built the interconnections between outputs of cur_pb_graph_node and outputs of child_pb_graph_node - * src_pb_graph_node.[in|out]_pins -----------------> des_pb_graph_node.[in|out]pins - * /|\ - * | - * input_pins, edges, output_pins - * - * This function does the following task: - * 1. identify pin interconnection type, - * 2. Identify the number of fan-in (Consider interconnection edges of only selected mode) - * 3. Add mux/direct connection as a child module to pb_module - * 4. Add nets related to the mux/direction - *******************************************************************/ -static -void add_module_pb_graph_pin_interc(ModuleManager& module_manager, - const ModuleId& pb_module, - std::vector& memory_modules, - std::vector& memory_instances, - const CircuitLibrary& circuit_lib, - const std::string& module_name_prefix, - t_pb_graph_pin* des_pb_graph_pin, - t_mode* physical_mode) { - /* Find the number of fan-in and detailed interconnection information - * related to the destination pb_graph_pin - */ - int fan_in = 0; - t_interconnect* cur_interc = NULL; - find_interc_fan_in_des_pb_graph_pin(des_pb_graph_pin, physical_mode, &cur_interc, &fan_in); - - /* If no interconnection is needed, we can return early */ - if ((NULL == cur_interc) || (0 == fan_in)) { - return; - } - - /* Initialize the interconnection type that will be physically implemented in module */ - enum e_interconnect verilog_interc_type = determine_actual_pb_interc_type(cur_interc, fan_in); - - /* Find input ports of the wire module */ - std::vector interc_model_inputs = circuit_lib.model_ports_by_type(cur_interc->circuit_model, SPICE_MODEL_PORT_INPUT, true); /* the last argument to guarantee that we ignore any global inputs */ - /* Find output ports of the wire module */ - std::vector interc_model_outputs = circuit_lib.model_ports_by_type(cur_interc->circuit_model, SPICE_MODEL_PORT_OUTPUT, true); /* the last argument to guarantee that we ignore any global ports */ - - /* Ensure that we have only 1 input port and 1 output port, this is valid for both wire and MUX */ - VTR_ASSERT(1 == interc_model_inputs.size()); - VTR_ASSERT(1 == interc_model_outputs.size()); - - /* Branch on the type of physical implementation, - * We add instances of programmable interconnection - */ - switch (verilog_interc_type) { - case DIRECT_INTERC: { - /* Ensure direct interc has only one fan-in */ - VTR_ASSERT(1 == fan_in); - - /* For more than one mode defined, the direct interc has more than one input_edge , - * We need to find which edge is connected the pin we want - */ - int iedge = 0; - for (iedge = 0; iedge < des_pb_graph_pin->num_input_edges; iedge++) { - if (cur_interc == des_pb_graph_pin->input_edges[iedge]->interconnect) { - break; - } - } - t_pb_graph_pin* src_pb_graph_pin = des_pb_graph_pin->input_edges[iedge]->input_pins[0]; - - /* Ensure that circuit model is a wire */ - VTR_ASSERT(SPICE_MODEL_WIRE == circuit_lib.model_type(cur_interc->circuit_model)); - /* Find the wire module in the module manager */ - ModuleId wire_module = module_manager.find_module(circuit_lib.model_name(cur_interc->circuit_model)); - VTR_ASSERT(true == module_manager.valid_module_id(wire_module)); - /* Get the instance id and add an instance of wire */ - size_t wire_instance = module_manager.num_instance(pb_module, wire_module); - module_manager.add_child_module(pb_module, wire_module); - - /* Ensure input and output ports of the wire model has only 1 pin respectively */ - VTR_ASSERT(1 == circuit_lib.port_size(interc_model_inputs[0])); - VTR_ASSERT(1 == circuit_lib.port_size(interc_model_outputs[0])); - - /* Add nets to connect the wires to ports of pb_module */ - /* First net is to connect input of src_pb_graph_node to input of the wire module */ - add_module_pb_graph_pin2pin_net(module_manager, pb_module, - wire_module, wire_instance, - circuit_lib.port_lib_name(interc_model_inputs[0]), - 0, /* wire input port has only 1 pin */ - module_name_prefix, - src_pb_graph_pin, - INPUT2INPUT_INTERC); - - /* Second net is to connect output of the wire module to output of des_pb_graph_pin */ - add_module_pb_graph_pin2pin_net(module_manager, pb_module, - wire_module, wire_instance, - circuit_lib.port_lib_name(interc_model_outputs[0]), - 0, /* wire output port has only 1 pin */ - module_name_prefix, - des_pb_graph_pin, - OUTPUT2OUTPUT_INTERC); - break; - } - case COMPLETE_INTERC: - case MUX_INTERC: { - /* Check: MUX should have at least 2 fan_in */ - VTR_ASSERT((2 == fan_in)||(2 < fan_in)); - /* Ensure that circuit model is a MUX */ - VTR_ASSERT(SPICE_MODEL_MUX == circuit_lib.model_type(cur_interc->circuit_model)); - /* Find the wire module in the module manager */ - ModuleId mux_module = module_manager.find_module(generate_mux_subckt_name(circuit_lib, cur_interc->circuit_model, fan_in, std::string())); - VTR_ASSERT(true == module_manager.valid_module_id(mux_module)); - - /* Instanciate the MUX */ - size_t mux_instance = module_manager.num_instance(pb_module, mux_module); - module_manager.add_child_module(pb_module, mux_module); - - /* Instanciate a memory module for the MUX */ - std::string mux_mem_module_name = generate_mux_subckt_name(circuit_lib, - cur_interc->circuit_model, - fan_in, - std::string(verilog_mem_posfix)); - ModuleId mux_mem_module = module_manager.find_module(mux_mem_module_name); - VTR_ASSERT(true == module_manager.valid_module_id(mux_mem_module)); - size_t mux_mem_instance = module_manager.num_instance(pb_module, mux_mem_module); - module_manager.add_child_module(pb_module, mux_mem_module); - - /* Add nets to connect SRAM ports of the MUX to the SRAM port of memory module */ - add_module_nets_between_logic_and_memory_sram_bus(module_manager, pb_module, - mux_module, mux_instance, - mux_mem_module, mux_mem_instance, - circuit_lib, cur_interc->circuit_model); - - /* Update memory modules and memory instance list */ - memory_modules.push_back(mux_mem_module); - memory_instances.push_back(mux_mem_instance); - - /* Ensure output port of the MUX model has only 1 pin, - * while the input port size is dependent on the architecture conext, - * no constaints on the circuit model definition - */ - VTR_ASSERT(1 == circuit_lib.port_size(interc_model_outputs[0])); - - /* Create nets to wire between the MUX and PB module */ - /* Add a net to wire the inputs of the multiplexer to its source pb_graph_pin inside pb_module - * Here is a tricky part. - * Not every input edges from the destination pb_graph_pin is used in the physical_model of pb_type - * So, we will skip these input edges when building nets - */ - int mux_input_pin_id = 0; - for (int iedge = 0; iedge < des_pb_graph_pin->num_input_edges; iedge++) { - if (physical_mode != des_pb_graph_pin->input_edges[iedge]->interconnect->parent_mode) { - continue; - } - /* Ensure that the input edge has only 1 input pin! */ - check_pb_graph_edge(*(des_pb_graph_pin->input_edges[iedge])); - t_pb_graph_pin* src_pb_graph_pin = des_pb_graph_pin->input_edges[iedge]->input_pins[0]; - /* Add a net, set its source and sink */ - add_module_pb_graph_pin2pin_net(module_manager, pb_module, - mux_module, mux_instance, - circuit_lib.port_lib_name(interc_model_inputs[0]), - mux_input_pin_id, - module_name_prefix, - src_pb_graph_pin, - INPUT2INPUT_INTERC); - mux_input_pin_id++; - } - /* Ensure all the fan_in has been covered */ - VTR_ASSERT(mux_input_pin_id == fan_in); - - /* Add a net to wire the output of the multiplexer to des_pb_graph_pin */ - add_module_pb_graph_pin2pin_net(module_manager, pb_module, - mux_module, mux_instance, - circuit_lib.port_lib_name(interc_model_outputs[0]), - 0, /* MUX should have only 1 pin in its output port */ - module_name_prefix, - des_pb_graph_pin, - OUTPUT2OUTPUT_INTERC); - break; - } - default: - vpr_printf(TIO_MESSAGE_ERROR, - "(File:%s,[LINE%d])Invalid interconnection type for %s [at Architecture XML LINE%d]!\n", - __FILE__, __LINE__, cur_interc->name, cur_interc->line_num); - exit(1); - } -} - -/******************************************************************** - * Add modules and nets for programmable/non-programmable interconnections - * which end to a port of pb_module - * This function will add the following elements to a module - * 1. Instances of direct connections - * 2. Instances of programmable routing multiplexers - * 3. nets to connect direct connections/multiplexer - * - * +-----------------------------------------+ - * | - * | +--------------+ +------------+ - * |--->| |--->| | - * |... | Multiplexers |... | | - * |--->| |--->| | - * | +--------------+ | des_pb_ | - * | | graph_node | - * | +--------------+ | | - * |--->| |--->| | - * | ...| Direct |... | | - * |--->| Connections |--->| | - * | +--------------+ +------------+ - * | - * +----------------------------------------+ - - * - * Note: this function should be run after ALL the child pb_modules - * have been added to the pb_module and ALL the ports defined - * in pb_type have been added to the pb_module!!! - * - ********************************************************************/ -static -void add_module_pb_graph_port_interc(ModuleManager& module_manager, - const ModuleId& pb_module, - std::vector& memory_modules, - std::vector& memory_instances, - const CircuitLibrary& circuit_lib, - t_pb_graph_node* des_pb_graph_node, - const std::string& module_name_prefix, - const e_spice_pb_port_type& pb_port_type, - t_mode* physical_mode) { - switch (pb_port_type) { - case SPICE_PB_PORT_INPUT: { - for (int iport = 0; iport < des_pb_graph_node->num_input_ports; ++iport) { - for (int ipin = 0; ipin < des_pb_graph_node->num_input_pins[iport]; ++ipin) { - /* Get the selected edge of current pin*/ - add_module_pb_graph_pin_interc(module_manager, pb_module, - memory_modules, memory_instances, - circuit_lib, - module_name_prefix, - &(des_pb_graph_node->input_pins[iport][ipin]), - physical_mode); - } - } - break; - } - case SPICE_PB_PORT_OUTPUT: { - for (int iport = 0; iport < des_pb_graph_node->num_output_ports; ++iport) { - for (int ipin = 0; ipin < des_pb_graph_node->num_output_pins[iport]; ++ipin) { - add_module_pb_graph_pin_interc(module_manager, pb_module, - memory_modules, memory_instances, - circuit_lib, - module_name_prefix, - &(des_pb_graph_node->output_pins[iport][ipin]), - physical_mode); - } - } - break; - } - case SPICE_PB_PORT_CLOCK: { - for (int iport = 0; iport < des_pb_graph_node->num_clock_ports; ++iport) { - for (int ipin = 0; ipin < des_pb_graph_node->num_clock_pins[iport]; ++ipin) { - add_module_pb_graph_pin_interc(module_manager, pb_module, - memory_modules, memory_instances, - circuit_lib, - module_name_prefix, - &(des_pb_graph_node->clock_pins[iport][ipin]), - physical_mode); - } - } - break; - } - default: - vpr_printf(TIO_MESSAGE_ERROR, - "(File:%s,[LINE%d]) Invalid pb port type!\n", - __FILE__, __LINE__); - exit(1); - } -} - -/******************************************************************** - * TODO: - * Add modules and nets for programmable/non-programmable interconnections - * inside a module of pb_type - * This function will add the following elements to a module - * 1. Instances of direct connections - * 2. Instances of programmable routing multiplexers - * 3. nets to connect direct connections/multiplexer - * - * Pb_module - * +--------------------------------------------------------------+ - * | | - * | +--------------+ +------------+ +--------------+ | - * |--->| |--->| |--->| |--->| - * |... | Multiplexers |... | |... | Multiplexers |... | - * |--->| |--->| |--->| |--->| - * | +--------------+ | Child | +--------------+ | - * | | Pb_modules | | - * | +--------------+ | | +--------------+ | - * |--->| |--->| |--->| |--->| - * | ...| Direct |... | |... | Direct |... | - * |--->| Connections |--->| |--->| Connections |--->| - * | +--------------+ +------------+ +--------------+ | - * | | - * +--------------------------------------------------------------+ - * - * Note: this function should be run after ALL the child pb_modules - * have been added to the pb_module and ALL the ports defined - * in pb_type have been added to the pb_module!!! - * - ********************************************************************/ -static -void add_module_pb_graph_interc(ModuleManager& module_manager, - const ModuleId& pb_module, - std::vector& memory_modules, - std::vector& memory_instances, - const CircuitLibrary& circuit_lib, - t_pb_graph_node* physical_pb_graph_node, - const std::string& module_name_prefix, - const int& physical_mode_index) { - /* Check cur_pb_graph_node*/ - if (NULL == physical_pb_graph_node) { - vpr_printf(TIO_MESSAGE_ERROR, - "(File:%s,[LINE%d]) Invalid cur_pb_graph_node.\n", - __FILE__, __LINE__); - exit(1); - } - - /* Assign physical mode */ - t_mode* physical_mode = &(physical_pb_graph_node->pb_type->modes[physical_mode_index]); - - /* We check output_pins of cur_pb_graph_node and its the input_edges - * Built the interconnections between outputs of cur_pb_graph_node and outputs of child_pb_graph_node - * child_pb_graph_node.output_pins -----------------> cur_pb_graph_node.outpins - * /|\ - * | - * input_pins, edges, output_pins - */ - add_module_pb_graph_port_interc(module_manager, pb_module, - memory_modules, memory_instances, - circuit_lib, - physical_pb_graph_node, - module_name_prefix, - SPICE_PB_PORT_OUTPUT, - physical_mode); - - /* We check input_pins of child_pb_graph_node and its the input_edges - * Built the interconnections between inputs of cur_pb_graph_node and inputs of child_pb_graph_node - * cur_pb_graph_node.input_pins -----------------> child_pb_graph_node.input_pins - * /|\ - * | - * input_pins, edges, output_pins - */ - for (int child = 0; child < physical_pb_graph_node->pb_type->modes[physical_mode_index].num_pb_type_children; ++child) { - for (int inst = 0; inst < physical_pb_graph_node->pb_type->modes[physical_mode_index].pb_type_children[child].num_pb; ++inst) { - t_pb_graph_node* child_pb_graph_node = &(physical_pb_graph_node->child_pb_graph_nodes[physical_mode_index][child][inst]); - /* For each child_pb_graph_node input pins*/ - add_module_pb_graph_port_interc(module_manager, pb_module, - memory_modules, memory_instances, - circuit_lib, - child_pb_graph_node, - module_name_prefix, - SPICE_PB_PORT_INPUT, - physical_mode); - - /* For each child_pb_graph_node clock pins*/ - add_module_pb_graph_port_interc(module_manager, pb_module, - memory_modules, memory_instances, - circuit_lib, - child_pb_graph_node, - module_name_prefix, - SPICE_PB_PORT_CLOCK, - physical_mode); - } - } -} - /******************************************************************** * Print Verilog modules of physical blocks inside a grid (CLB, I/O. etc.) * This function will traverse the graph of complex logic block (t_pb_graph_node) @@ -843,9 +108,6 @@ void add_module_pb_graph_interc(ModuleManager& module_manager, static void print_verilog_physical_blocks_rec(std::fstream& fp, ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - const MuxLibrary& mux_lib, - t_sram_orgz_info* cur_sram_orgz_info, t_pb_graph_node* physical_pb_graph_node, const e_side& io_side, const bool& use_explicit_mapping) { @@ -872,8 +134,7 @@ void print_verilog_physical_blocks_rec(std::fstream& fp, if (FALSE == is_primitive_pb_type(physical_pb_type)) { for (int ipb = 0; ipb < physical_pb_type->modes[physical_mode_index].num_pb_type_children; ++ipb) { /* Go recursive to visit the children */ - print_verilog_physical_blocks_rec(fp, module_manager, circuit_lib, mux_lib, - cur_sram_orgz_info, + print_verilog_physical_blocks_rec(fp, module_manager, &(physical_pb_graph_node->child_pb_graph_nodes[physical_mode_index][ipb][0]), io_side, use_explicit_mapping); @@ -882,8 +143,7 @@ void print_verilog_physical_blocks_rec(std::fstream& fp, /* For leaf node, a primitive Verilog module will be generated */ if (TRUE == is_primitive_pb_type(physical_pb_type)) { - print_verilog_primitive_block(fp, module_manager, circuit_lib, - cur_sram_orgz_info, + print_verilog_primitive_block(fp, module_manager, physical_pb_graph_node, io_side, use_explicit_mapping); @@ -896,102 +156,8 @@ void print_verilog_physical_blocks_rec(std::fstream& fp, std::string pb_module_name = generate_physical_block_module_name(pb_module_name_prefix, physical_pb_type); /* Register the Verilog module in module manager */ - ModuleId pb_module = module_manager.add_module(pb_module_name); - VTR_ASSERT(ModuleId::INVALID() != pb_module); - - /* Add ports to the Verilog module */ - add_pb_type_ports_to_module_manager(module_manager, pb_module, physical_pb_type); - - /* Vectors to record all the memory modules have been added - * They are used to add module nets of configuration bus - */ - std::vector memory_modules; - std::vector memory_instances; - - /* TODO: this should be added to the cur_sram_orgz_info !!! */ - t_spice_model* mem_model = NULL; - get_sram_orgz_info_mem_model(cur_sram_orgz_info, & mem_model); - CircuitModelId sram_model = circuit_lib.model(mem_model->name); - VTR_ASSERT(CircuitModelId::INVALID() != sram_model); - - /* Add all the child Verilog modules as instances */ - for (int ichild = 0; ichild < physical_pb_type->modes[physical_mode_index].num_pb_type_children; ++ichild) { - /* Get the name and module id for this child pb_type */ - std::string child_pb_module_name = generate_physical_block_module_name(pb_module_name_prefix, &(physical_pb_type->modes[physical_mode_index].pb_type_children[ichild])); - ModuleId child_pb_module = module_manager.find_module(child_pb_module_name); - /* We must have one valid id! */ - VTR_ASSERT(true == module_manager.valid_module_id(child_pb_module)); - - /* Each child may exist multiple times in the hierarchy*/ - for (int inst = 0; inst < physical_pb_type->modes[physical_mode_index].pb_type_children[ichild].num_pb; ++inst) { - size_t child_instance_id = module_manager.num_instance(pb_module, child_pb_module); - /* Ensure the instance of this child module is the same as placement index, - * This check is necessary because placement_index is used to identify instance id for children - * when adding local interconnection for this pb_type - */ - VTR_ASSERT(child_instance_id == (size_t)physical_pb_graph_node->child_pb_graph_nodes[physical_mode_index][ichild][inst].placement_index); - - /* Add the memory module as a child of primitive module */ - module_manager.add_child_module(pb_module, child_pb_module); - /* Identify if this sub module includes configuration bits, - * we will update the memory module and instance list - */ - if (0 < find_module_num_config_bits(module_manager, child_pb_module, - circuit_lib, sram_model, - cur_sram_orgz_info->type)) { - memory_modules.push_back(child_pb_module); - memory_instances.push_back(child_instance_id); - } - } - } - - /* Add modules and nets for programmable/non-programmable interconnections - * inside the Verilog module - */ - add_module_pb_graph_interc(module_manager, pb_module, - memory_modules, memory_instances, - circuit_lib, physical_pb_graph_node, - pb_module_name_prefix, - physical_mode_index); - - /* Add global ports to the pb_module: - * This is a much easier job after adding sub modules (instances), - * we just need to find all the global ports from the child modules and build a list of it - */ - add_module_global_ports_from_child_modules(module_manager, pb_module); - - /* Count GPIO ports from the sub-modules under this Verilog module - * This is a much easier job after adding sub modules (instances), - * we just need to find all the I/O ports from the child modules and build a list of it - */ - add_module_gpio_ports_from_child_modules(module_manager, pb_module); - - /* Count shared SRAM ports from the sub-modules under this Verilog module - * This is a much easier job after adding sub modules (instances), - * we just need to find all the I/O ports from the child modules and build a list of it - */ - size_t module_num_shared_config_bits = find_module_num_shared_config_bits_from_child_modules(module_manager, pb_module); - if (0 < module_num_shared_config_bits) { - add_reserved_sram_ports_to_module_manager(module_manager, pb_module, module_num_shared_config_bits); - } - - /* Count SRAM ports from the sub-modules under this Verilog module - * This is a much easier job after adding sub modules (instances), - * we just need to find all the I/O ports from the child modules and build a list of it - */ - size_t module_num_config_bits = find_module_num_config_bits_from_child_modules(module_manager, pb_module, circuit_lib, sram_model, cur_sram_orgz_info->type); - if (0 < module_num_config_bits) { - add_sram_ports_to_module_manager(module_manager, pb_module, circuit_lib, sram_model, cur_sram_orgz_info->type, module_num_config_bits); - } - - /* Add module nets to connect memory cells inside - * This is a one-shot addition that covers all the memory modules in this pb module! - */ - if (false == memory_modules.empty()) { - add_module_nets_memory_config_bus(module_manager, pb_module, - memory_modules, memory_instances, - cur_sram_orgz_info->type, circuit_lib.design_tech_type(sram_model)); - } + ModuleId pb_module = module_manager.find_module(pb_module_name); + VTR_ASSERT(true == module_manager.valid_module_id(pb_module)); /* Comment lines */ print_verilog_comment(fp, std::string("----- BEGIN Physical programmable logic block Verilog module: " + std::string(physical_pb_type->name) + " -----")); @@ -1015,9 +181,6 @@ void print_verilog_physical_blocks_rec(std::fstream& fp, *****************************************************************************/ static void print_verilog_grid(ModuleManager& module_manager, - const MuxLibrary& mux_lib, - const CircuitLibrary& circuit_lib, - t_sram_orgz_info* cur_sram_orgz_info, const std::string& verilog_dir, const std::string& subckt_dir, t_type_ptr phy_block_type, @@ -1072,8 +235,7 @@ void print_verilog_grid(ModuleManager& module_manager, print_verilog_comment(fp, std::string("---- BEGIN Sub-module of physical block:" + std::string(phy_block_type->name) + " ----")); /* Print Verilog modules starting from the top-level pb_type/pb_graph_node, and traverse the graph in a recursive way */ - print_verilog_physical_blocks_rec(fp, module_manager, circuit_lib, mux_lib, - cur_sram_orgz_info, + print_verilog_physical_blocks_rec(fp, module_manager, phy_block_type->pb_graph_head, border_side, use_explicit_mapping); @@ -1082,92 +244,9 @@ void print_verilog_grid(ModuleManager& module_manager, /* Create a Verilog Module for the top-level physical block, and add to module manager */ std::string grid_module_name = generate_grid_block_module_name(std::string(grid_verilog_file_name_prefix), std::string(phy_block_type->name), IO_TYPE == phy_block_type, border_side); - ModuleId grid_module = module_manager.add_module(grid_module_name); + ModuleId grid_module = module_manager.find_module(grid_module_name); VTR_ASSERT(true == module_manager.valid_module_id(grid_module)); - /* Vectors to record all the memory modules have been added - * They are used to add module nets of configuration bus - */ - std::vector memory_modules; - std::vector memory_instances; - - /* TODO: this should be added to the cur_sram_orgz_info !!! */ - t_spice_model* mem_model = NULL; - get_sram_orgz_info_mem_model(cur_sram_orgz_info, & mem_model); - CircuitModelId sram_model = circuit_lib.model(mem_model->name); - VTR_ASSERT(CircuitModelId::INVALID() != sram_model); - - /* Generate the name of the Verilog module for this pb_type */ - std::string pb_module_name_prefix(grid_verilog_file_name_prefix); - std::string pb_module_name = generate_grid_physical_block_module_name(pb_module_name_prefix, phy_block_type->pb_graph_head->pb_type, border_side); - ModuleId pb_module = module_manager.find_module(pb_module_name); - VTR_ASSERT(true == module_manager.valid_module_id(pb_module)); - - /* Add all the sub modules */ - for (int iz = 0; iz < phy_block_type->capacity; ++iz) { - size_t pb_instance_id = module_manager.num_instance(grid_module, pb_module); - module_manager.add_child_module(grid_module, pb_module); - /* Identify if this sub module includes configuration bits, - * we will update the memory module and instance list - */ - if (0 < find_module_num_config_bits(module_manager, pb_module, - circuit_lib, sram_model, - cur_sram_orgz_info->type)) { - memory_modules.push_back(pb_module); - memory_instances.push_back(pb_instance_id); - } - } - - /* Add grid ports(pins) to the module */ - add_grid_module_pb_type_ports(module_manager, grid_module, - phy_block_type, border_side); - - /* Add module nets to connect the pb_type ports to sub modules */ - for (const size_t& child_instance : module_manager.child_module_instances(grid_module, pb_module)) { - add_grid_module_nets_connect_pb_type_ports(module_manager, grid_module, - pb_module, child_instance, - phy_block_type, border_side); - } - - /* Add global ports to the pb_module: - * This is a much easier job after adding sub modules (instances), - * we just need to find all the global ports from the child modules and build a list of it - */ - add_module_global_ports_from_child_modules(module_manager, grid_module); - - /* Count GPIO ports from the sub-modules under this Verilog module - * This is a much easier job after adding sub modules (instances), - * we just need to find all the I/O ports from the child modules and build a list of it - */ - add_module_gpio_ports_from_child_modules(module_manager, grid_module); - - /* Count shared SRAM ports from the sub-modules under this Verilog module - * This is a much easier job after adding sub modules (instances), - * we just need to find all the I/O ports from the child modules and build a list of it - */ - size_t module_num_shared_config_bits = find_module_num_shared_config_bits_from_child_modules(module_manager, grid_module); - if (0 < module_num_shared_config_bits) { - add_reserved_sram_ports_to_module_manager(module_manager, grid_module, module_num_shared_config_bits); - } - - /* Count SRAM ports from the sub-modules under this Verilog module - * This is a much easier job after adding sub modules (instances), - * we just need to find all the I/O ports from the child modules and build a list of it - */ - size_t module_num_config_bits = find_module_num_config_bits_from_child_modules(module_manager, grid_module, circuit_lib, sram_model, cur_sram_orgz_info->type); - if (0 < module_num_config_bits) { - add_sram_ports_to_module_manager(module_manager, grid_module, circuit_lib, sram_model, cur_sram_orgz_info->type, module_num_config_bits); - } - - /* Add module nets to connect memory cells inside - * This is a one-shot addition that covers all the memory modules in this pb module! - */ - if (false == memory_modules.empty()) { - add_module_nets_memory_config_bus(module_manager, grid_module, - memory_modules, memory_instances, - cur_sram_orgz_info->type, circuit_lib.design_tech_type(sram_model)); - } - /* Write the verilog module */ print_verilog_comment(fp, std::string("----- BEGIN Grid Verilog module: " + module_manager.module_name(grid_module) + " -----")); write_verilog_module_to_file(fp, module_manager, grid_module, use_explicit_mapping); @@ -1193,12 +272,9 @@ void print_verilog_grid(ModuleManager& module_manager, * 3. Only one module for each heterogeneous block ****************************************************************************/ void print_verilog_grids(ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - const MuxLibrary& mux_lib, - t_sram_orgz_info* cur_sram_orgz_info, const std::string& verilog_dir, const std::string& subckt_dir, - const bool& is_explicit_mapping) { + const bool& use_explicit_mapping) { /* Enumerate the types, dump one Verilog module for each */ for (int itype = 0; itype < num_types; itype++) { if (EMPTY_TYPE == &type_descriptors[itype]) { @@ -1208,31 +284,28 @@ void print_verilog_grids(ModuleManager& module_manager, /* Special for I/O block, generate one module for each border side */ for (int iside = 0; iside < NUM_SIDES; iside++) { Side side_manager(iside); - print_verilog_grid(module_manager, mux_lib, circuit_lib, - cur_sram_orgz_info, + print_verilog_grid(module_manager, verilog_dir, subckt_dir, &type_descriptors[itype], side_manager.get_side(), - is_explicit_mapping); + use_explicit_mapping); } continue; } else if (FILL_TYPE == &type_descriptors[itype]) { /* For CLB */ - print_verilog_grid(module_manager, mux_lib, circuit_lib, - cur_sram_orgz_info, + print_verilog_grid(module_manager, verilog_dir, subckt_dir, &type_descriptors[itype], NUM_SIDES, - is_explicit_mapping); + use_explicit_mapping); continue; } else { /* For heterogenenous blocks */ - print_verilog_grid(module_manager, mux_lib, circuit_lib, - cur_sram_orgz_info, + print_verilog_grid(module_manager, verilog_dir, subckt_dir, &type_descriptors[itype], NUM_SIDES, - is_explicit_mapping); + use_explicit_mapping); } } diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_grid.h b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_grid.h index b99ffd430..d1bc8cdfb 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_grid.h +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_grid.h @@ -11,11 +11,8 @@ #include "mux_library.h" void print_verilog_grids(ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - const MuxLibrary& mux_lib, - t_sram_orgz_info* cur_sram_orgz_info, const std::string& verilog_dir, const std::string& subckt_dir, - const bool& is_explicit_mapping); + const bool& use_explicit_mapping); #endif