diff --git a/vpr7_x2p/libarchfpga/SRC/device_port.cpp b/vpr7_x2p/libarchfpga/SRC/device_port.cpp index 38241f198..04ee4facf 100644 --- a/vpr7_x2p/libarchfpga/SRC/device_port.cpp +++ b/vpr7_x2p/libarchfpga/SRC/device_port.cpp @@ -1,6 +1,8 @@ +#include #include #include -#include + +#include "vtr_assert.h" #include "device_port.h" @@ -63,6 +65,24 @@ std::string BasicPort::get_name() const { return name_; } +/* Make a range of the pin indices */ +std::vector BasicPort::pins() const { + std::vector pin_indices; + + /* Return if the port is invalid */ + if (false == is_valid()) { + return pin_indices; /* Return an empty vector */ + } + /* For valid ports, create a vector whose length is the port width */ + pin_indices.resize(get_width()); + /* Fill in an incremental sequence */ + std::iota(pin_indices.begin(), pin_indices.end(), get_lsb()); + /* Ensure the last one is MSB */ + VTR_ASSERT(get_msb() == pin_indices.back()); + + return pin_indices; +} + /* Mutators */ /* copy */ void BasicPort::set(const BasicPort& basic_port) { @@ -188,7 +208,7 @@ void BasicPort::reset() { void BasicPort::combine(const BasicPort& port) { /* LSB follows the current LSB */ /* MSB increases */ - assert( 0 < port.get_width() ); /* Make sure port is valid */ + VTR_ASSERT(0 < port.get_width() ); /* Make sure port is valid */ /* If current port is invalid, we do not combine */ if (0 == get_width()) { return; diff --git a/vpr7_x2p/libarchfpga/SRC/device_port.h b/vpr7_x2p/libarchfpga/SRC/device_port.h index 21666dcb4..eb4a91b86 100644 --- a/vpr7_x2p/libarchfpga/SRC/device_port.h +++ b/vpr7_x2p/libarchfpga/SRC/device_port.h @@ -6,6 +6,7 @@ #define DEVICE_PORT_H #include +#include /* A basic port */ class BasicPort { @@ -22,6 +23,7 @@ class BasicPort { size_t get_lsb() const; /* get the LSB */ std::string get_name() const; /* get the name */ bool is_valid() const; /* check if port size is valid > 0 */ + std::vector pins() const; /* Make a range of the pin indices */ public: /* Mutators */ void set(const BasicPort& basic_port); /* copy */ void set_name(const std::string& name); /* set the port LSB and MSB */ diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager.cpp b/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager.cpp index f7e7b1e6c..41a5f723e 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager.cpp +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager.cpp @@ -56,6 +56,20 @@ std::vector ModuleManager::child_module_instances(const ModuleId& parent return instance_range; } +/* Find the source ids of modules */ +ModuleManager::module_net_src_range ModuleManager::module_net_sources(const ModuleId& module, const ModuleNetId& net) const { + /* Validate the module_id */ + VTR_ASSERT(valid_module_net_id(module, net)); + return vtr::make_range(net_src_ids_[module][net].begin(), net_src_ids_[module][net].end()); +} + +/* Find the sink ids of modules */ +ModuleManager::module_net_sink_range ModuleManager::module_net_sinks(const ModuleId& module, const ModuleNetId& net) const { + /* Validate the module_id */ + VTR_ASSERT(valid_module_net_id(module, net)); + return vtr::make_range(net_sink_ids_[module][net].begin(), net_sink_ids_[module][net].end()); +} + /****************************************************************************** * Public Accessors ******************************************************************************/ @@ -101,6 +115,24 @@ std::vector ModuleManager::module_ports_by_type(const ModuleId& modul return ports; } +/* Find a list of port ids of a module by a given types */ +std::vector ModuleManager::module_port_ids_by_type(const ModuleId& module_id, const enum e_module_port_type& port_type) const { + /* Validate the module_id */ + VTR_ASSERT(valid_module_id(module_id)); + + std::vector port_ids; + for (const auto& port : port_ids_[module_id]) { + /* Skip unmatched ports */ + if (port_type != port_types_[module_id][port]) { + continue; + } + port_ids.push_back(port_ids_[module_id][port]); + } + + return port_ids; +} + + /* Find a port of a module by a given name */ ModulePortId ModuleManager::find_module_port(const ModuleId& module_id, const std::string& port_name) const { /* Validate the module id */ @@ -207,7 +239,7 @@ std::string ModuleManager::net_name(const ModuleId& module, const ModuleNetId& n } /* Find the source modules of a net */ -std::vector ModuleManager::net_source_modules(const ModuleId& module, const ModuleNetId& net) const { +vtr::vector ModuleManager::net_source_modules(const ModuleId& module, const ModuleNetId& net) const { /* Validate module net */ VTR_ASSERT(valid_module_net_id(module, net)); @@ -215,7 +247,7 @@ std::vector ModuleManager::net_source_modules(const ModuleId& module, } /* Find the ids of source instances of a net */ -std::vector ModuleManager::net_source_instances(const ModuleId& module, const ModuleNetId& net) const { +vtr::vector ModuleManager::net_source_instances(const ModuleId& module, const ModuleNetId& net) const { /* Validate module net */ VTR_ASSERT(valid_module_net_id(module, net)); @@ -223,7 +255,7 @@ std::vector ModuleManager::net_source_instances(const ModuleId& module, } /* Find the source ports of a net */ -std::vector ModuleManager::net_source_ports(const ModuleId& module, const ModuleNetId& net) const { +vtr::vector ModuleManager::net_source_ports(const ModuleId& module, const ModuleNetId& net) const { /* Validate module net */ VTR_ASSERT(valid_module_net_id(module, net)); @@ -231,7 +263,7 @@ std::vector ModuleManager::net_source_ports(const ModuleId& module } /* Find the source pin indices of a net */ -std::vector ModuleManager::net_source_pins(const ModuleId& module, const ModuleNetId& net) const { +vtr::vector ModuleManager::net_source_pins(const ModuleId& module, const ModuleNetId& net) const { /* Validate module net */ VTR_ASSERT(valid_module_net_id(module, net)); @@ -239,7 +271,7 @@ std::vector ModuleManager::net_source_pins(const ModuleId& module, const } /* Find the sink modules of a net */ -std::vector ModuleManager::net_sink_modules(const ModuleId& module, const ModuleNetId& net) const { +vtr::vector ModuleManager::net_sink_modules(const ModuleId& module, const ModuleNetId& net) const { /* Validate module net */ VTR_ASSERT(valid_module_net_id(module, net)); @@ -247,7 +279,7 @@ std::vector ModuleManager::net_sink_modules(const ModuleId& module, co } /* Find the ids of sink instances of a net */ -std::vector ModuleManager::net_sink_instances(const ModuleId& module, const ModuleNetId& net) const { +vtr::vector ModuleManager::net_sink_instances(const ModuleId& module, const ModuleNetId& net) const { /* Validate module net */ VTR_ASSERT(valid_module_net_id(module, net)); @@ -255,7 +287,7 @@ std::vector ModuleManager::net_sink_instances(const ModuleId& module, co } /* Find the sink ports of a net */ -std::vector ModuleManager::net_sink_ports(const ModuleId& module, const ModuleNetId& net) const { +vtr::vector ModuleManager::net_sink_ports(const ModuleId& module, const ModuleNetId& net) const { /* Validate module net */ VTR_ASSERT(valid_module_net_id(module, net)); @@ -263,7 +295,7 @@ std::vector ModuleManager::net_sink_ports(const ModuleId& module, } /* Find the sink pin indices of a net */ -std::vector ModuleManager::net_sink_pins(const ModuleId& module, const ModuleNetId& net) const { +vtr::vector ModuleManager::net_sink_pins(const ModuleId& module, const ModuleNetId& net) const { /* Validate module net */ VTR_ASSERT(valid_module_net_id(module, net)); @@ -300,11 +332,13 @@ ModuleId ModuleManager::add_module(const std::string& name) { net_ids_.emplace_back(); net_names_.emplace_back(); + net_src_ids_.emplace_back(); net_src_module_ids_.emplace_back(); net_src_instance_ids_.emplace_back(); net_src_port_ids_.emplace_back(); net_src_pin_ids_.emplace_back(); + net_sink_ids_.emplace_back(); net_sink_module_ids_.emplace_back(); net_sink_instance_ids_.emplace_back(); net_sink_port_ids_.emplace_back(); @@ -426,11 +460,13 @@ ModuleNetId ModuleManager::create_module_net(const ModuleId& module) { /* Allocate net-related data structures */ net_names_[module].emplace_back(); + net_src_ids_[module].emplace_back(); net_src_module_ids_[module].emplace_back(); net_src_instance_ids_[module].emplace_back(); net_src_port_ids_[module].emplace_back(); net_src_pin_ids_[module].emplace_back(); + net_sink_ids_[module].emplace_back(); net_sink_module_ids_[module].emplace_back(); net_sink_instance_ids_[module].emplace_back(); net_sink_port_ids_[module].emplace_back(); @@ -449,12 +485,16 @@ void ModuleManager::set_net_name(const ModuleId& module, const ModuleNetId& net, } /* Add a source to a net in the connection graph */ -void ModuleManager::add_module_net_source(const ModuleId& module, const ModuleNetId& net, - const ModuleId& src_module, const size_t& instance_id, - const ModulePortId& src_port, const size_t& src_pin) { +ModuleNetSrcId ModuleManager::add_module_net_source(const ModuleId& module, const ModuleNetId& net, + const ModuleId& src_module, const size_t& instance_id, + const ModulePortId& src_port, const size_t& src_pin) { /* Validate the module and net id */ VTR_ASSERT(valid_module_net_id(module, net)); + /* Create a new id for src node */ + ModuleNetSrcId net_src = ModuleNetSrcId(net_src_ids_[module][net].size()); + net_src_ids_[module][net].push_back(net_src); + /* Validate the source module */ VTR_ASSERT(valid_module_id(src_module)); net_src_module_ids_[module][net].push_back(src_module); @@ -480,15 +520,21 @@ void ModuleManager::add_module_net_source(const ModuleId& module, const ModuleNe /* Update fast look-up for nets */ net_lookup_[module][src_module][src_instance_id][src_port][src_pin] = net; + + return net_src; } /* Add a sink to a net in the connection graph */ -void ModuleManager::add_module_net_sink(const ModuleId& module, const ModuleNetId& net, - const ModuleId& sink_module, const size_t& instance_id, - const ModulePortId& sink_port, const size_t& sink_pin) { +ModuleNetSinkId ModuleManager::add_module_net_sink(const ModuleId& module, const ModuleNetId& net, + const ModuleId& sink_module, const size_t& instance_id, + const ModulePortId& sink_port, const size_t& sink_pin) { /* Validate the module and net id */ VTR_ASSERT(valid_module_net_id(module, net)); + /* Create a new id for sink node */ + ModuleNetSinkId net_sink = ModuleNetSinkId(net_sink_ids_[module][net].size()); + net_sink_ids_[module][net].push_back(net_sink); + /* Validate the source module */ VTR_ASSERT(valid_module_id(sink_module)); net_sink_module_ids_[module][net].push_back(sink_module); @@ -514,6 +560,8 @@ void ModuleManager::add_module_net_sink(const ModuleId& module, const ModuleNetI /* Update fast look-up for nets */ net_lookup_[module][sink_module][sink_instance_id][sink_port][sink_pin] = net; + + return net_sink; } /****************************************************************************** diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager.h b/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager.h index 5204f0de3..6bba3a67a 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager.h +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager.h @@ -38,9 +38,13 @@ class ModuleManager { public: /* Types and ranges */ typedef vtr::vector::const_iterator module_iterator; typedef vtr::vector::const_iterator module_net_iterator; + typedef vtr::vector::const_iterator module_net_src_iterator; + typedef vtr::vector::const_iterator module_net_sink_iterator; typedef vtr::Range module_range; typedef vtr::Range module_net_range; + typedef vtr::Range module_net_src_range; + typedef vtr::Range module_net_sink_range; public: /* Public aggregators */ /* Find all the modules */ @@ -51,6 +55,10 @@ class ModuleManager { std::vector child_modules(const ModuleId& parent_module) const; /* Find all the instances under a parent module */ std::vector child_module_instances(const ModuleId& parent_module, const ModuleId& child_module) const; + /* Find the source ids of modules */ + module_net_src_range module_net_sources(const ModuleId& module, const ModuleNetId& net) const; + /* Find the sink ids of modules */ + module_net_sink_range module_net_sinks(const ModuleId& module, const ModuleNetId& net) const; public: /* Public accessors */ size_t num_modules() const; @@ -58,6 +66,7 @@ class ModuleManager { std::string module_name(const ModuleId& module_id) const; std::string module_port_type_str(const enum e_module_port_type& port_type) const; std::vector module_ports_by_type(const ModuleId& module_id, const enum e_module_port_type& port_type) const; + std::vector module_port_ids_by_type(const ModuleId& module_id, const enum e_module_port_type& port_type) const; /* Find a port of a module by a given name */ ModulePortId find_module_port(const ModuleId& module_id, const std::string& port_name) const; /* Find the Port information with a given port id */ @@ -79,21 +88,22 @@ class ModuleManager { /* Find the name of net */ std::string net_name(const ModuleId& module, const ModuleNetId& net) const; /* Find the source modules of a net */ - std::vector net_source_modules(const ModuleId& module, const ModuleNetId& net) const; + vtr::vector net_source_modules(const ModuleId& module, const ModuleNetId& net) const; /* Find the ids of source instances of a net */ - std::vector net_source_instances(const ModuleId& module, const ModuleNetId& net) const; + vtr::vector net_source_instances(const ModuleId& module, const ModuleNetId& net) const; /* Find the source ports of a net */ - std::vector net_source_ports(const ModuleId& module, const ModuleNetId& net) const; + vtr::vector net_source_ports(const ModuleId& module, const ModuleNetId& net) const; /* Find the source pin indices of a net */ - std::vector net_source_pins(const ModuleId& module, const ModuleNetId& net) const; + vtr::vector net_source_pins(const ModuleId& module, const ModuleNetId& net) const; + /* Find the sink modules of a net */ - std::vector net_sink_modules(const ModuleId& module, const ModuleNetId& net) const; + vtr::vector net_sink_modules(const ModuleId& module, const ModuleNetId& net) const; /* Find the ids of sink instances of a net */ - std::vector net_sink_instances(const ModuleId& module, const ModuleNetId& net) const; + vtr::vector net_sink_instances(const ModuleId& module, const ModuleNetId& net) const; /* Find the sink ports of a net */ - std::vector net_sink_ports(const ModuleId& module, const ModuleNetId& net) const; + vtr::vector net_sink_ports(const ModuleId& module, const ModuleNetId& net) const; /* Find the sink pin indices of a net */ - std::vector net_sink_pins(const ModuleId& module, const ModuleNetId& net) const; + vtr::vector net_sink_pins(const ModuleId& module, const ModuleNetId& net) const; public: /* Public mutators */ /* Add a module */ ModuleId add_module(const std::string& name); @@ -116,13 +126,13 @@ class ModuleManager { void set_net_name(const ModuleId& module, const ModuleNetId& net, const std::string& name); /* Add a source to a net in the connection graph */ - void add_module_net_source(const ModuleId& module, const ModuleNetId& net, - const ModuleId& src_module, const size_t& instance_id, - const ModulePortId& src_port, const size_t& src_pin); + ModuleNetSrcId add_module_net_source(const ModuleId& module, const ModuleNetId& net, + const ModuleId& src_module, const size_t& instance_id, + const ModulePortId& src_port, const size_t& src_pin); /* Add a sink to a net in the connection graph */ - void add_module_net_sink(const ModuleId& module, const ModuleNetId& net, - const ModuleId& sink_module, const size_t& instance_id, - const ModulePortId& sink_port, const size_t& sink_pin); + ModuleNetSinkId add_module_net_sink(const ModuleId& module, const ModuleNetId& net, + const ModuleId& sink_module, const size_t& instance_id, + const ModulePortId& sink_port, const size_t& sink_pin); public: /* Public validators/invalidators */ bool valid_module_id(const ModuleId& module) const; bool valid_module_port_id(const ModuleId& module, const ModulePortId& port) const; @@ -154,14 +164,19 @@ class ModuleManager { */ vtr::vector> net_ids_; /* List of nets for each Module */ vtr::vector> net_names_; /* Name of net */ - vtr::vector>> net_src_module_ids_; /* Pin ids that drive the net */ - vtr::vector>> net_src_instance_ids_; /* Pin ids that drive the net */ - vtr::vector>> net_src_port_ids_; /* Pin ids that drive the net */ - vtr::vector>> net_src_pin_ids_; /* Pin ids that drive the net */ - vtr::vector>> net_sink_module_ids_; /* Pin ids that the net drives */ - vtr::vector>> net_sink_instance_ids_; /* Pin ids that drive the net */ - vtr::vector>> net_sink_port_ids_; /* Pin ids that drive the net */ - vtr::vector>> net_sink_pin_ids_; /* Pin ids that drive the net */ + + vtr::vector>> net_src_ids_; /* Unique id of the source that drive the net */ + vtr::vector>> net_src_module_ids_; /* Pin ids that drive the net */ + vtr::vector>> net_src_instance_ids_; /* Pin ids that drive the net */ + vtr::vector>> net_src_port_ids_; /* Pin ids that drive the net */ + vtr::vector>> net_src_pin_ids_; /* Pin ids that drive the net */ + + + vtr::vector>> net_sink_ids_; /* Unique ids of the sink that the net drives */ + vtr::vector>> net_sink_module_ids_; /* Pin ids that the net drives */ + vtr::vector>> net_sink_instance_ids_; /* Pin ids that drive the net */ + vtr::vector>> net_sink_port_ids_; /* Pin ids that drive the net */ + vtr::vector>> net_sink_pin_ids_; /* Pin ids that drive the net */ /* fast look-up for module */ std::map name_id_map_; diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager_fwd.h b/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager_fwd.h index 37509ebac..bffc2df6a 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager_fwd.h +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager_fwd.h @@ -13,11 +13,15 @@ struct module_id_tag; struct module_port_id_tag; struct module_pin_id_tag; struct module_net_id_tag; +struct module_net_src_id_tag; +struct module_net_sink_id_tag; typedef vtr::StrongId ModuleId; typedef vtr::StrongId ModulePortId; typedef vtr::StrongId ModulePinId; typedef vtr::StrongId ModuleNetId; +typedef vtr::StrongId ModuleNetSrcId; +typedef vtr::StrongId ModuleNetSinkId; class ModuleManager; 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 9f744bd24..f24683bba 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 @@ -260,3 +260,31 @@ void add_pb_type_ports_to_module_manager(ModuleManager& module_manager, } } +/******************************************************************** + * Identify if a net is a local wire inside a module: + * A net is a local wire if it connects between two instances, + * It means that any of its source and sink modules should not include current module_id + *******************************************************************/ +bool module_net_is_local_wire(const ModuleManager& module_manager, + const ModuleId& module_id, const ModuleNetId& module_net) { + /* A flag to identify local wire */ + /* Check all the sink modules of the net, + * if we have a source module is the current module, this is not local wire + */ + for (ModuleId src_module : module_manager.net_source_modules(module_id, module_net)) { + if (module_id == src_module) { + /* Here, this is not a local wire */ + return false; + } + } + + /* Check all the sink modules of the net */ + for (ModuleId sink_module : module_manager.net_sink_modules(module_id, module_net)) { + if (module_id == sink_module) { + /* Here, this is not a local wire */ + return false; + } + } + + return true; +} 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 cbdc04891..ce86a1f55 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 @@ -43,5 +43,7 @@ void add_pb_type_ports_to_module_manager(ModuleManager& module_manager, const ModuleId& module_id, t_pb_type* cur_pb_type); -#endif +bool module_net_is_local_wire(const ModuleManager& module_manager, + const ModuleId& module_id, const ModuleNetId& module_net); +#endif diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_module_writer.cpp b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_module_writer.cpp index c54d73619..7d8256744 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_module_writer.cpp +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_module_writer.cpp @@ -9,49 +9,192 @@ *******************************************************************/ #include "vtr_assert.h" #include "fpga_x2p_utils.h" +#include "module_manager_utils.h" #include "verilog_writer_utils.h" #include "verilog_module_writer.h" /******************************************************************** - * Collect all the nets that are going to be local wires + * Name a net for a local wire for a verilog module + * 1. If this is a local wire, name it after the __ + * 2. If this is not a local wire, name it after the port name of parent module + * + * In addition, it will assign the pin index as well + * + * Restriction: this function requires each net has single driver + * which is definitely always true in circuits. + *******************************************************************/ +static +BasicPort generate_verilog_port_for_module_net(const ModuleManager& module_manager, + const ModuleId& module_id, + const ModuleNetId& module_net) { + /* Check all the sink modules of the net, + * if we have a source module is the current module, this is not local wire + */ + for (ModuleNetSrcId src_id : module_manager.module_net_sources(module_id, module_net)) { + if (module_id == module_manager.net_source_modules(module_id, module_net)[src_id]) { + /* Here, this is not a local wire, return the port name of the src_port */ + ModulePortId net_src_port = module_manager.net_source_ports(module_id, module_net)[src_id]; + size_t src_pin_index = module_manager.net_source_pins(module_id, module_net)[src_id]; + return BasicPort(module_manager.module_port(module_id, net_src_port).get_name(), src_pin_index, src_pin_index); + } + } + + /* Check all the sink modules of the net */ + for (ModuleNetSinkId sink_id : module_manager.module_net_sinks(module_id, module_net)) { + if (module_id == module_manager.net_sink_modules(module_id, module_net)[sink_id]) { + /* Here, this is not a local wire, return the port name of the sink_port */ + ModulePortId net_sink_port = module_manager.net_sink_ports(module_id, module_net)[sink_id]; + size_t sink_pin_index = module_manager.net_sink_pins(module_id, module_net)[sink_id]; + return BasicPort(module_manager.module_port(module_id, net_sink_port).get_name(), sink_pin_index, sink_pin_index); + } + } + + /* Reach here, this is a local wire */ + std::string net_name; + + /* Each net must only one 1 source */ + VTR_ASSERT(1 == module_manager.net_source_modules(module_id, module_net).size()); + + /* Get the source module */ + ModuleId net_src_module = module_manager.net_source_modules(module_id, module_net)[ModuleNetSrcId(0)]; + /* Get the instance id */ + size_t net_src_instance = module_manager.net_source_instances(module_id, module_net)[ModuleNetSrcId(0)]; + /* Get the port id */ + ModulePortId net_src_port = module_manager.net_source_ports(module_id, module_net)[ModuleNetSrcId(0)]; + /* Get the pin id */ + size_t net_src_pin = module_manager.net_source_pins(module_id, module_net)[ModuleNetSrcId(0)]; + + net_name = module_manager.module_name(net_src_module); + net_name += std::string("_") + std::to_string(net_src_instance) + std::string("_"); + net_name += module_manager.module_port(module_id, net_src_port).get_name(); + + return BasicPort(net_name, net_src_pin, net_src_pin); +} + +/******************************************************************** + * Find all the nets that are going to be local wires * And organize it in a vector of ports * Verilog wire writter function will use the output of this function * to write up local wire declaration in Verilog format - * - * Here is the strategy to identify local wires: - * Iterate over the nets inside the module. - * A net is a local wire if it connects between two instances, - * This is valid when all the sinks of the net are pins/ports of instances *******************************************************************/ static std::vector find_verilog_module_local_wires(const ModuleManager& module_manager, const ModuleId& module_id) { - std::vector local_wire_ports; - - /* Find local wires between instances */ + std::vector local_wires; + + /* Local wires come from the child modules */ for (ModuleNetId module_net : module_manager.module_nets(module_id)) { - /* A flag to identify local wire */ - bool is_local_wire = false; - - /* Each net must only one 1 source */ - VTR_ASSERT(1 == module_manager.net_source_modules(module_id, module_net).size()); - - /* Check if source module is the module itself */ - if (module_id != module_manager.net_source_modules(module_id, module_net)[0]) { - is_local_wire = true; + /* We only care local wires */ + if (false == module_net_is_local_wire(module_manager, module_id, module_net)) { + continue; } - - /* Check all the sink modules of the net */ - for (ModuleId sink_module : module_manager.net_sink_modules(module_id, module_net)) { - if (module_id == sink_module) { - is_local_wire = false; - } + /* Find the name for this local wire */ + BasicPort local_wire_candidate = generate_verilog_port_for_module_net(module_manager, module_id, module_net); + /* Try to find a port in the list that can absorb the current local wire */ + bool merged = false; + for (BasicPort& local_wire : local_wires) { + /* check if the candidate can be combined to an existing local wire */ + if (true == two_verilog_ports_mergeable(local_wire, local_wire_candidate)) { + /* Merge the ports */ + local_wire = merge_two_verilog_ports(local_wire, local_wire_candidate); + merged = true; + break; + } + } + /* If not merged, push the port to the list */ + if (false == merged) { + local_wires.push_back(local_wire_candidate); } - - /* TODO: Push the Verilog port the list, try to combine the ports if we can */ } - return local_wire_ports; + return local_wires; +} + +/******************************************************************** + * Write a Verilog instance to a file + * This function will name the input and output connections to + * the inputs/output or local wires available in the parent module + * + * Parent_module + * +-----------------------------+ + * | | + * | +--------------+ | + * | | | | + * | | child_module | | + * | | [instance] | | + * | +--------------+ | + * | | + * +-----------------------------+ + * + *******************************************************************/ +static +void write_verilog_instance_to_file(std::fstream& fp, + const ModuleManager& module_manager, + const ModuleId& parent_module, + const ModuleId& child_module, + const size_t& instance_id, + const bool& use_explicit_port_map) { + /* Ensure a valid file stream */ + check_file_handler(fp); + + /* Print module name */ + fp << "\t" << module_manager.module_name(child_module) << " "; + /* Print instance name, _ */ + fp << module_manager.module_name(child_module) << "_" << module_manager.num_instance(parent_module, child_module) << "_" << " (" << std::endl; + + /* Print each port with/without explicit port map */ + /* port type2type mapping */ + std::map port_type2type_map; + port_type2type_map[ModuleManager::MODULE_GLOBAL_PORT] = VERILOG_PORT_CONKT; + port_type2type_map[ModuleManager::MODULE_INOUT_PORT] = VERILOG_PORT_CONKT; + port_type2type_map[ModuleManager::MODULE_INPUT_PORT] = VERILOG_PORT_CONKT; + port_type2type_map[ModuleManager::MODULE_OUTPUT_PORT] = VERILOG_PORT_CONKT; + port_type2type_map[ModuleManager::MODULE_CLOCK_PORT] = VERILOG_PORT_CONKT; + + /* Port sequence: global, inout, input, output and clock ports, */ + size_t port_cnt = 0; + for (const auto& kv : port_type2type_map) { + for (const ModulePortId& child_port_id : module_manager.module_port_ids_by_type(child_module, kv.first)) { + BasicPort child_port = module_manager.module_port(child_module, child_port_id); + if (0 != port_cnt) { + /* Do not dump a comma for the first port */ + fp << "," << std::endl; + } + /* Print port */ + fp << "\t\t"; + /* if explicit port map is required, output the port name */ + if (true == use_explicit_port_map) { + fp << "." << child_port.get_name() << "("; + } + + /* Create the port name and width to be used by the instance */ + std::vector instance_ports; + for (size_t child_pin : child_port.pins()) { + /* Find the net linked to the pin */ + ModuleNetId net = module_manager.module_instance_port_net(parent_module, child_module, instance_id, + child_port_id, child_pin); + /* Find the name for this child port */ + BasicPort instance_port = generate_verilog_port_for_module_net(module_manager, parent_module, net); + /* Create the port information for the net */ + instance_ports.push_back(instance_port); + } + /* Try to merge the ports */ + std::vector merged_ports = combine_verilog_ports(instance_ports); + + /* Print a verilog port by combining the instance ports */ + fp << generate_verilog_ports(merged_ports); + + /* if explicit port map is required, output the pair of branket */ + if (true == use_explicit_port_map) { + fp << ")"; + } + port_cnt++; + } + } + + /* Print an end to the instance */ + fp << ");" << std::endl; + } /******************************************************************** @@ -59,27 +202,46 @@ std::vector find_verilog_module_local_wires(const ModuleManager& modu * This is a key function, maybe most frequently called in our Verilog writer * Note that file stream must be valid *******************************************************************/ -void writer_verilog_module_to_file(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& module_id) { - /* Ensure a valid file stream */ - check_file_handler(fp); - +void write_verilog_module_to_file(std::fstream& fp, + const ModuleManager& module_manager, + const ModuleId& module_id, + const bool& use_explicit_port_map) { /* Ensure we have a valid module_id */ VTR_ASSERT(module_manager.valid_module_id(module_id)); /* Print module declaration */ print_verilog_module_declaration(fp, module_manager, module_id); + + /* Print an empty line as splitter */ + fp << std::endl; /* TODO: Print internal wires */ + std::vector local_wires = find_verilog_module_local_wires(module_manager, module_id); + for (BasicPort local_wire : local_wires) { + fp << generate_verilog_port(VERILOG_PORT_WIRE, local_wire) << ";" << std::endl; + } - /* TODO: Print instances */ + /* Print an empty line as splitter */ + fp << std::endl; + + /* TODO: Print local connection (from module inputs to output! */ + + /* Print an empty line as splitter */ + fp << std::endl; + + /* Print instances */ for (ModuleId child_module : module_manager.child_modules(module_id)) { for (size_t instance : module_manager.child_module_instances(module_id, child_module)) { /* Print an instance */ + write_verilog_instance_to_file(fp, module_manager, module_id, child_module, instance, use_explicit_port_map); + /* Print an empty line as splitter */ + fp << std::endl; } } /* Print an end for the module */ print_verilog_module_end(fp, module_manager.module_name(module_id)); + + /* Print an empty line as splitter */ + fp << std::endl; } diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_module_writer.h b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_module_writer.h index bb7b401fb..0846384b7 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_module_writer.h +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_module_writer.h @@ -8,8 +8,9 @@ #include #include "module_manager.h" -void writer_verilog_module_to_file(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& module_id); +void write_verilog_module_to_file(std::fstream& fp, + const ModuleManager& module_manager, + const ModuleId& module_id, + const bool& use_explicit_port_map); #endif diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_writer_utils.cpp b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_writer_utils.cpp index d582c59bd..0341ef0a9 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_writer_utils.cpp +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_writer_utils.cpp @@ -406,6 +406,37 @@ std::string generate_verilog_port(const enum e_dump_verilog_port_type& verilog_p return verilog_line; } +/******************************************************************** + * Evaluate if two Verilog ports can be merged: + * If the port name is same, it can merged + *******************************************************************/ +bool two_verilog_ports_mergeable(const BasicPort& portA, + const BasicPort& portB) { + if (0 == portA.get_name().compare(portB.get_name())) { + return true; + } + return false; +} + +/******************************************************************** + * Merge two Verilog ports, return the merged port + * The ports should have the same name + * The new LSB will be minimum of the LSBs of the two ports + * The new MSB will the maximum of the MSBs of the two ports + *******************************************************************/ +BasicPort merge_two_verilog_ports(const BasicPort& portA, + const BasicPort& portB) { + BasicPort merged_port; + + VTR_ASSERT(true == two_verilog_ports_mergeable(portA, portB)); + + merged_port.set_name(portA.get_name()); + merged_port.set_lsb((size_t)std::min((int)portA.get_lsb(), (int)portB.get_lsb())); + merged_port.set_msb((size_t)std::max((int)portA.get_msb(), (int)portB.get_msb())); + + return merged_port; +} + /************************************************ * This function takes a list of ports and * combine the port string by comparing the name diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_writer_utils.h b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_writer_utils.h index 1840f447f..f06e72baf 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_writer_utils.h +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_writer_utils.h @@ -53,6 +53,12 @@ void print_verilog_module_end(std::fstream& fp, std::string generate_verilog_port(const enum e_dump_verilog_port_type& dump_port_type, const BasicPort& port_info); +bool two_verilog_ports_mergeable(const BasicPort& portA, + const BasicPort& portB); + +BasicPort merge_two_verilog_ports(const BasicPort& portA, + const BasicPort& portB); + std::vector combine_verilog_ports(const std::vector& ports); std::string generate_verilog_ports(const std::vector& merged_ports);