update VPR7 to support global I/O ports

This commit is contained in:
tangxifan 2020-04-06 20:44:00 -06:00
parent 7a4137fdcf
commit 92a3a444f9
13 changed files with 180 additions and 27 deletions

View File

@ -145,6 +145,8 @@ void add_grid_module_nets_connect_pb_type_ports(ModuleManager& module_manager,
}
/********************************************************************
* Add module nets between primitive module and its internal circuit module
* This is only applicable to the primitive module of a grid
*******************************************************************/
static
void add_primitive_module_fpga_global_io_port(ModuleManager& module_manager,

View File

@ -352,9 +352,10 @@ size_t check_circuit_library_ports(const CircuitLibrary& circuit_lib) {
/* Check global ports: make sure all the global ports are input ports */
for (const auto& port : circuit_lib.ports()) {
if ( (circuit_lib.port_is_global(port))
&& (!circuit_lib.is_input_port(port)) ) {
&& (!circuit_lib.is_input_port(port))
&& (!circuit_lib.is_output_port(port)) ) {
vpr_printf(TIO_MESSAGE_ERROR,
"Circuit port (type=%s) of model (name=%s) is defined as global but not an input port!\n",
"Circuit port (type=%s) of model (name=%s) is defined as global but not an input/output port!\n",
CIRCUIT_MODEL_PORT_TYPE_STRING[size_t(circuit_lib.port_type(port))],
circuit_lib.model_name(port).c_str());
num_err++;

View File

@ -767,6 +767,12 @@ size_t CircuitLibrary::port_default_value(const CircuitPortId& circuit_port_id)
return port_default_values_[circuit_port_id];
}
/* Return a flag if the port is used in mode-selection purpuse of a circuit model */
bool CircuitLibrary::port_is_io(const CircuitPortId& circuit_port_id) const {
/* validate the circuit_port_id */
VTR_ASSERT(valid_circuit_port_id(circuit_port_id));
return port_is_io_[circuit_port_id];
}
/* Return a flag if the port is used in mode-selection purpuse of a circuit model */
bool CircuitLibrary::port_is_mode_select(const CircuitPortId& circuit_port_id) const {
@ -1212,6 +1218,7 @@ CircuitPortId CircuitLibrary::add_model_port(const CircuitModelId& model_id,
port_lib_names_.emplace_back();
port_inv_prefix_.emplace_back();
port_default_values_.push_back(-1);
port_is_io_.push_back(false);
port_is_mode_select_.push_back(false);
port_is_global_.push_back(false);
port_is_reset_.push_back(false);
@ -1282,6 +1289,15 @@ void CircuitLibrary::set_port_default_value(const CircuitPortId& circuit_port_id
return;
}
/* Set the is_mode_select for a port of a circuit model */
void CircuitLibrary::set_port_is_io(const CircuitPortId& circuit_port_id,
const bool& is_io) {
/* validate the circuit_port_id */
VTR_ASSERT(valid_circuit_port_id(circuit_port_id));
port_is_io_[circuit_port_id] = is_io;
return;
}
/* Set the is_mode_select for a port of a circuit model */
void CircuitLibrary::set_port_is_mode_select(const CircuitPortId& circuit_port_id,
const bool& is_mode_select) {

View File

@ -281,6 +281,7 @@ class CircuitLibrary {
std::string port_lib_name(const CircuitPortId& circuit_port_id) const;
std::string port_inv_prefix(const CircuitPortId& circuit_port_id) const;
size_t port_default_value(const CircuitPortId& circuit_port_id) const;
bool port_is_io(const CircuitPortId& circuit_port_id) const;
bool port_is_mode_select(const CircuitPortId& circuit_port_id) const;
bool port_is_global(const CircuitPortId& circuit_port_id) const;
bool port_is_reset(const CircuitPortId& circuit_port_id) const;
@ -351,6 +352,8 @@ class CircuitLibrary {
const std::string& inv_prefix);
void set_port_default_value(const CircuitPortId& circuit_port_id,
const size_t& default_val);
void set_port_is_io(const CircuitPortId& circuit_port_id,
const bool& is_io);
void set_port_is_mode_select(const CircuitPortId& circuit_port_id,
const bool& is_mode_select);
void set_port_is_global(const CircuitPortId& circuit_port_id,
@ -534,6 +537,7 @@ class CircuitLibrary {
vtr::vector<CircuitPortId, std::string> port_lib_names_;
vtr::vector<CircuitPortId, std::string> port_inv_prefix_;
vtr::vector<CircuitPortId, size_t> port_default_values_;
vtr::vector<CircuitPortId, bool> port_is_io_;
vtr::vector<CircuitPortId, bool> port_is_mode_select_;
vtr::vector<CircuitPortId, bool> port_is_global_;
vtr::vector<CircuitPortId, bool> port_is_reset_;

View File

@ -783,6 +783,11 @@ static void ProcessSpiceModelPort(ezxml_t Node,
/* Output mast of a fracturable LUT, which is to identify which intermediate LUT output will be connected to outputs */
ProcessSpiceModelPortLutOutputMask(Node, port);
if (SPICE_MODEL_PORT_INPUT == port->type) {
port->is_io = GetBooleanProperty(Node, "io", FALSE, FALSE);
ezxml_set_attr(Node, "io", NULL);
}
/* See if this is a global signal
* We assume that global signals are shared by all the SPICE Model/blocks.
* We need to check if other SPICE model has the same port name
@ -1748,6 +1753,7 @@ CircuitLibrary build_circuit_library(int num_spice_model, t_spice_model* spice_m
circuit_lib.set_port_default_value(port_id, spice_models[imodel].ports[iport].default_val);
circuit_lib.set_port_is_io(port_id, TRUE == spice_models[imodel].ports[iport].is_io);
circuit_lib.set_port_is_mode_select(port_id, TRUE == spice_models[imodel].ports[iport].mode_select);
circuit_lib.set_port_is_global(port_id, TRUE == spice_models[imodel].ports[iport].is_global);
circuit_lib.set_port_is_reset(port_id, TRUE == spice_models[imodel].ports[iport].is_reset);

View File

@ -164,6 +164,7 @@ struct s_spice_model_port {
boolean mode_select;
int default_val;
/* Global port properties */
boolean is_io;
boolean is_global;
boolean is_reset;
boolean is_set;

View File

@ -1343,10 +1343,13 @@ 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) {
const CircuitModelId& circuit_model,
const CircuitPortId& circuit_port) {
std::string port_name(prefix);
port_name += circuit_lib.model_name(circuit_model);
port_name += std::string("_");
port_name += circuit_lib.port_prefix(circuit_port);
return port_name;
}

View File

@ -232,7 +232,8 @@ 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);
const CircuitModelId& circuit_model,
const CircuitPortId& circuit_port);
std::string generate_fpga_top_module_name();

View File

@ -117,7 +117,7 @@ std::string ModuleManager::module_name(const ModuleId& module_id) const {
/* Get the string of a module port type */
std::string ModuleManager::module_port_type_str(const enum e_module_port_type& port_type) const {
std::array<const char*, NUM_MODULE_PORT_TYPES> MODULE_PORT_TYPE_STRING = {{"GLOBAL PORTS", "GPIO PORTS", "INOUT PORTS", "INPUT PORTS", "OUTPUT PORTS", "CLOCK PORTS"}};
std::array<const char*, NUM_MODULE_PORT_TYPES> MODULE_PORT_TYPE_STRING = {{"GLOBAL PORTS", "GPIN PORTS", "GPOUT PORTS", "GPIO PORTS", "INOUT PORTS", "INPUT PORTS", "OUTPUT PORTS", "CLOCK PORTS"}};
return MODULE_PORT_TYPE_STRING[port_type];
}

View File

@ -26,6 +26,8 @@ class ModuleManager {
public: /* Private data structures */
enum e_module_port_type {
MODULE_GLOBAL_PORT, /* Global inputs */
MODULE_GPIN_PORT, /* General-purpose input */
MODULE_GPOUT_PORT, /* General-purpose outputs, could be used for spypads */
MODULE_GPIO_PORT, /* General-purpose IOs, which are data IOs of the fabric */
MODULE_INOUT_PORT, /* Normal (non-global) inout ports */
MODULE_INPUT_PORT, /* Normal (non-global) input ports */

View File

@ -37,7 +37,18 @@ ModuleId add_circuit_model_to_module_manager(ModuleManager& module_manager,
/* Find global ports and add one by one */
for (const auto& port : circuit_lib.model_global_ports(circuit_model, false)) {
BasicPort port_info(circuit_lib.port_prefix(port), circuit_lib.port_size(port));
module_manager.add_port(module, port_info, ModuleManager::MODULE_GLOBAL_PORT);
if ( (SPICE_MODEL_PORT_INPUT == circuit_lib.port_type(port))
&& (false == circuit_lib.port_is_io(port)) ) {
module_manager.add_port(module, port_info, ModuleManager::MODULE_GLOBAL_PORT);
} else if (SPICE_MODEL_PORT_CLOCK == circuit_lib.port_type(port)) {
module_manager.add_port(module, port_info, ModuleManager::MODULE_GLOBAL_PORT);
} else if ( (SPICE_MODEL_PORT_INPUT == circuit_lib.port_type(port))
&& (true == circuit_lib.port_is_io(port)) ) {
module_manager.add_port(module, port_info, ModuleManager::MODULE_GPIN_PORT);
} else {
VTR_ASSERT(SPICE_MODEL_PORT_OUTPUT == circuit_lib.port_type(port));
module_manager.add_port(module, port_info, ModuleManager::MODULE_GPOUT_PORT);
}
}
/* Find other ports and add one by one */
@ -925,19 +936,35 @@ size_t find_module_num_config_bits(const ModuleManager& module_manager,
}
/********************************************************************
* Add GPIO ports to the module:
* Add General purpose I/O ports to the module:
* In this function, the following tasks are done:
* 1. find all the GPIO ports from the child modules and build a list of it,
* 2. Merge all the GPIO ports with the same name
* 1. find all the I/O ports from the child modules and build a list of it,
* 2. Merge all the I/O ports with the same name
* 3. add the ports to the pb_module
* 4. add module nets to connect to the GPIO ports of each sub module
*
* Module
* ----------------------+
* |
* child[0] |
* -----------+ |
* |----------+----> outputA[0]
* -----------+ |
* |
* child[1] |
* -----------+ |
* |----------+----> outputA[1]
* -----------+ |
*
* Note: This function should be call ONLY after all the sub modules (instances)
* have been added to the pb_module!
* Otherwise, some GPIO ports of the sub modules may be missed!
*******************************************************************/
void add_module_gpio_ports_from_child_modules(ModuleManager& module_manager,
const ModuleId& module_id) {
static
void add_module_io_ports_from_child_modules(ModuleManager& module_manager,
const ModuleId& module_id,
const ModuleManager::e_module_port_type& module_port_type) {
std::vector<BasicPort> gpio_ports_to_add;
/* Iterate over the child modules */
@ -945,7 +972,7 @@ void add_module_gpio_ports_from_child_modules(ModuleManager& module_manager,
/* Iterate over the child instances */
for (size_t i = 0; i < module_manager.num_instance(module_id, child); ++i) {
/* Find all the global ports, whose port type is special */
for (BasicPort gpio_port : module_manager.module_ports_by_type(child, ModuleManager::MODULE_GPIO_PORT)) {
for (BasicPort gpio_port : module_manager.module_ports_by_type(child, module_port_type)) {
/* If this port is not mergeable, we update the list */
bool is_mergeable = false;
for (BasicPort& gpio_port_to_add : gpio_ports_to_add) {
@ -973,7 +1000,7 @@ void add_module_gpio_ports_from_child_modules(ModuleManager& module_manager,
std::vector<ModulePortId> gpio_port_ids;
/* Add the gpio ports for the module */
for (const BasicPort& gpio_port_to_add : gpio_ports_to_add) {
ModulePortId port_id = module_manager.add_port(module_id, gpio_port_to_add, ModuleManager::MODULE_GPIO_PORT);
ModulePortId port_id = module_manager.add_port(module_id, gpio_port_to_add, module_port_type);
gpio_port_ids.push_back(port_id);
}
@ -984,7 +1011,7 @@ void add_module_gpio_ports_from_child_modules(ModuleManager& module_manager,
/* Iterate over the child instances */
for (const size_t& child_instance : module_manager.child_module_instances(module_id, child)) {
/* Find all the global ports, whose port type is special */
for (ModulePortId child_gpio_port_id : module_manager.module_port_ids_by_type(child, ModuleManager::MODULE_GPIO_PORT)) {
for (ModulePortId child_gpio_port_id : module_manager.module_port_ids_by_type(child, module_port_type)) {
BasicPort child_gpio_port = module_manager.module_port(child, child_gpio_port_id);
/* Find the port with the same name! */
for (size_t iport = 0; iport < gpio_ports_to_add.size(); ++iport) {
@ -995,8 +1022,22 @@ void add_module_gpio_ports_from_child_modules(ModuleManager& module_manager,
for (const size_t& pin_id : child_gpio_port.pins()) {
/* Reach here, it means this is the port we want, create a net and configure its source and sink */
ModuleNetId net = module_manager.create_module_net(module_id);
module_manager.add_module_net_source(module_id, net, module_id, 0, gpio_port_ids[iport], gpio_port_lsb[iport]);
module_manager.add_module_net_sink(module_id, net, child, child_instance, child_gpio_port_id, pin_id);
/* - For GPIO and GPIN ports
* the source of the net is the current module
* the sink of the net is the child module
* - For GPOUT ports
* the source of the net is the child module
* the sink of the net is the current module
*/
if ( (ModuleManager::MODULE_GPIO_PORT == module_port_type)
|| (ModuleManager::MODULE_GPIN_PORT == module_port_type) ) {
module_manager.add_module_net_source(module_id, net, module_id, 0, gpio_port_ids[iport], gpio_port_lsb[iport]);
module_manager.add_module_net_sink(module_id, net, child, child_instance, child_gpio_port_id, pin_id);
} else {
VTR_ASSERT(ModuleManager::MODULE_GPOUT_PORT == module_port_type);
module_manager.add_module_net_sink(module_id, net, module_id, 0, gpio_port_ids[iport], gpio_port_lsb[iport]);
module_manager.add_module_net_source(module_id, net, child, child_instance, child_gpio_port_id, pin_id);
}
/* Update the LSB counter */
gpio_port_lsb[iport]++;
}
@ -1014,6 +1055,27 @@ void add_module_gpio_ports_from_child_modules(ModuleManager& module_manager,
}
}
/********************************************************************
* Add GPIO ports to the module:
* In this function, the following tasks are done:
* 1. find all the GPIO ports from the child modules and build a list of it,
* 2. Merge all the GPIO ports with the same name
* 3. add the ports to the pb_module
* 4. add module nets to connect to the GPIO ports of each sub module
*
* Note: This function should be call ONLY after all the sub modules (instances)
* have been added to the pb_module!
* Otherwise, some GPIO ports of the sub modules may be missed!
*******************************************************************/
void add_module_gpio_ports_from_child_modules(ModuleManager& module_manager,
const ModuleId& module_id) {
add_module_io_ports_from_child_modules(module_manager, module_id, ModuleManager::MODULE_GPIO_PORT);
add_module_io_ports_from_child_modules(module_manager, module_id, ModuleManager::MODULE_GPIN_PORT);
add_module_io_ports_from_child_modules(module_manager, module_id, ModuleManager::MODULE_GPOUT_PORT);
}
/********************************************************************
* Add global ports to the module:
* In this function, the following tasks are done:

View File

@ -140,6 +140,41 @@ void add_grid_module_nets_connect_pb_type_ports(ModuleManager& module_manager,
}
}
/********************************************************************
* Add module nets between primitive module and its internal circuit module
* This is only applicable to the primitive module of a grid
*******************************************************************/
static
void add_primitive_module_fpga_global_io_port(ModuleManager& module_manager,
const ModuleId& primitive_module,
const ModuleId& logic_module,
const size_t& logic_instance_id,
const ModuleManager::e_module_port_type& module_io_port_type,
const CircuitLibrary& circuit_lib,
const CircuitModelId& primitive_model,
const CircuitPortId& circuit_port) {
BasicPort module_port(generate_fpga_global_io_port_name(std::string(gio_inout_prefix), circuit_lib, primitive_model, circuit_port), circuit_lib.port_size(circuit_port));
ModulePortId primitive_io_port_id = module_manager.add_port(primitive_module, module_port, module_io_port_type);
ModulePortId logic_io_port_id = module_manager.find_module_port(logic_module, circuit_lib.port_prefix(circuit_port));
BasicPort logic_io_port = module_manager.module_port(logic_module, logic_io_port_id);
VTR_ASSERT(logic_io_port.get_width() == module_port.get_width());
/* Wire the GPIO port form primitive_module to the logic module!*/
for (size_t pin_id = 0; pin_id < module_port.pins().size(); ++pin_id) {
ModuleNetId net = module_manager.create_module_net(primitive_module);
if ( (ModuleManager::MODULE_GPIO_PORT == module_io_port_type)
|| (ModuleManager::MODULE_GPIN_PORT == module_io_port_type) ) {
module_manager.add_module_net_source(primitive_module, net, primitive_module, 0, primitive_io_port_id, module_port.pins()[pin_id]);
module_manager.add_module_net_sink(primitive_module, net, logic_module, logic_instance_id, logic_io_port_id, logic_io_port.pins()[pin_id]);
} else {
VTR_ASSERT(ModuleManager::MODULE_GPOUT_PORT == module_io_port_type);
module_manager.add_module_net_source(primitive_module, net, logic_module, logic_instance_id, logic_io_port_id, logic_io_port.pins()[pin_id]);
module_manager.add_module_net_sink(primitive_module, net, primitive_module, 0, primitive_io_port_id, module_port.pins()[pin_id]);
}
}
}
/********************************************************************
* 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
@ -274,18 +309,32 @@ void build_primitive_block_module(ModuleManager& module_manager,
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);
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));
ModulePortId primitive_gpio_port_id = module_manager.add_port(primitive_module, module_port, ModuleManager::MODULE_GPIO_PORT);
ModulePortId logic_gpio_port_id = module_manager.find_module_port(logic_module, circuit_lib.port_prefix(port));
BasicPort logic_gpio_port = module_manager.module_port(logic_module, logic_gpio_port_id);
VTR_ASSERT(logic_gpio_port.get_width() == module_port.get_width());
add_primitive_module_fpga_global_io_port(module_manager, primitive_module,
logic_module, logic_instance_id,
ModuleManager::MODULE_GPIO_PORT,
circuit_lib,
primitive_model,
port);
}
}
/* Wire the GPIO port form primitive_module to the logic module!*/
for (size_t pin_id = 0; pin_id < module_port.pins().size(); ++pin_id) {
ModuleNetId net = module_manager.create_module_net(primitive_module);
module_manager.add_module_net_source(primitive_module, net, primitive_module, 0, primitive_gpio_port_id, module_port.pins()[pin_id]);
module_manager.add_module_net_sink(primitive_module, net, logic_module, logic_instance_id, logic_gpio_port_id, logic_gpio_port.pins()[pin_id]);
}
/* Find the other i/o ports required by the primitive node, and add them to the module */
for (const auto& port : circuit_lib.model_global_ports(primitive_model, false)) {
if ( (SPICE_MODEL_PORT_INPUT == circuit_lib.port_type(port))
&& (true == circuit_lib.port_is_io(port)) ) {
add_primitive_module_fpga_global_io_port(module_manager, primitive_module,
logic_module, logic_instance_id,
ModuleManager::MODULE_GPIN_PORT,
circuit_lib,
primitive_model,
port);
} else if (SPICE_MODEL_PORT_OUTPUT == circuit_lib.port_type(port)) {
add_primitive_module_fpga_global_io_port(module_manager, primitive_module,
logic_module, logic_instance_id,
ModuleManager::MODULE_GPOUT_PORT,
circuit_lib,
primitive_model,
port);
}
}
}

View File

@ -125,6 +125,8 @@ void print_verilog_module_definition(std::fstream& fp,
/* port type2type mapping */
std::map<ModuleManager::e_module_port_type, enum e_dump_verilog_port_type> port_type2type_map;
port_type2type_map[ModuleManager::MODULE_GLOBAL_PORT] = VERILOG_PORT_CONKT;
port_type2type_map[ModuleManager::MODULE_GPIN_PORT] = VERILOG_PORT_CONKT;
port_type2type_map[ModuleManager::MODULE_GPOUT_PORT] = VERILOG_PORT_CONKT;
port_type2type_map[ModuleManager::MODULE_GPIO_PORT] = VERILOG_PORT_CONKT;
port_type2type_map[ModuleManager::MODULE_INOUT_PORT] = VERILOG_PORT_CONKT;
port_type2type_map[ModuleManager::MODULE_INPUT_PORT] = VERILOG_PORT_CONKT;
@ -184,6 +186,8 @@ void print_verilog_module_ports(std::fstream& fp,
/* port type2type mapping */
std::map<ModuleManager::e_module_port_type, enum e_dump_verilog_port_type> port_type2type_map;
port_type2type_map[ModuleManager::MODULE_GLOBAL_PORT] = VERILOG_PORT_INPUT;
port_type2type_map[ModuleManager::MODULE_GPIN_PORT] = VERILOG_PORT_INPUT;
port_type2type_map[ModuleManager::MODULE_GPOUT_PORT] = VERILOG_PORT_OUTPUT;
port_type2type_map[ModuleManager::MODULE_GPIO_PORT] = VERILOG_PORT_INOUT;
port_type2type_map[ModuleManager::MODULE_INOUT_PORT] = VERILOG_PORT_INOUT;
port_type2type_map[ModuleManager::MODULE_INPUT_PORT] = VERILOG_PORT_INPUT;
@ -340,6 +344,8 @@ void print_verilog_module_instance(std::fstream& fp,
/* port type2type mapping */
std::map<ModuleManager::e_module_port_type, enum e_dump_verilog_port_type> port_type2type_map;
port_type2type_map[ModuleManager::MODULE_GLOBAL_PORT] = VERILOG_PORT_CONKT;
port_type2type_map[ModuleManager::MODULE_GPIN_PORT] = VERILOG_PORT_CONKT;
port_type2type_map[ModuleManager::MODULE_GPOUT_PORT] = VERILOG_PORT_CONKT;
port_type2type_map[ModuleManager::MODULE_GPIO_PORT] = VERILOG_PORT_CONKT;
port_type2type_map[ModuleManager::MODULE_INOUT_PORT] = VERILOG_PORT_CONKT;
port_type2type_map[ModuleManager::MODULE_INPUT_PORT] = VERILOG_PORT_CONKT;