diff --git a/openfpga/src/base/annotate_pb_types.cpp b/openfpga/src/base/annotate_pb_types.cpp index dc1618d6e..783447cfb 100644 --- a/openfpga/src/base/annotate_pb_types.cpp +++ b/openfpga/src/base/annotate_pb_types.cpp @@ -584,6 +584,69 @@ void check_vpr_physical_pb_type_annotation(const DeviceContext& vpr_device_ctx, } } +/******************************************************************** + * This function aims to link all the ports defined under a physical + * pb_type to the ports of circuit model in the circuit library + * The binding assumes that pb_type port should be defined with the same name + * as the circuit port + *******************************************************************/ +static +bool link_physical_pb_port_to_circuit_port(t_pb_type* physical_pb_type, + const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model, + VprPbTypeAnnotation& vpr_pb_type_annotation) { + bool link_success = true; + /* Iterate over the pb_ports + * Note: + * - Not every port defined in the circuit model will appear under the pb_type + * Some circuit ports are just for physical implementation + */ + for (t_port* pb_port : pb_type_ports(physical_pb_type)) { + CircuitPortId circuit_port = circuit_lib.model_port(circuit_model, std::string(pb_port->name)); + + /* If we cannot find a port with the same name, error out */ + if (CircuitPortId::INVALID() == circuit_port) { + VTR_LOG_ERROR("Pb type port '%s' is not found in any port of circuit model '%s'!\n", + pb_port->name, circuit_lib.model_name(circuit_model).c_str()); + link_success = false; + continue; + } + + /* If the port width does not match, error out */ + if ((size_t)(pb_port->num_pins) != circuit_lib.port_size(circuit_port)) { + VTR_LOG_ERROR("Pb type port '%s[%d:%d]' does not match the port '%s[%d:%d]' of circuit model '%s' in size!\n", + pb_port->name, + 0, pb_port->num_pins - 1, + circuit_lib.port_prefix(circuit_port).c_str(), + 0, circuit_lib.port_size(circuit_port) - 1, + circuit_lib.model_name(circuit_model).c_str()); + link_success = false; + continue; + } + + /* If the port type does not match, error out */ + if (ERR_PORT == circuit_port_require_pb_port_type(circuit_lib.port_type(circuit_port))) { + VTR_LOG_ERROR("Pb type port '%s' type does not match the port type '%s' of circuit model '%s'!\n", + pb_port->name, + circuit_lib.port_prefix(circuit_port).c_str(), + circuit_lib.model_name(circuit_model).c_str()); + + link_success = false; + continue; + } + + /* Reach here, it means that mapping should be ok, update the vpr_pb_type_annotation */ + vpr_pb_type_annotation.add_pb_circuit_port(pb_port, circuit_port); + VTR_LOG("Bind pb type '%s' port '%s' to circuit model '%s' port '%s'\n", + physical_pb_type->name, + pb_port->name, + circuit_lib.model_name(circuit_model).c_str(), + circuit_lib.port_prefix(circuit_port).c_str()); + } + + return link_success; +} + /******************************************************************** * This function aims to link a physical pb_type to a valid circuit model * in the circuit library @@ -613,7 +676,10 @@ bool link_physical_pb_type_to_circuit_model(t_pb_type* physical_pb_type, return false; } - /* TODO: Ensure that the pb_type ports can be matched in the circuit model ports */ + /* Ensure that the pb_type ports can be matched in the circuit model ports */ + if (false == link_physical_pb_port_to_circuit_port(physical_pb_type, circuit_lib, circuit_model_id, vpr_pb_type_annotation)) { + return false; + } /* Now the circuit model is valid, update the vpr_pb_type_annotation */ vpr_pb_type_annotation.add_pb_type_circuit_model(physical_pb_type, circuit_model_id); diff --git a/openfpga/src/base/pb_type_utils.cpp b/openfpga/src/base/pb_type_utils.cpp index 090661b50..b791485a2 100644 --- a/openfpga/src/base/pb_type_utils.cpp +++ b/openfpga/src/base/pb_type_utils.cpp @@ -228,4 +228,30 @@ e_circuit_model_type pb_interconnect_require_circuit_model_type(const e_intercon return type_mapping.at(pb_interc_type); } +/******************************************************************** + * This function aims to find the required type for a pb_port + * when it is linked to a port of a circuit model + * We start from the view of a circuit port here. + * This is due to circuit port has more types than a pb_type port + * as it is designed for physical implementation + * As such, a few types of circuit port may be directed the same type of pb_type port + * This is done to make the mapping much simpler than doing in the opposite direction + *******************************************************************/ +enum PORTS circuit_port_require_pb_port_type(const e_circuit_model_port_type& circuit_port_type) { + std::map type_mapping; + + /* These circuit model ports may be founed in the pb_type ports */ + type_mapping[CIRCUIT_MODEL_PORT_INPUT] = IN_PORT; + type_mapping[CIRCUIT_MODEL_PORT_OUTPUT] = OUT_PORT; + type_mapping[CIRCUIT_MODEL_PORT_INOUT] = INOUT_PORT; + type_mapping[CIRCUIT_MODEL_PORT_CLOCK] = IN_PORT; + + /* Other circuit model ports should not be found when mapping to the pb_type ports */ + if (type_mapping.end() == type_mapping.find(circuit_port_type)) { + return ERR_PORT; + } + + return type_mapping.at(circuit_port_type); +} + } /* end namespace openfpga */ diff --git a/openfpga/src/base/pb_type_utils.h b/openfpga/src/base/pb_type_utils.h index ac3ade343..17ec7f78e 100644 --- a/openfpga/src/base/pb_type_utils.h +++ b/openfpga/src/base/pb_type_utils.h @@ -41,6 +41,8 @@ e_interconnect pb_interconnect_physical_type(t_interconnect* pb_interc, e_circuit_model_type pb_interconnect_require_circuit_model_type(const e_interconnect& pb_interc_type); +enum PORTS circuit_port_require_pb_port_type(const e_circuit_model_port_type& circuit_port_type); + } /* end namespace openfpga */ #endif diff --git a/openfpga/src/base/vpr_pb_type_annotation.cpp b/openfpga/src/base/vpr_pb_type_annotation.cpp index 97dc7354b..867f40794 100644 --- a/openfpga/src/base/vpr_pb_type_annotation.cpp +++ b/openfpga/src/base/vpr_pb_type_annotation.cpp @@ -89,12 +89,23 @@ e_interconnect VprPbTypeAnnotation::interconnect_physical_type(t_interconnect* p /* Ensure that the pb_type is in the list */ std::map::const_iterator it = interconnect_physical_types_.find(pb_interconnect); if (it == interconnect_physical_types_.end()) { - /* Return an invalid circuit model id */ + /* Return an invalid interconnect type */ return NUM_INTERC_TYPES; } return interconnect_physical_types_.at(pb_interconnect); } +CircuitPortId VprPbTypeAnnotation::pb_circuit_port(t_port* pb_port) const { + /* Ensure that the pb_type is in the list */ + std::map::const_iterator it = pb_circuit_ports_.find(pb_port); + if (it == pb_circuit_ports_.end()) { + /* Return an invalid circuit port id */ + return CircuitPortId::INVALID(); + } + return pb_circuit_ports_.at(pb_port); +} + + /************************************************************************ * Public mutators ***********************************************************************/ @@ -179,4 +190,15 @@ void VprPbTypeAnnotation::add_interconnect_physical_type(t_interconnect* pb_inte interconnect_physical_types_[pb_interconnect] = physical_type; } +void VprPbTypeAnnotation::add_pb_circuit_port(t_port* pb_port, const CircuitPortId& circuit_port) { + /* Warn any override attempt */ + std::map::const_iterator it = pb_circuit_ports_.find(pb_port); + if (it != pb_circuit_ports_.end()) { + VTR_LOG_WARN("Override the circuit port mapping for pb_type port '%s'!\n", + pb_port->name); + } + + pb_circuit_ports_[pb_port] = circuit_port; +} + } /* End namespace openfpga*/ diff --git a/openfpga/src/base/vpr_pb_type_annotation.h b/openfpga/src/base/vpr_pb_type_annotation.h index 824a81e87..fb0fec934 100644 --- a/openfpga/src/base/vpr_pb_type_annotation.h +++ b/openfpga/src/base/vpr_pb_type_annotation.h @@ -37,6 +37,7 @@ class VprPbTypeAnnotation { CircuitModelId pb_type_circuit_model(t_pb_type* physical_pb_type) const; CircuitModelId interconnect_circuit_model(t_interconnect* pb_interconnect) const; e_interconnect interconnect_physical_type(t_interconnect* pb_interconnect) const; + CircuitPortId pb_circuit_port(t_port* pb_port) const; public: /* Public mutators */ void add_pb_type_physical_mode(t_pb_type* pb_type, t_mode* physical_mode); void add_physical_pb_type(t_pb_type* operating_pb_type, t_pb_type* physical_pb_type); @@ -45,6 +46,7 @@ class VprPbTypeAnnotation { void add_pb_type_circuit_model(t_pb_type* physical_pb_type, const CircuitModelId& circuit_model); void add_interconnect_circuit_model(t_interconnect* pb_interconnect, const CircuitModelId& circuit_model); void add_interconnect_physical_type(t_interconnect* pb_interconnect, const e_interconnect& physical_type); + void add_pb_circuit_port(t_port* pb_port, const CircuitPortId& circuit_port); private: /* Internal data */ /* Pair a regular pb_type to its physical pb_type */ std::map physical_pb_types_; @@ -94,6 +96,12 @@ class VprPbTypeAnnotation { */ std::map physical_pb_port_ranges_; + /* Pair a pb_port to a circuit port in circuit model + * Note: + * - the parent of physical pb_port MUST be a physical pb_type + */ + std::map pb_circuit_ports_; + /* Pair a pb_graph_node to a physical pb_graph_node * Note: * - the pb_type of physical pb_graph_node must be a physical pb_type