mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-11-04 13:29:12 +00:00 
			
		
		
		
	Add support for copying unpacked arrays
Signed-off-by: Lukasz Dalek <ldalek@antmicro.com>
This commit is contained in:
		
							parent
							
								
									2257a9a721
								
							
						
					
					
						commit
						df390a1ceb
					
				
					 2 changed files with 156 additions and 0 deletions
				
			
		| 
						 | 
					@ -944,6 +944,122 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
 | 
				
			||||||
				if (!is_rand_reg)
 | 
									if (!is_rand_reg)
 | 
				
			||||||
					log_warning("reg '%s' is assigned in a continuous assignment at %s:%d.%d-%d.%d.\n", children[0]->str.c_str(), filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column);
 | 
										log_warning("reg '%s' is assigned in a continuous assignment at %s:%d.%d-%d.%d.\n", children[0]->str.c_str(), filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// Copy entire (unpacked) array
 | 
				
			||||||
 | 
								if (children[0]->id2ast->type == AST_MEMORY &&
 | 
				
			||||||
 | 
										children[1]->type == AST_IDENTIFIER && children[1]->id2ast && children[1]->id2ast->type == AST_MEMORY &&
 | 
				
			||||||
 | 
										children[0]->children.empty() && children[1]->children.empty()) {
 | 
				
			||||||
 | 
									const auto& lhs_unpacked_range = children[0]->id2ast->children[1];
 | 
				
			||||||
 | 
									log_assert(lhs_unpacked_range->basic_prep);
 | 
				
			||||||
 | 
									const auto& rhs_unpacked_range = children[1]->id2ast->children[1];
 | 
				
			||||||
 | 
									log_assert(rhs_unpacked_range->basic_prep);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									log_assert(lhs_unpacked_range->range_valid && rhs_unpacked_range->range_valid);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									int lhs_width = lhs_unpacked_range->range_left - lhs_unpacked_range->range_right + 1;
 | 
				
			||||||
 | 
									int rhs_width = rhs_unpacked_range->range_left - rhs_unpacked_range->range_right + 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if (lhs_width != rhs_width)
 | 
				
			||||||
 | 
										log_error("Array '%s' and '%s' differs in size: %s:%d.%d-%d.%d.\n",
 | 
				
			||||||
 | 
											children[0]->str.c_str(), children[1]->str.c_str(), filename.c_str(),
 | 
				
			||||||
 | 
											location.first_line, location.first_column, location.last_line, location.last_column);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									const auto& lhs_multirange = children[0]->id2ast->multirange_dimensions;
 | 
				
			||||||
 | 
									const auto& lhs_multirange_swapped = children[0]->id2ast->multirange_swapped;
 | 
				
			||||||
 | 
									log_assert(lhs_multirange.size() == 2*lhs_multirange_swapped.size());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									const auto& rhs_multirange = children[1]->id2ast->multirange_dimensions;
 | 
				
			||||||
 | 
									const auto& rhs_multirange_swapped = children[1]->id2ast->multirange_swapped;
 | 
				
			||||||
 | 
									log_assert(rhs_multirange.size() == 2*rhs_multirange_swapped.size());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if (lhs_multirange.size() != rhs_multirange.size())
 | 
				
			||||||
 | 
										log_error("Array '%s' and '%s' differs in size: %s:%d.%d-%d.%d.\n",
 | 
				
			||||||
 | 
											children[0]->str.c_str(), children[1]->str.c_str(), filename.c_str(),
 | 
				
			||||||
 | 
											location.first_line, location.first_column, location.last_line, location.last_column);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									// Create template from (this) assignment
 | 
				
			||||||
 | 
									const auto* tmpl = this->clone();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									// Replace assignment with [gen]block
 | 
				
			||||||
 | 
									log_assert(type == AST_ASSIGN_EQ || type == AST_ASSIGN_LE || type == AST_ASSIGN);
 | 
				
			||||||
 | 
									if (type == AST_ASSIGN) {
 | 
				
			||||||
 | 
										type = AST_GENBLOCK;
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										type = AST_BLOCK;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									children.clear();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									// multirange_combined combines multirange offset, dimension and swapped parameter
 | 
				
			||||||
 | 
									std::vector<int> lhs_multirange_combined, rhs_multirange_combined;
 | 
				
			||||||
 | 
									for (size_t i = 0; i < lhs_multirange.size() / 2; ++i) {
 | 
				
			||||||
 | 
										lhs_multirange_combined.push_back(lhs_multirange[2*i+0]); // offset
 | 
				
			||||||
 | 
										lhs_multirange_combined.push_back(lhs_multirange[2*i+1]); // size
 | 
				
			||||||
 | 
										lhs_multirange_combined.push_back(lhs_multirange_swapped[i]);  // swapped
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										rhs_multirange_combined.push_back(rhs_multirange[2*i+0]); // offset
 | 
				
			||||||
 | 
										rhs_multirange_combined.push_back(rhs_multirange[2*i+1]); // size
 | 
				
			||||||
 | 
										rhs_multirange_combined.push_back(rhs_multirange_swapped[i]);  // swapped
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									std::vector<std::tuple<int, int>> unrolled_assigment;
 | 
				
			||||||
 | 
									std::function<void(
 | 
				
			||||||
 | 
											const std::vector<int>&,
 | 
				
			||||||
 | 
											const std::vector<int>&,
 | 
				
			||||||
 | 
											const int, const int)> unroll_array_assigment =
 | 
				
			||||||
 | 
										[&unroll_array_assigment,&unrolled_assigment](
 | 
				
			||||||
 | 
												const std::vector<int>& lhs_multirange_combined,
 | 
				
			||||||
 | 
												const std::vector<int>& rhs_multirange_combined,
 | 
				
			||||||
 | 
												const int lhs_offset, const int rhs_offset) {
 | 
				
			||||||
 | 
											if (lhs_multirange_combined.empty() || rhs_multirange_combined.empty()) {
 | 
				
			||||||
 | 
												unrolled_assigment.push_back(std::tuple<int, int>(lhs_offset, rhs_offset));
 | 
				
			||||||
 | 
												return;
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											for (int idx = 0; idx < lhs_multirange_combined[1]; ++idx) {
 | 
				
			||||||
 | 
												std::vector<int> lhs_subrange_combined, rhs_subrange_combined;
 | 
				
			||||||
 | 
												lhs_subrange_combined = std::vector<int>(
 | 
				
			||||||
 | 
													lhs_multirange_combined.begin()+3, lhs_multirange_combined.end());
 | 
				
			||||||
 | 
												rhs_subrange_combined = std::vector<int>(
 | 
				
			||||||
 | 
													rhs_multirange_combined.begin()+3, rhs_multirange_combined.end());
 | 
				
			||||||
 | 
												int lhs_idx = !lhs_multirange_combined[2]?idx:lhs_multirange_combined[1] - idx - 1;
 | 
				
			||||||
 | 
												int rhs_idx = !rhs_multirange_combined[2]?idx:rhs_multirange_combined[1] - idx - 1;
 | 
				
			||||||
 | 
												unroll_array_assigment(lhs_subrange_combined, rhs_subrange_combined,
 | 
				
			||||||
 | 
													lhs_offset*lhs_multirange_combined[1]+lhs_idx,
 | 
				
			||||||
 | 
													rhs_offset*rhs_multirange_combined[1]+rhs_idx);
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									// Recursively unroll array assignment
 | 
				
			||||||
 | 
									unroll_array_assigment(lhs_multirange_combined, rhs_multirange_combined, 0, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									// Generate assigments from unrolled array
 | 
				
			||||||
 | 
									for (const auto& itr : unrolled_assigment) {
 | 
				
			||||||
 | 
										auto* assign = tmpl->clone();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										assign->children[0]->children.push_back(new AstNode(AST_RANGE));
 | 
				
			||||||
 | 
										assign->children[1]->children.push_back(new AstNode(AST_RANGE));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										assign->children[0]->children[0]->children.push_back(AstNode::mkconst_int(std::get<0>(itr), true));
 | 
				
			||||||
 | 
										assign->children[1]->children[0]->children.push_back(AstNode::mkconst_int(std::get<1>(itr), true));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										// simplify
 | 
				
			||||||
 | 
										assign->children[0]->basic_prep = false;
 | 
				
			||||||
 | 
										while (!assign->children[0]->basic_prep && assign->children[0]->simplify(false, false, true, stage, -1, false, in_param))
 | 
				
			||||||
 | 
											did_something = true;
 | 
				
			||||||
 | 
										assign->children[1]->basic_prep = false;
 | 
				
			||||||
 | 
										while (!assign->children[1]->basic_prep && assign->children[1]->simplify(false, false, true, stage, -1, false, in_param))
 | 
				
			||||||
 | 
											did_something = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										assign->children[0]->was_checked = true;
 | 
				
			||||||
 | 
										assign->children[1]->was_checked = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										children.push_back(assign);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									log_assert(GetSize(this->children) == lhs_width);
 | 
				
			||||||
 | 
									did_something = true;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			children[0]->was_checked = true;
 | 
								children[0]->was_checked = true;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										40
									
								
								tests/svtypes/array_copy.sv
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								tests/svtypes/array_copy.sv
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,40 @@
 | 
				
			||||||
 | 
					// test multirange array assignement (copy)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module top;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					logic a [1:0][1:0];
 | 
				
			||||||
 | 
					logic b [1:0][1:0];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					assign a[0][0] = 1'b0;
 | 
				
			||||||
 | 
					assign a[0][1] = 1'b1;
 | 
				
			||||||
 | 
					assign a[1][0] = 1'b1;
 | 
				
			||||||
 | 
					assign a[1][1] = 1'b1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					assign b = a;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					always_comb begin
 | 
				
			||||||
 | 
						assert(b[0][0] == 1'b0);
 | 
				
			||||||
 | 
						assert(b[0][1] == 1'b1);
 | 
				
			||||||
 | 
						assert(b[1][0] == 1'b1);
 | 
				
			||||||
 | 
						assert(b[1][1] == 1'b1);
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// reversed indicies
 | 
				
			||||||
 | 
					logic r_a [1:0][1:0];
 | 
				
			||||||
 | 
					logic r_b [1:0][0:1];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					assign r_a[0][0] = 1'b0;
 | 
				
			||||||
 | 
					assign r_a[0][1] = 1'b1;
 | 
				
			||||||
 | 
					assign r_a[1][0] = 1'b1;
 | 
				
			||||||
 | 
					assign r_a[1][1] = 1'b1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					assign r_b = r_a;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					always_comb begin
 | 
				
			||||||
 | 
					  assert(r_b[0][1] == 1'b0);
 | 
				
			||||||
 | 
					  assert(r_b[0][0] == 1'b1);
 | 
				
			||||||
 | 
					  assert(r_b[1][1] == 1'b1);
 | 
				
			||||||
 | 
					  assert(r_b[1][0] == 1'b1);
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					endmodule
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue