diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_naming.cpp b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_naming.cpp index 913c17e12..76c0e7086 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_naming.cpp +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_naming.cpp @@ -760,3 +760,31 @@ std::string generate_physical_block_module_name(const std::string& prefix, return module_name; } + + +/********************************************************************* + * Generate the port name of a Verilog module describing a pb_type + * The name convention is + * _ + ********************************************************************/ +std::string generate_pb_type_port_name(t_port* pb_type_port) { + std::string port_name; + + port_name = std::string(pb_type_port->parent_pb_type->name) + std::string("_") + std::string(pb_type_port->name); + + return port_name; +} + +/********************************************************************* + * Generate the global I/O port name of a Verilog module + * This is mainly used by I/O circuit models + ********************************************************************/ +std::string generate_fpga_global_io_port_name(const std::string& prefix, + const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model) { + std::string port_name(prefix); + + port_name += circuit_lib.model_name(circuit_model); + + return port_name; +} diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_naming.h b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_naming.h index 7d65a9605..989c60714 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_naming.h +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_naming.h @@ -143,4 +143,9 @@ std::string generate_grid_block_module_name(const std::string& prefix, std::string generate_physical_block_module_name(const std::string& prefix, t_pb_type* physical_pb_type); +std::string generate_pb_type_port_name(t_port* pb_type_port); + +std::string generate_fpga_global_io_port_name(const std::string& prefix, + const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model); #endif diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_pbtypes_utils.c b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_pbtypes_utils.c index 9da08d95b..b1eb28306 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_pbtypes_utils.c +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_pbtypes_utils.c @@ -1,7 +1,15 @@ -/***********************************/ -/* SPICE Modeling for VPR */ -/* Xifan TANG, EPFL/LSI */ -/***********************************/ +/******************************************************************** + * This file includes most utilized functions to operate on pb_type + * related data structures, including t_pb_type, t_pb_graph_node, t_pb + * + * Note: + * If you want to classify functions, functions in this file should meet + * at least one of it + * 1. non-generic data query of pb_type - related data structures + * 2. non-generic mutator/copy the pb_type + * + * Generic accessors/mutators should be a method of the data structure + ********************************************************************/ #include #include #include @@ -12,6 +20,7 @@ #include /* Include vpr structs*/ +#include "vtr_assert.h" #include "util.h" #include "physical_types.h" #include "vpr_types.h" @@ -1322,6 +1331,54 @@ t_port* find_pb_type_port_match_spice_model_port(t_pb_type* pb_type, return ret; } +/******************************************************************** + * Return a list of ports of a pb_type which matches the ports defined + * in its linked circuit model + * This function will only care if the port type matches + *******************************************************************/ +std::vector find_pb_type_ports_match_circuit_model_port_type(t_pb_type* pb_type, + enum e_spice_model_port_type port_type) { + std::vector ports; + + for (int iport = 0; iport < pb_type->num_ports; ++iport) { + /* Check the circuit_port id of the port ? */ + VTR_ASSERT(CircuitPortId::INVALID() != pb_type->ports[iport].circuit_model_port); + switch (port_type) { + case SPICE_MODEL_PORT_INPUT: + if ( (IN_PORT == pb_type->ports[iport].type) + && (0 == pb_type->ports[iport].is_clock) ) { + ports.push_back(&pb_type->ports[iport]); + } + break; + case SPICE_MODEL_PORT_OUTPUT: + if ( (OUT_PORT == pb_type->ports[iport].type) + && (0 == pb_type->ports[iport].is_clock) ) { + ports.push_back(&pb_type->ports[iport]); + } + break; + case SPICE_MODEL_PORT_INOUT: + if ( (INOUT_PORT == pb_type->ports[iport].type) + && (0 == pb_type->ports[iport].is_clock) ) { + ports.push_back(&pb_type->ports[iport]); + } + break; + case SPICE_MODEL_PORT_CLOCK: + if ( (IN_PORT == pb_type->ports[iport].type) + && (1 == pb_type->ports[iport].is_clock) ) { + ports.push_back(&pb_type->ports[iport]); + } + break; + /* Configuration ports are not in pb_type definition */ + default: + vpr_printf(TIO_MESSAGE_ERROR, + "(File:%s, [LINE%d]) Invalid type for port!\n", + __FILE__, __LINE__); + exit(1); + } + } + + return ports; +} t_port** find_pb_type_ports_match_spice_model_port_type(t_pb_type* pb_type, enum e_spice_model_port_type port_type, diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_pbtypes_utils.h b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_pbtypes_utils.h index 8a85329c0..ee5db00f4 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_pbtypes_utils.h +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_pbtypes_utils.h @@ -1,6 +1,9 @@ #ifndef FPGA_X2P_PBTYPES_UTILS_H #define FPGA_X2P_PBTYPES_UTILS_H +/* Only include header files those are required by the data types in the following function declaration */ +#include +#include "fpga_x2p_types.h" #include "fpga_x2p_bitstream_utils.h" void check_pb_graph_edge(t_pb_graph_edge pb_graph_edge); @@ -100,6 +103,9 @@ void map_clb_pins_to_pb_graph_pins(); t_port* find_pb_type_port_match_spice_model_port(t_pb_type* pb_type, t_spice_model_port* spice_model_port); +std::vector find_pb_type_ports_match_circuit_model_port_type(t_pb_type* pb_type, + enum e_spice_model_port_type port_type); + t_port** find_pb_type_ports_match_spice_model_port_type(t_pb_type* pb_type, enum e_spice_model_port_type port_type, int* port_num); diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/link_arch_circuit_lib.cpp b/vpr7_x2p/vpr/SRC/fpga_x2p/base/link_arch_circuit_lib.cpp index 8e1848932..86d3aabee 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/link_arch_circuit_lib.cpp +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/link_arch_circuit_lib.cpp @@ -270,12 +270,12 @@ int link_pb_type_port_to_circuit_model_ports(const t_pb_type* cur_pb_type, cur_pb_type->ports[iport].circuit_model_port = CircuitPortId::INVALID(); } - /* Return if SPICE_MODEL is NULL */ + /* Return if circuit model is NULL */ if (CircuitModelId::INVALID() == circuit_model) { return 0; } - /* For each port, find a SPICE model port, which has the same name and port size */ + /* For each port, find a circuit model port, which has the same name and port size */ for (auto& port : circuit_lib.model_ports(circuit_model)) { t_port* cur_pb_type_port = find_pb_type_port_match_circuit_model_port(cur_pb_type, circuit_lib, port); /* Not every spice_model_port can find a mapped pb_type_port. @@ -292,7 +292,7 @@ int link_pb_type_port_to_circuit_model_ports(const t_pb_type* cur_pb_type, for (int iport = 0; iport < cur_pb_type->num_ports; iport++) { if (CircuitPortId::INVALID() == cur_pb_type->ports[iport].circuit_model_port) { vpr_printf(TIO_MESSAGE_ERROR, - "(File:%s, [LINE%d])Pb_type(%s) Port(%s) cannot find a corresponding port in SPICE model(%s)\n", + "(File:%s, [LINE%d]) Pb_type(%s) Port(%s) cannot find a corresponding port in SPICE model(%s)\n", __FILE__, __LINE__, cur_pb_type->name, cur_pb_type->ports[iport].name, circuit_lib.model_name(circuit_model).c_str()); exit(1); diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager_utils.cpp b/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager_utils.cpp index 6b7c9bdc9..120ed3958 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager_utils.cpp +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager_utils.cpp @@ -14,6 +14,7 @@ #include "module_manager.h" #include "fpga_x2p_naming.h" +#include "fpga_x2p_pbtypes_utils.h" #include "module_manager_utils.h" @@ -210,3 +211,44 @@ void add_sram_ports_to_module_manager(ModuleManager& module_manager, } } +/******************************************************************** + * Add ports of a pb_type block to module manager + * Port addition will follow the sequence: inout, input, output, clock + * This will help use to keep a clean module definition when printing out + * To avoid port mismatch between the pb_type and its linked circuit model + * This function will also check that each pb_type port is actually exist + * in the linked circuit model + *******************************************************************/ +void add_pb_type_ports_to_module_manager(ModuleManager& module_manager, + const ModuleId& module_id, + t_pb_type* cur_pb_type) { + + /* Find the inout ports required by the primitive pb_type, and add them to the module */ + std::vector pb_type_inout_ports = find_pb_type_ports_match_circuit_model_port_type(cur_pb_type, SPICE_MODEL_PORT_INOUT); + for (auto port : pb_type_inout_ports) { + BasicPort module_port(generate_pb_type_port_name(port), port->num_pins); + module_manager.add_port(module_id, module_port, ModuleManager::MODULE_INOUT_PORT); + } + + /* Find the input ports required by the primitive pb_type, and add them to the module */ + std::vector pb_type_input_ports = find_pb_type_ports_match_circuit_model_port_type(cur_pb_type, SPICE_MODEL_PORT_INPUT); + for (auto port : pb_type_input_ports) { + BasicPort module_port(generate_pb_type_port_name(port), port->num_pins); + module_manager.add_port(module_id, module_port, ModuleManager::MODULE_INPUT_PORT); + } + + /* Find the output ports required by the primitive pb_type, and add them to the module */ + std::vector pb_type_output_ports = find_pb_type_ports_match_circuit_model_port_type(cur_pb_type, SPICE_MODEL_PORT_OUTPUT); + for (auto port : pb_type_output_ports) { + BasicPort module_port(generate_pb_type_port_name(port), port->num_pins); + module_manager.add_port(module_id, module_port, ModuleManager::MODULE_OUTPUT_PORT); + } + + /* Find the clock ports required by the primitive pb_type, and add them to the module */ + std::vector pb_type_clock_ports = find_pb_type_ports_match_circuit_model_port_type(cur_pb_type, SPICE_MODEL_PORT_CLOCK); + for (auto port : pb_type_clock_ports) { + BasicPort module_port(generate_pb_type_port_name(port), port->num_pins); + module_manager.add_port(module_id, module_port, ModuleManager::MODULE_CLOCK_PORT); + } +} + diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager_utils.h b/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager_utils.h index 17d395cdb..cbdc04891 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager_utils.h +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager_utils.h @@ -10,6 +10,7 @@ #include #include "device_port.h" #include "spice_types.h" +#include "vpr_types.h" #include "circuit_library.h" #include "module_manager.h" @@ -38,5 +39,9 @@ void add_sram_ports_to_module_manager(ModuleManager& module_manager, const e_sram_orgz sram_orgz_type, const size_t& port_size); +void add_pb_type_ports_to_module_manager(ModuleManager& module_manager, + const ModuleId& module_id, + t_pb_type* cur_pb_type); + #endif 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 3d3e45e55..5e56b5327 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_grid.cpp +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_grid.cpp @@ -19,6 +19,8 @@ #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" @@ -90,37 +92,28 @@ void print_verilog_primitive_block(std::fstream& fp, 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_by_type(primitive_model, SPICE_MODEL_PORT_INPUT, true, false); + 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_INPUT_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 */ - 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(circuit_lib.port_lib_name(port), circuit_lib.port_size(port)); - module_manager.add_port(primitive_module, module_port, ModuleManager::MODULE_INOUT_PORT); - } - /* Find the input ports required by the primitive node, and add them to the module */ - std::vector primitive_model_input_ports = circuit_lib.model_ports_by_type(primitive_model, SPICE_MODEL_PORT_INPUT); - for (auto port : primitive_model_input_ports) { - BasicPort module_port(circuit_lib.port_lib_name(port), circuit_lib.port_size(port)); - module_manager.add_port(primitive_module, module_port, ModuleManager::MODULE_INPUT_PORT); - } - /* Find the output ports required by the primitive node, and add them to the module */ - std::vector primitive_model_output_ports = circuit_lib.model_ports_by_type(primitive_model, SPICE_MODEL_PORT_OUTPUT); - for (auto port : primitive_model_output_ports) { - BasicPort module_port(circuit_lib.port_lib_name(port), circuit_lib.port_size(port)); - module_manager.add_port(primitive_module, module_port, ModuleManager::MODULE_OUTPUT_PORT); - } - /* Find the clock ports required by the primitive node, and add them to the module */ - std::vector primitive_model_clock_ports = circuit_lib.model_ports_by_type(primitive_model, SPICE_MODEL_PORT_CLOCK); - for (auto port : primitive_model_clock_ports) { - BasicPort module_port(circuit_lib.port_lib_name(port), circuit_lib.port_size(port)); - module_manager.add_port(primitive_module, module_port, ModuleManager::MODULE_CLOCK_PORT); + 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_INOUT_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_pb_type_ports_to_module_manager(module_manager, primitive_module, primitive_pb_graph_node->pb_type); /* Add configuration ports */ /* TODO: Shared SRAM ports*/ diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_pbtypes.c b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_pbtypes.c index 4e6ec1d4a..4a54959b4 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_pbtypes.c +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_pbtypes.c @@ -12,6 +12,7 @@ #include /* Include vpr structs*/ +#include "vtr_assert.h" #include "util.h" #include "physical_types.h" #include "vpr_types.h"