@@ -552,7 +552,7 @@ void generate_opname_ram (t_node* vqm_node, const LogicalModels& arch_models, st
552552 reg_outputs = true ;
553553 }
554554 } else {
555- VTR_ASSERT (ram_info.mode == " dual_port" || ram_info.mode == " bidir_dual_port" );
555+ VTR_ASSERT (ram_info.mode == " dual_port" || ram_info.mode == " bidir_dual_port" || ram_info. mode == " quad_port " );
556556 VTR_ASSERT_MSG (ram_info.port_b_input_clock , " RAM inputs always assumed sequential" );
557557
558558 if (ram_info.mode == " dual_port" && ram_info.port_b_output_clock ) {
@@ -568,6 +568,16 @@ void generate_opname_ram (t_node* vqm_node, const LogicalModels& arch_models, st
568568 cout << " port A output sequential: " << bool (ram_info.port_a_output_clock ) << " \n " ;
569569 cout << " port B output sequential: " << bool (ram_info.port_b_output_clock ) << " \n " ;
570570 }
571+ } else {
572+ if (ram_info.port_a_output_clock && ram_info.port_b_output_clock ) {
573+ reg_outputs = true ; // Sequential output
574+ } else if (!ram_info.port_a_output_clock && !ram_info.port_b_output_clock ) {
575+ reg_outputs = false ; // Comb output
576+ } else {
577+ cout << " Unable to resolve whether quad port RAM " << vqm_node->name << " outputs are sequential or combinational:\n " ;
578+ cout << " port A output sequential: " << bool (ram_info.port_a_output_clock ) << " \n " ;
579+ cout << " port B output sequential: " << bool (ram_info.port_b_output_clock ) << " \n " ;
580+ }
571581 }
572582 }
573583
@@ -602,6 +612,8 @@ void generate_opname_ram (t_node* vqm_node, const LogicalModels& arch_models, st
602612 // && (port_b_data_width == NULL) && (port_b_addr_width == NULL)) {
603613 if (ram_info.mode == " single_port" || ram_info.mode == " rom" ) {
604614 VTR_ASSERT (ram_info.port_b_addr_width == 0 );
615+ VTR_ASSERT (ram_info.port_b_addr2_width == 0 );
616+ VTR_ASSERT (ram_info.port_a_addr2_width == 0 );
605617
606618 // Only print the address width, the data widths are handled by the VPR memory class
607619 mode_hash.append (" .port_a_address_width{" + std::to_string (ram_info.port_a_addr_width ) + " }" );
@@ -613,8 +625,9 @@ void generate_opname_ram (t_node* vqm_node, const LogicalModels& arch_models, st
613625 }
614626
615627 // A dual port memory, both port A and B params have been found
616- } else {
617- VTR_ASSERT (ram_info.mode == " dual_port" || ram_info.mode == " bidir_dual_port" );
628+ } else if (ram_info.mode == " dual_port" || ram_info.mode == " bidir_dual_port" ){
629+ VTR_ASSERT (ram_info.port_b_addr2_width == 0 );
630+ VTR_ASSERT (ram_info.port_a_addr2_width == 0 );
618631
619632 // 2) Both ports are the same size, so only append the address widths, the data widths are handled by the VPR memory class
620633 if ( (ram_info.port_a_data_width == ram_info.port_b_data_width )
@@ -645,6 +658,53 @@ void generate_opname_ram (t_node* vqm_node, const LogicalModels& arch_models, st
645658 tmp_mode_hash.append (" .port_a_data_width{" + std::to_string (ram_info.port_a_data_width ) + " }" );
646659 tmp_mode_hash.append (" .port_b_data_width{" + std::to_string (ram_info.port_b_data_width ) + " }" );
647660
661+ LogicalModelId arch_model_id = arch_models.get_model_by_name (tmp_mode_hash);
662+ if (!arch_model_id.is_valid ()) {
663+ // 3a) Not found, use the default name (no specific address/data widths)
664+ ; // do nothing
665+ } else {
666+ // 3b) Use the more detailed name, since it was found in the architecture
667+ mode_hash = tmp_mode_hash;
668+ }
669+ }
670+ } else {
671+ VTR_ASSERT (ram_info.mode == " quad_port" );
672+
673+ // 2) Both ports are the same size, so only append the address widths, the data widths are handled by the VPR memory class
674+ if ( (ram_info.port_a_data_width == ram_info.port_b_data_width )
675+ && (ram_info.port_a_addr_width == ram_info.port_b_addr_width )
676+ && (ram_info.port_a_addr_width == ram_info.port_b_addr2_width )
677+ && (ram_info.port_a_addr2_width == ram_info.port_b_addr2_width )) {
678+
679+ mode_hash.append (" .port_a_address_width{" + std::to_string (ram_info.port_a_addr_width ) + " }" );
680+ mode_hash.append (" .port_a_address2_width{" + std::to_string (ram_info.port_a_addr2_width ) + " }" );
681+ mode_hash.append (" .port_b_address_width{" + std::to_string (ram_info.port_b_addr_width ) + " }" );
682+ mode_hash.append (" .port_b_address2_width{" + std::to_string (ram_info.port_b_addr2_width ) + " }" );
683+
684+ LogicalModelId arch_model_id = arch_models.get_model_by_name (mode_hash);
685+ if (!arch_model_id.is_valid ()) {
686+ cout << " Error: could not find dual port (non-mixed_width) memory primitive '" << mode_hash << " ' in architecture file" ;
687+ exit (1 );
688+ }
689+ // 3) Mixed width dual port ram
690+ } else {
691+ // Make a temporary copy of the mode hash
692+ string tmp_mode_hash = mode_hash;
693+
694+ /*
695+ * Try to see if the detailed version exists in the architecture,
696+ * if it does, use it. Otherwise use the operation mode only.
697+ */
698+
699+ tmp_mode_hash.append (" .port_a_address_width{" + std::to_string (ram_info.port_a_addr_width ) + " }" );
700+ tmp_mode_hash.append (" .port_a_address2_width{" + std::to_string (ram_info.port_a_addr2_width ) + " }" );
701+ tmp_mode_hash.append (" .port_b_address_width{" + std::to_string (ram_info.port_b_addr_width ) + " }" );
702+ tmp_mode_hash.append (" .port_b_address2_width{" + std::to_string (ram_info.port_b_addr2_width ) + " }" );
703+
704+ // Each port has a different size, so print both the address and data widths. Mixed widths are not handled by the VPR memory class
705+ tmp_mode_hash.append (" .port_a_data_width{" + std::to_string (ram_info.port_a_data_width ) + " }" );
706+ tmp_mode_hash.append (" .port_b_data_width{" + std::to_string (ram_info.port_b_data_width ) + " }" );
707+
648708 LogicalModelId arch_model_id = arch_models.get_model_by_name (tmp_mode_hash);
649709 if (!arch_model_id.is_valid ()) {
650710 // 3a) Not found, use the default name (no specific address/data widths)
@@ -997,8 +1057,10 @@ RamInfo get_ram_info(const t_node* vqm_node, string device) {
9971057 // We need to save the ram data and address widths, to identfy the RAM type (singel port, rom, simple dual port, true dual port)
9981058 t_node_parameter* port_a_data_width = NULL ;
9991059 t_node_parameter* port_a_addr_width = NULL ;
1060+ t_node_parameter* port_a_addr2_width = NULL ;
10001061 t_node_parameter* port_b_data_width = NULL ;
10011062 t_node_parameter* port_b_addr_width = NULL ;
1063+ t_node_parameter* port_b_addr2_width = NULL ;
10021064
10031065 for (int i = 0 ; i < vqm_node->number_of_params ; i++){
10041066 // Each parameter specifies a configuration of the node in the circuit.
@@ -1020,6 +1082,11 @@ RamInfo get_ram_info(const t_node* vqm_node, string device) {
10201082 port_a_addr_width = temp_param;
10211083 continue ;
10221084 }
1085+ if (strcmp (temp_param->name , " port_a_address2_width" ) == 0 ){
1086+ VTR_ASSERT ( temp_param->type == NODE_PARAMETER_INTEGER );
1087+ port_a_addr2_width = temp_param;
1088+ continue ;
1089+ }
10231090 if (strcmp (temp_param->name , " port_b_data_width" ) == 0 ){
10241091 VTR_ASSERT ( temp_param->type == NODE_PARAMETER_INTEGER );
10251092 port_b_data_width = temp_param;
@@ -1030,6 +1097,11 @@ RamInfo get_ram_info(const t_node* vqm_node, string device) {
10301097 port_b_addr_width = temp_param;
10311098 continue ;
10321099 }
1100+ if (strcmp (temp_param->name , " port_b_address2_width" ) == 0 ){
1101+ VTR_ASSERT ( temp_param->type == NODE_PARAMETER_INTEGER );
1102+ port_b_addr2_width = temp_param;
1103+ continue ;
1104+ }
10331105 if (strcmp (temp_param->name , " port_a_address_clock" ) == 0 ){ // This parameter doesn't exist for Stratix 10 - clock0 is always used for port address_a
10341106 VTR_ASSERT ( temp_param->type == NODE_PARAMETER_STRING );
10351107 port_a_address_clock = temp_param;
@@ -1096,6 +1168,12 @@ RamInfo get_ram_info(const t_node* vqm_node, string device) {
10961168 VTR_ASSERT (port_a_data_width);
10971169 ram_info.port_a_data_width = port_a_data_width->value .integer_value ;
10981170
1171+ if (port_a_addr2_width) {
1172+ ram_info.port_a_addr2_width = port_a_addr2_width->value .integer_value ;
1173+ }
1174+ if (port_b_addr2_width) {
1175+ ram_info.port_b_addr2_width = port_b_addr2_width->value .integer_value ;
1176+ }
10991177 if (port_b_addr_width) {
11001178 ram_info.port_b_addr_width = port_b_addr_width->value .integer_value ;
11011179 }
0 commit comments