refactored port addition for pb_types in Verilog generation

This commit is contained in:
tangxifan 2019-10-08 14:03:17 -06:00
parent 512e9f4e8e
commit ea2942640e
9 changed files with 168 additions and 31 deletions

View File

@ -760,3 +760,31 @@ std::string generate_physical_block_module_name(const std::string& prefix,
return module_name; return module_name;
} }
/*********************************************************************
* Generate the port name of a Verilog module describing a pb_type
* The name convention is
* <pb_type_name>_<port_name>
********************************************************************/
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;
}

View File

@ -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, std::string generate_physical_block_module_name(const std::string& prefix,
t_pb_type* physical_pb_type); 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 #endif

View File

@ -1,7 +1,15 @@
/***********************************/ /********************************************************************
/* SPICE Modeling for VPR */ * This file includes most utilized functions to operate on pb_type
/* Xifan TANG, EPFL/LSI */ * 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 <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -12,6 +20,7 @@
#include <unistd.h> #include <unistd.h>
/* Include vpr structs*/ /* Include vpr structs*/
#include "vtr_assert.h"
#include "util.h" #include "util.h"
#include "physical_types.h" #include "physical_types.h"
#include "vpr_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 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<t_port*> find_pb_type_ports_match_circuit_model_port_type(t_pb_type* pb_type,
enum e_spice_model_port_type port_type) {
std::vector<t_port*> 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, t_port** find_pb_type_ports_match_spice_model_port_type(t_pb_type* pb_type,
enum e_spice_model_port_type port_type, enum e_spice_model_port_type port_type,

View File

@ -1,6 +1,9 @@
#ifndef FPGA_X2P_PBTYPES_UTILS_H #ifndef FPGA_X2P_PBTYPES_UTILS_H
#define 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 <vector>
#include "fpga_x2p_types.h"
#include "fpga_x2p_bitstream_utils.h" #include "fpga_x2p_bitstream_utils.h"
void check_pb_graph_edge(t_pb_graph_edge pb_graph_edge); 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_port* find_pb_type_port_match_spice_model_port(t_pb_type* pb_type,
t_spice_model_port* spice_model_port); t_spice_model_port* spice_model_port);
std::vector<t_port*> 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, t_port** find_pb_type_ports_match_spice_model_port_type(t_pb_type* pb_type,
enum e_spice_model_port_type port_type, enum e_spice_model_port_type port_type,
int* port_num); int* port_num);

View File

@ -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(); 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) { if (CircuitModelId::INVALID() == circuit_model) {
return 0; 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)) { 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); 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. /* Not every spice_model_port can find a mapped pb_type_port.

View File

@ -14,6 +14,7 @@
#include "module_manager.h" #include "module_manager.h"
#include "fpga_x2p_naming.h" #include "fpga_x2p_naming.h"
#include "fpga_x2p_pbtypes_utils.h"
#include "module_manager_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<t_port*> 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<t_port*> 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<t_port*> 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<t_port*> 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);
}
}

View File

@ -10,6 +10,7 @@
#include <vector> #include <vector>
#include "device_port.h" #include "device_port.h"
#include "spice_types.h" #include "spice_types.h"
#include "vpr_types.h"
#include "circuit_library.h" #include "circuit_library.h"
#include "module_manager.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 e_sram_orgz sram_orgz_type,
const size_t& port_size); 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 #endif

View File

@ -19,6 +19,8 @@
#include "fpga_x2p_types.h" #include "fpga_x2p_types.h"
#include "fpga_x2p_utils.h" #include "fpga_x2p_utils.h"
#include "fpga_x2p_pbtypes_utils.h" #include "fpga_x2p_pbtypes_utils.h"
#include "module_manager_utils.h"
#include "fpga_x2p_globals.h"
/* Header files for Verilog generator */ /* Header files for Verilog generator */
#include "verilog_global.h" #include "verilog_global.h"
@ -90,37 +92,28 @@ void print_verilog_primitive_block(std::fstream& fp,
VTR_ASSERT(ModuleId::INVALID() != primitive_module); VTR_ASSERT(ModuleId::INVALID() != primitive_module);
/* Find the global ports required by the primitive node, and add them to the module */ /* Find the global ports required by the primitive node, and add them to the module */
std::vector<CircuitPortId> primitive_model_global_ports = circuit_lib.model_global_ports_by_type(primitive_model, SPICE_MODEL_PORT_INPUT, true, false); std::vector<CircuitPortId> primitive_model_global_ports = circuit_lib.model_global_ports(primitive_model, true);
for (auto port : primitive_model_global_ports) { 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)); 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 /* 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 * 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<CircuitPortId> primitive_model_inout_ports = circuit_lib.model_ports_by_type(primitive_model, SPICE_MODEL_PORT_INOUT); std::vector<CircuitPortId> primitive_model_inout_ports = circuit_lib.model_ports_by_type(primitive_model, SPICE_MODEL_PORT_INOUT);
for (auto port : primitive_model_inout_ports) { for (auto port : primitive_model_inout_ports) {
BasicPort module_port(circuit_lib.port_lib_name(port), circuit_lib.port_size(port)); 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); 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<CircuitPortId> 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<CircuitPortId> 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<CircuitPortId> 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);
} }
/* 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 */ /* Add configuration ports */
/* TODO: Shared SRAM ports*/ /* TODO: Shared SRAM ports*/

View File

@ -12,6 +12,7 @@
#include <unistd.h> #include <unistd.h>
/* Include vpr structs*/ /* Include vpr structs*/
#include "vtr_assert.h"
#include "util.h" #include "util.h"
#include "physical_types.h" #include "physical_types.h"
#include "vpr_types.h" #include "vpr_types.h"