@@ -905,6 +905,92 @@ bool primitive_type_feasible(const AtomBlockId blk_id, const t_pb_type* cur_pb_t
905905 // Feasible
906906 return true ;
907907}
908+ bool primitive_type_feasible (const AtomBlockId blk_id, t_pb_graph_node* curr_pb_graph_node) {
909+ t_pb_type* cur_pb_type = curr_pb_graph_node->pb_type ;
910+
911+ if (cur_pb_type == nullptr ) {
912+ return false ;
913+ }
914+
915+ auto & atom_ctx = g_vpr_ctx.atom ();
916+ if (cur_pb_type->model != atom_ctx.nlist .block_model (blk_id)) {
917+ if ((strcmp (atom_ctx.nlist .block_model (blk_id)->name , MODEL_LATCH) == 0 ) &&
918+ (strcmp (atom_ctx.nlist .block_model (blk_id)->name , cur_pb_type->model ->name ) == 0 )) {
919+ /* *
920+ * Special case for .latch: this model exists in 2 variations which are
921+ * defined one after another in linked list, check if the second variant match
922+ */
923+
924+ if (cur_pb_type->model ->next == atom_ctx.nlist .block_model (blk_id) && atom_ctx.nlist .block_model (blk_id)->inputs [1 ].trigg_edge == TriggeringEdge::FALLING_EDGE) {
925+ // Next primitive match atom - add secondary references
926+ if (!curr_pb_graph_node->has_secondary )
927+ curr_pb_graph_node->update_pins ();
928+ } else {
929+ // Next primitive and atom do not match
930+ return false ;
931+ }
932+ } else {
933+ // Primitive and atom do not match
934+ return false ;
935+ }
936+ }
937+
938+ VTR_ASSERT_MSG (atom_ctx.nlist .is_compressed (), " This function assumes a compressed/non-dirty netlist" );
939+
940+ // Keep track of how many atom ports were checked.
941+ //
942+ // We need to do this since we iterate over the pb's ports and
943+ // may miss some atom ports if there is a mismatch
944+ size_t checked_ports = 0 ;
945+
946+ // Look at each port on the pb and find the associated port on the
947+ // atom. To be feasible the pb must have as many pins on each port
948+ // as the atom requires
949+ for (int iport = 0 ; iport < cur_pb_type->num_ports ; ++iport) {
950+ t_port* pb_port;
951+ if (curr_pb_graph_node->has_secondary )
952+ pb_port = &cur_pb_type->ports_sec [iport];
953+ else
954+ pb_port = &cur_pb_type->ports [iport];
955+
956+ const t_model_ports* pb_model_port = pb_port->model_port ;
957+
958+ // Find the matching port on the atom
959+ auto port_id = atom_ctx.nlist .find_atom_port (blk_id, pb_model_port);
960+
961+ if (port_id) { // Port is used by the atom
962+
963+ // In compressed form the atom netlist stores only in-use pins,
964+ // so we can query the number of required pins directly
965+ int required_atom_pins = atom_ctx.nlist .port_pins (port_id).size ();
966+
967+ int available_pb_pins = pb_port->num_pins ;
968+
969+ if (available_pb_pins < required_atom_pins) {
970+ // Too many pins required
971+ return false ;
972+ }
973+
974+ // Note that this port was checked
975+ ++checked_ports;
976+ }
977+ }
978+
979+ // Similarly to pins, only in-use ports are stored in the compressed
980+ // atom netlist, so we can figure out how many ports should have been
981+ // checked directly
982+ size_t atom_ports = atom_ctx.nlist .block_ports (blk_id).size ();
983+
984+ // See if all the atom ports were checked
985+ if (checked_ports != atom_ports) {
986+ VTR_ASSERT (checked_ports < atom_ports);
987+ // Required atom port was missing from physical primitive
988+ return false ;
989+ }
990+
991+ // Feasible
992+ return true ;
993+ }
908994
909995// Returns the sibling atom of a memory slice pb
910996// Note that the pb must be part of a MEMORY_CLASS
0 commit comments