mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-11-04 05:19:11 +00:00 
			
		
		
		
	Resolve multiple dimensions defined in stages with typedef
This commit is contained in:
		
							parent
							
								
									e0d3977e19
								
							
						
					
					
						commit
						03f35c3def
					
				
					 2 changed files with 70 additions and 74 deletions
				
			
		| 
						 | 
					@ -554,6 +554,22 @@ static AstNode *make_packed_struct(AstNode *template_node, std::string &name, de
 | 
				
			||||||
	return wnode;
 | 
						return wnode;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void prepend_ranges(AstNode *&range, AstNode *range_add)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						// Convert range to multirange.
 | 
				
			||||||
 | 
						if (range->type == AST_RANGE)
 | 
				
			||||||
 | 
							range = new AstNode(AST_MULTIRANGE, range);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Add range or ranges.
 | 
				
			||||||
 | 
						if (range_add->type == AST_RANGE)
 | 
				
			||||||
 | 
							range->children.insert(range->children.begin(), range_add->clone());
 | 
				
			||||||
 | 
						else {
 | 
				
			||||||
 | 
							int i = 0;
 | 
				
			||||||
 | 
							for (auto child : range_add->children)
 | 
				
			||||||
 | 
								range->children.insert(range->children.begin() + i++, child->clone());
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// check if a node or its children contains an assignment to the given variable
 | 
					// check if a node or its children contains an assignment to the given variable
 | 
				
			||||||
static bool node_contains_assignment_to(const AstNode* node, const AstNode* var)
 | 
					static bool node_contains_assignment_to(const AstNode* node, const AstNode* var)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -1879,8 +1895,10 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin
 | 
				
			||||||
			log_assert(resolved_type_node->children.size() == 1);
 | 
								log_assert(resolved_type_node->children.size() == 1);
 | 
				
			||||||
			AstNode *template_node = resolved_type_node->children[0];
 | 
								AstNode *template_node = resolved_type_node->children[0];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// Ensure typedef itself is fully simplified
 | 
								// Resolve the typedef from the bottom up, recursing within the current
 | 
				
			||||||
			while (template_node->simplify(const_fold, stage, width_hint, sign_hint)) {};
 | 
								// block of code. Defer further simplification until the complete type is
 | 
				
			||||||
 | 
								// resolved.
 | 
				
			||||||
 | 
								while (template_node->is_custom_type && template_node->simplify(const_fold, stage, width_hint, sign_hint)) {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (!str.empty() && str[0] == '\\' && (template_node->type == AST_STRUCT || template_node->type == AST_UNION)) {
 | 
								if (!str.empty() && str[0] == '\\' && (template_node->type == AST_STRUCT || template_node->type == AST_UNION)) {
 | 
				
			||||||
				// replace instance with wire representing the packed structure
 | 
									// replace instance with wire representing the packed structure
 | 
				
			||||||
| 
						 | 
					@ -1893,90 +1911,68 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin
 | 
				
			||||||
				goto apply_newNode;
 | 
									goto apply_newNode;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// Remove type reference
 | 
								// Prepare replacement node.
 | 
				
			||||||
			delete children[0];
 | 
								newNode = template_node->clone();
 | 
				
			||||||
			children.erase(children.begin());
 | 
								newNode->str = str;
 | 
				
			||||||
 | 
								newNode->set_attribute(ID::wiretype, mkconst_str(resolved_type_node->str));
 | 
				
			||||||
			if (type == AST_WIRE)
 | 
								newNode->is_input = is_input;
 | 
				
			||||||
				type = template_node->type;
 | 
								newNode->is_output = is_output;
 | 
				
			||||||
			is_reg = template_node->is_reg;
 | 
								newNode->is_wand = is_wand;
 | 
				
			||||||
			is_logic = template_node->is_logic;
 | 
								newNode->is_wor = is_wor;
 | 
				
			||||||
			is_signed = template_node->is_signed;
 | 
								for (auto &pair : attributes)
 | 
				
			||||||
			is_string = template_node->is_string;
 | 
									newNode->set_attribute(pair.first, pair.second->clone());
 | 
				
			||||||
			is_custom_type = template_node->is_custom_type;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			range_valid = template_node->range_valid;
 | 
					 | 
				
			||||||
			range_swapped = template_node->range_swapped;
 | 
					 | 
				
			||||||
			range_left = template_node->range_left;
 | 
					 | 
				
			||||||
			range_right = template_node->range_right;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			set_attribute(ID::wiretype, mkconst_str(resolved_type_node->str));
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// if an enum then add attributes to support simulator tracing
 | 
								// if an enum then add attributes to support simulator tracing
 | 
				
			||||||
			annotateTypedEnums(template_node);
 | 
								newNode->annotateTypedEnums(template_node);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// Insert clones children from template at beginning
 | 
								bool add_packed_dimensions = (type == AST_WIRE && GetSize(children) > 1) || (type == AST_MEMORY && GetSize(children) > 2);
 | 
				
			||||||
			for (int i  = 0; i < GetSize(template_node->children); i++)
 | 
					 | 
				
			||||||
				children.insert(children.begin() + i, template_node->children[i]->clone());
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (type == AST_MEMORY && GetSize(children) == 1) {
 | 
								// Cannot add packed dimensions if unpacked dimensions are already specified.
 | 
				
			||||||
				// Single-bit memories must have [0:0] range
 | 
								if (add_packed_dimensions && newNode->type == AST_MEMORY)
 | 
				
			||||||
				AstNode *rng = make_range(0, 0);
 | 
									input_error("Cannot extend unpacked type `%s' with packed dimensions\n", type_name.c_str());
 | 
				
			||||||
				children.insert(children.begin(), rng);
 | 
					
 | 
				
			||||||
 | 
								// Add packed dimensions.
 | 
				
			||||||
 | 
								if (add_packed_dimensions) {
 | 
				
			||||||
 | 
									AstNode *packed = children[1];
 | 
				
			||||||
 | 
									if (newNode->children.empty())
 | 
				
			||||||
 | 
										newNode->children.insert(newNode->children.begin(), packed->clone());
 | 
				
			||||||
 | 
									else
 | 
				
			||||||
 | 
										prepend_ranges(newNode->children[0], packed);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			fixup_hierarchy_flags();
 | 
					
 | 
				
			||||||
			did_something = true;
 | 
								// Add unpacked dimensions.
 | 
				
			||||||
 | 
								if (type == AST_MEMORY) {
 | 
				
			||||||
 | 
									AstNode *unpacked = children.back();
 | 
				
			||||||
 | 
									if (GetSize(newNode->children) < 2)
 | 
				
			||||||
 | 
										newNode->children.push_back(unpacked->clone());
 | 
				
			||||||
 | 
									else
 | 
				
			||||||
 | 
										prepend_ranges(newNode->children[1], unpacked);
 | 
				
			||||||
 | 
									newNode->type = type;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// Prepare to generate dimensions metadata for the resolved type.
 | 
				
			||||||
 | 
								newNode->dimensions.clear();
 | 
				
			||||||
 | 
								newNode->unpacked_dimensions = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								goto apply_newNode;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		log_assert(!is_custom_type);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// resolve types of parameters
 | 
						// resolve types of parameters
 | 
				
			||||||
	if (type == AST_LOCALPARAM || type == AST_PARAMETER) {
 | 
						if (type == AST_LOCALPARAM || type == AST_PARAMETER) {
 | 
				
			||||||
		if (is_custom_type) {
 | 
							if (is_custom_type) {
 | 
				
			||||||
			log_assert(children.size() == 2);
 | 
								log_assert(children.size() >= 2);
 | 
				
			||||||
			log_assert(children[1]->type == AST_WIRETYPE);
 | 
								log_assert(children[1]->type == AST_WIRETYPE);
 | 
				
			||||||
			auto type_name = children[1]->str;
 | 
								// Pretend it's a wire in order to resolve the type in the code block above.
 | 
				
			||||||
			if (!current_scope.count(type_name)) {
 | 
								AstNodeType param_type = type;
 | 
				
			||||||
				input_error("Unknown identifier `%s' used as type name\n", type_name.c_str());
 | 
								type = AST_WIRE;
 | 
				
			||||||
			}
 | 
								AstNode *expr = children[0];
 | 
				
			||||||
			AstNode *resolved_type_node = current_scope.at(type_name);
 | 
								children.erase(children.begin());
 | 
				
			||||||
			if (resolved_type_node->type != AST_TYPEDEF)
 | 
								while (simplify(const_fold, stage, width_hint, sign_hint)) {};
 | 
				
			||||||
				input_error("`%s' does not name a type\n", type_name.c_str());
 | 
								type = param_type;
 | 
				
			||||||
			log_assert(resolved_type_node->children.size() == 1);
 | 
								children.insert(children.begin(), expr);
 | 
				
			||||||
			AstNode *template_node = resolved_type_node->children[0];
 | 
								if (children[1]->type == AST_MEMORY)
 | 
				
			||||||
 | 
					 | 
				
			||||||
			// Ensure typedef itself is fully simplified
 | 
					 | 
				
			||||||
			while (template_node->simplify(const_fold, stage, width_hint, sign_hint)) {};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if (template_node->type == AST_STRUCT || template_node->type == AST_UNION) {
 | 
					 | 
				
			||||||
				// replace with wire representing the packed structure
 | 
					 | 
				
			||||||
				newNode = make_packed_struct(template_node, str, attributes);
 | 
					 | 
				
			||||||
				newNode->set_attribute(ID::wiretype, mkconst_str(resolved_type_node->str));
 | 
					 | 
				
			||||||
				newNode->type = type;
 | 
					 | 
				
			||||||
				current_scope[str] = this;
 | 
					 | 
				
			||||||
				// copy param value, it needs to be 1st value
 | 
					 | 
				
			||||||
				delete children[1];
 | 
					 | 
				
			||||||
				children.pop_back();
 | 
					 | 
				
			||||||
				newNode->children.insert(newNode->children.begin(), children[0]->clone());
 | 
					 | 
				
			||||||
				goto apply_newNode;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			delete children[1];
 | 
					 | 
				
			||||||
			children.pop_back();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if (template_node->type == AST_MEMORY)
 | 
					 | 
				
			||||||
				input_error("unpacked array type `%s' cannot be used for a parameter\n", children[1]->str.c_str());
 | 
									input_error("unpacked array type `%s' cannot be used for a parameter\n", children[1]->str.c_str());
 | 
				
			||||||
			is_signed = template_node->is_signed;
 | 
					 | 
				
			||||||
			is_string = template_node->is_string;
 | 
					 | 
				
			||||||
			is_custom_type = template_node->is_custom_type;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			range_valid = template_node->range_valid;
 | 
					 | 
				
			||||||
			range_swapped = template_node->range_swapped;
 | 
					 | 
				
			||||||
			range_left = template_node->range_left;
 | 
					 | 
				
			||||||
			range_right = template_node->range_right;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			set_attribute(ID::wiretype, mkconst_str(resolved_type_node->str));
 | 
					 | 
				
			||||||
			for (auto template_child : template_node->children)
 | 
					 | 
				
			||||||
				children.push_back(template_child->clone());
 | 
					 | 
				
			||||||
			fixup_hierarchy_flags();
 | 
								fixup_hierarchy_flags();
 | 
				
			||||||
			did_something = true;
 | 
								did_something = true;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2122,7 +2122,7 @@ typedef_decl:
 | 
				
			||||||
			astbuf1->children.push_back(astbuf2);
 | 
								astbuf1->children.push_back(astbuf2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if ($5 != NULL) {
 | 
							if ($5 != NULL) {
 | 
				
			||||||
			if (!astbuf2) {
 | 
								if (!astbuf2 && !astbuf1->is_custom_type) {
 | 
				
			||||||
				addRange(astbuf1, 0, 0, false);
 | 
									addRange(astbuf1, 0, 0, false);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			rewriteAsMemoryNode(astbuf1, $5);
 | 
								rewriteAsMemoryNode(astbuf1, $5);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue