@@ -552,7 +552,7 @@ void generate_opname_ram (t_node* vqm_node, const LogicalModels& arch_models, st
552
552
reg_outputs = true ;
553
553
}
554
554
} 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 " );
556
556
VTR_ASSERT_MSG (ram_info.port_b_input_clock , " RAM inputs always assumed sequential" );
557
557
558
558
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
568
568
cout << " port A output sequential: " << bool (ram_info.port_a_output_clock ) << " \n " ;
569
569
cout << " port B output sequential: " << bool (ram_info.port_b_output_clock ) << " \n " ;
570
570
}
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
+ }
571
581
}
572
582
}
573
583
@@ -602,6 +612,8 @@ void generate_opname_ram (t_node* vqm_node, const LogicalModels& arch_models, st
602
612
// && (port_b_data_width == NULL) && (port_b_addr_width == NULL)) {
603
613
if (ram_info.mode == " single_port" || ram_info.mode == " rom" ) {
604
614
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 );
605
617
606
618
// Only print the address width, the data widths are handled by the VPR memory class
607
619
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
613
625
}
614
626
615
627
// 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 );
618
631
619
632
// 2) Both ports are the same size, so only append the address widths, the data widths are handled by the VPR memory class
620
633
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
645
658
tmp_mode_hash.append (" .port_a_data_width{" + std::to_string (ram_info.port_a_data_width ) + " }" );
646
659
tmp_mode_hash.append (" .port_b_data_width{" + std::to_string (ram_info.port_b_data_width ) + " }" );
647
660
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
+
648
708
LogicalModelId arch_model_id = arch_models.get_model_by_name (tmp_mode_hash);
649
709
if (!arch_model_id.is_valid ()) {
650
710
// 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) {
997
1057
// We need to save the ram data and address widths, to identfy the RAM type (singel port, rom, simple dual port, true dual port)
998
1058
t_node_parameter* port_a_data_width = NULL ;
999
1059
t_node_parameter* port_a_addr_width = NULL ;
1060
+ t_node_parameter* port_a_addr2_width = NULL ;
1000
1061
t_node_parameter* port_b_data_width = NULL ;
1001
1062
t_node_parameter* port_b_addr_width = NULL ;
1063
+ t_node_parameter* port_b_addr2_width = NULL ;
1002
1064
1003
1065
for (int i = 0 ; i < vqm_node->number_of_params ; i++){
1004
1066
// 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) {
1020
1082
port_a_addr_width = temp_param;
1021
1083
continue ;
1022
1084
}
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
+ }
1023
1090
if (strcmp (temp_param->name , " port_b_data_width" ) == 0 ){
1024
1091
VTR_ASSERT ( temp_param->type == NODE_PARAMETER_INTEGER );
1025
1092
port_b_data_width = temp_param;
@@ -1030,6 +1097,11 @@ RamInfo get_ram_info(const t_node* vqm_node, string device) {
1030
1097
port_b_addr_width = temp_param;
1031
1098
continue ;
1032
1099
}
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
+ }
1033
1105
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
1034
1106
VTR_ASSERT ( temp_param->type == NODE_PARAMETER_STRING );
1035
1107
port_a_address_clock = temp_param;
@@ -1096,6 +1168,12 @@ RamInfo get_ram_info(const t_node* vqm_node, string device) {
1096
1168
VTR_ASSERT (port_a_data_width);
1097
1169
ram_info.port_a_data_width = port_a_data_width->value .integer_value ;
1098
1170
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
+ }
1099
1177
if (port_b_addr_width) {
1100
1178
ram_info.port_b_addr_width = port_b_addr_width->value .integer_value ;
1101
1179
}
0 commit comments