refactored port addition for pb_types in Verilog generation
This commit is contained in:
parent
512e9f4e8e
commit
ea2942640e
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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*/
|
||||||
|
|
|
@ -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"
|
||||||
|
|
Loading…
Reference in New Issue