mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-11-04 13:29:12 +00:00 
			
		
		
		
	partial rebase of PeterCrozier's enum work onto current master
I tried to keep only the enum-related changes, and minimize the diff. (The
original commit also had a lot of work done to get typedefs working, but yosys
has diverged quite a bit since the 2018-03-09 commit, with a new typedef
implementation.) I did not include the import related changes either.
Original commit:
"Initial implementation of enum, typedef, import.  Still a WIP."
881833aa73
			
			
This commit is contained in:
		
							parent
							
								
									2bda51ac34
								
							
						
					
					
						commit
						16ea4ea61a
					
				
					 5 changed files with 207 additions and 17 deletions
				
			
		| 
						 | 
					@ -88,6 +88,8 @@ std::string AST::type2str(AstNodeType type)
 | 
				
			||||||
	X(AST_LIVE)
 | 
						X(AST_LIVE)
 | 
				
			||||||
	X(AST_FAIR)
 | 
						X(AST_FAIR)
 | 
				
			||||||
	X(AST_COVER)
 | 
						X(AST_COVER)
 | 
				
			||||||
 | 
						X(AST_ENUM)
 | 
				
			||||||
 | 
						X(AST_ENUM_ITEM)
 | 
				
			||||||
	X(AST_FCALL)
 | 
						X(AST_FCALL)
 | 
				
			||||||
	X(AST_TO_BITS)
 | 
						X(AST_TO_BITS)
 | 
				
			||||||
	X(AST_TO_SIGNED)
 | 
						X(AST_TO_SIGNED)
 | 
				
			||||||
| 
						 | 
					@ -202,6 +204,7 @@ AstNode::AstNode(AstNodeType type, AstNode *child1, AstNode *child2, AstNode *ch
 | 
				
			||||||
	is_logic = false;
 | 
						is_logic = false;
 | 
				
			||||||
	is_signed = false;
 | 
						is_signed = false;
 | 
				
			||||||
	is_string = false;
 | 
						is_string = false;
 | 
				
			||||||
 | 
						is_enum = false;
 | 
				
			||||||
	is_wand = false;
 | 
						is_wand = false;
 | 
				
			||||||
	is_wor = false;
 | 
						is_wor = false;
 | 
				
			||||||
	is_unsized = false;
 | 
						is_unsized = false;
 | 
				
			||||||
| 
						 | 
					@ -321,6 +324,9 @@ void AstNode::dumpAst(FILE *f, std::string indent) const
 | 
				
			||||||
			fprintf(f, " %d", v);
 | 
								fprintf(f, " %d", v);
 | 
				
			||||||
		fprintf(f, " ]");
 | 
							fprintf(f, " ]");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						if (is_enum) {
 | 
				
			||||||
 | 
							fprintf(f, " type=enum");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	fprintf(f, "\n");
 | 
						fprintf(f, "\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (auto &it : attributes) {
 | 
						for (auto &it : attributes) {
 | 
				
			||||||
| 
						 | 
					@ -1174,7 +1180,15 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump
 | 
				
			||||||
			for (auto n : design->verilog_packages){
 | 
								for (auto n : design->verilog_packages){
 | 
				
			||||||
				for (auto o : n->children) {
 | 
									for (auto o : n->children) {
 | 
				
			||||||
					AstNode *cloned_node = o->clone();
 | 
										AstNode *cloned_node = o->clone();
 | 
				
			||||||
					cloned_node->str = n->str + std::string("::") + cloned_node->str.substr(1);
 | 
										log("cloned node %s\n", type2str(cloned_node->type).c_str());
 | 
				
			||||||
 | 
										if (cloned_node->type == AST_ENUM){
 | 
				
			||||||
 | 
											for (auto e : cloned_node->children){
 | 
				
			||||||
 | 
												log_assert(e->type == AST_ENUM_ITEM);
 | 
				
			||||||
 | 
												e->str = n->str + std::string("::") + e->str.substr(1);
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										} else {
 | 
				
			||||||
 | 
											cloned_node->str = n->str + std::string("::") + cloned_node->str.substr(1);
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
					(*it)->children.push_back(cloned_node);
 | 
										(*it)->children.push_back(cloned_node);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
| 
						 | 
					@ -1203,10 +1217,13 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			design->add(process_module(*it, defer));
 | 
								design->add(process_module(*it, defer));
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		else if ((*it)->type == AST_PACKAGE)
 | 
							else if ((*it)->type == AST_PACKAGE) {
 | 
				
			||||||
			design->verilog_packages.push_back((*it)->clone());
 | 
								design->verilog_packages.push_back((*it)->clone());
 | 
				
			||||||
		else
 | 
							}
 | 
				
			||||||
 | 
							else {
 | 
				
			||||||
 | 
								// must be global definition
 | 
				
			||||||
			design->verilog_globals.push_back((*it)->clone());
 | 
								design->verilog_globals.push_back((*it)->clone());
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -68,6 +68,8 @@ namespace AST
 | 
				
			||||||
		AST_LIVE,
 | 
							AST_LIVE,
 | 
				
			||||||
		AST_FAIR,
 | 
							AST_FAIR,
 | 
				
			||||||
		AST_COVER,
 | 
							AST_COVER,
 | 
				
			||||||
 | 
							AST_ENUM,
 | 
				
			||||||
 | 
							AST_ENUM_ITEM,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		AST_FCALL,
 | 
							AST_FCALL,
 | 
				
			||||||
		AST_TO_BITS,
 | 
							AST_TO_BITS,
 | 
				
			||||||
| 
						 | 
					@ -181,6 +183,8 @@ namespace AST
 | 
				
			||||||
		int port_id, range_left, range_right;
 | 
							int port_id, range_left, range_right;
 | 
				
			||||||
		uint32_t integer;
 | 
							uint32_t integer;
 | 
				
			||||||
		double realvalue;
 | 
							double realvalue;
 | 
				
			||||||
 | 
							// set for IDs typed to an enumeration, not used
 | 
				
			||||||
 | 
							bool is_enum;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// if this is a multirange memory then this vector contains offset and length of each dimension
 | 
							// if this is a multirange memory then this vector contains offset and length of each dimension
 | 
				
			||||||
		std::vector<int> multirange_dimensions;
 | 
							std::vector<int> multirange_dimensions;
 | 
				
			||||||
| 
						 | 
					@ -285,6 +289,9 @@ namespace AST
 | 
				
			||||||
		int isConst() const; // return '1' for AST_CONSTANT and '2' for AST_REALVALUE
 | 
							int isConst() const; // return '1' for AST_CONSTANT and '2' for AST_REALVALUE
 | 
				
			||||||
		double asReal(bool is_signed);
 | 
							double asReal(bool is_signed);
 | 
				
			||||||
		RTLIL::Const realAsConst(int width);
 | 
							RTLIL::Const realAsConst(int width);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// helpers for enum
 | 
				
			||||||
 | 
							void allocateDefaultEnumValues();
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// process an AST tree (ast must point to an AST_DESIGN node) and generate RTLIL code
 | 
						// process an AST tree (ast must point to an AST_DESIGN node) and generate RTLIL code
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -595,6 +595,9 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch (type)
 | 
						switch (type)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
 | 
						case AST_NONE:
 | 
				
			||||||
 | 
							// unallocated enum, ignore
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
	case AST_CONSTANT:
 | 
						case AST_CONSTANT:
 | 
				
			||||||
		width_hint = max(width_hint, int(bits.size()));
 | 
							width_hint = max(width_hint, int(bits.size()));
 | 
				
			||||||
		if (!is_signed)
 | 
							if (!is_signed)
 | 
				
			||||||
| 
						 | 
					@ -612,7 +615,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
 | 
				
			||||||
			id_ast = current_scope.at(str);
 | 
								id_ast = current_scope.at(str);
 | 
				
			||||||
		if (!id_ast)
 | 
							if (!id_ast)
 | 
				
			||||||
			log_file_error(filename, linenum, "Failed to resolve identifier %s for width detection!\n", str.c_str());
 | 
								log_file_error(filename, linenum, "Failed to resolve identifier %s for width detection!\n", str.c_str());
 | 
				
			||||||
		if (id_ast->type == AST_PARAMETER || id_ast->type == AST_LOCALPARAM) {
 | 
							if (id_ast->type == AST_PARAMETER || id_ast->type == AST_LOCALPARAM || id_ast->type == AST_ENUM_ITEM) {
 | 
				
			||||||
			if (id_ast->children.size() > 1 && id_ast->children[1]->range_valid) {
 | 
								if (id_ast->children.size() > 1 && id_ast->children[1]->range_valid) {
 | 
				
			||||||
				this_width = id_ast->children[1]->range_left - id_ast->children[1]->range_right + 1;
 | 
									this_width = id_ast->children[1]->range_left - id_ast->children[1]->range_right + 1;
 | 
				
			||||||
			} else
 | 
								} else
 | 
				
			||||||
| 
						 | 
					@ -861,6 +864,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
 | 
				
			||||||
	case AST_GENIF:
 | 
						case AST_GENIF:
 | 
				
			||||||
	case AST_GENCASE:
 | 
						case AST_GENCASE:
 | 
				
			||||||
	case AST_PACKAGE:
 | 
						case AST_PACKAGE:
 | 
				
			||||||
 | 
						case AST_ENUM:
 | 
				
			||||||
	case AST_MODPORT:
 | 
						case AST_MODPORT:
 | 
				
			||||||
	case AST_MODPORTMEMBER:
 | 
						case AST_MODPORTMEMBER:
 | 
				
			||||||
	case AST_TYPEDEF:
 | 
						case AST_TYPEDEF:
 | 
				
			||||||
| 
						 | 
					@ -1022,7 +1026,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
 | 
				
			||||||
				else
 | 
									else
 | 
				
			||||||
					log_file_error(filename, linenum, "Identifier `%s' is implicitly declared and `default_nettype is set to none.\n", str.c_str());
 | 
										log_file_error(filename, linenum, "Identifier `%s' is implicitly declared and `default_nettype is set to none.\n", str.c_str());
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			else if (id2ast->type == AST_PARAMETER || id2ast->type == AST_LOCALPARAM) {
 | 
								else if (id2ast->type == AST_PARAMETER || id2ast->type == AST_LOCALPARAM || id2ast->type == AST_ENUM_ITEM) {
 | 
				
			||||||
				if (id2ast->children[0]->type != AST_CONSTANT)
 | 
									if (id2ast->children[0]->type != AST_CONSTANT)
 | 
				
			||||||
					log_file_error(filename, linenum, "Parameter %s does not evaluate to constant value!\n", str.c_str());
 | 
										log_file_error(filename, linenum, "Parameter %s does not evaluate to constant value!\n", str.c_str());
 | 
				
			||||||
				chunk = RTLIL::Const(id2ast->children[0]->bits);
 | 
									chunk = RTLIL::Const(id2ast->children[0]->bits);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -318,13 +318,13 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// activate const folding if this is anything that must be evaluated statically (ranges, parameters, attributes, etc.)
 | 
						// activate const folding if this is anything that must be evaluated statically (ranges, parameters, attributes, etc.)
 | 
				
			||||||
	if (type == AST_WIRE || type == AST_PARAMETER || type == AST_LOCALPARAM || type == AST_DEFPARAM || type == AST_PARASET || type == AST_RANGE || type == AST_PREFIX || type == AST_TYPEDEF)
 | 
						if (type == AST_WIRE || type == AST_PARAMETER || type == AST_LOCALPARAM || type == AST_ENUM_ITEM || type == AST_DEFPARAM || type == AST_PARASET || type == AST_RANGE || type == AST_PREFIX || type == AST_TYPEDEF)
 | 
				
			||||||
		const_fold = true;
 | 
							const_fold = true;
 | 
				
			||||||
	if (type == AST_IDENTIFIER && current_scope.count(str) > 0 && (current_scope[str]->type == AST_PARAMETER || current_scope[str]->type == AST_LOCALPARAM))
 | 
						if (type == AST_IDENTIFIER && current_scope.count(str) > 0 && (current_scope[str]->type == AST_PARAMETER || current_scope[str]->type == AST_LOCALPARAM || current_scope[str]->type == AST_ENUM_ITEM))
 | 
				
			||||||
		const_fold = true;
 | 
							const_fold = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// in certain cases a function must be evaluated constant. this is what in_param controls.
 | 
						// in certain cases a function must be evaluated constant. this is what in_param controls.
 | 
				
			||||||
	if (type == AST_PARAMETER || type == AST_LOCALPARAM || type == AST_DEFPARAM || type == AST_PARASET || type == AST_PREFIX)
 | 
						if (type == AST_PARAMETER || type == AST_LOCALPARAM || type == AST_LOCALPARAM || type == AST_ENUM_ITEM || type == AST_DEFPARAM || type == AST_PARASET || type == AST_PREFIX)
 | 
				
			||||||
		in_param = true;
 | 
							in_param = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	std::map<std::string, AstNode*> backup_scope;
 | 
						std::map<std::string, AstNode*> backup_scope;
 | 
				
			||||||
| 
						 | 
					@ -405,12 +405,23 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				this_wire_scope[node->str] = node;
 | 
									this_wire_scope[node->str] = node;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								// these nodes appear at the top level in a module and can define names
 | 
				
			||||||
			if (node->type == AST_PARAMETER || node->type == AST_LOCALPARAM || node->type == AST_WIRE || node->type == AST_AUTOWIRE || node->type == AST_GENVAR ||
 | 
								if (node->type == AST_PARAMETER || node->type == AST_LOCALPARAM || node->type == AST_WIRE || node->type == AST_AUTOWIRE || node->type == AST_GENVAR ||
 | 
				
			||||||
					node->type == AST_MEMORY || node->type == AST_FUNCTION || node->type == AST_TASK || node->type == AST_DPI_FUNCTION || node->type == AST_CELL ||
 | 
										node->type == AST_MEMORY || node->type == AST_FUNCTION || node->type == AST_TASK || node->type == AST_DPI_FUNCTION || node->type == AST_CELL ||
 | 
				
			||||||
					node->type == AST_TYPEDEF) {
 | 
										node->type == AST_TYPEDEF) {
 | 
				
			||||||
				backup_scope[node->str] = current_scope[node->str];
 | 
									backup_scope[node->str] = current_scope[node->str];
 | 
				
			||||||
				current_scope[node->str] = node;
 | 
									current_scope[node->str] = node;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								if (node->type == AST_ENUM) {
 | 
				
			||||||
 | 
									for (auto enode : node->children) {
 | 
				
			||||||
 | 
										log_assert(enode->type==AST_ENUM_ITEM);
 | 
				
			||||||
 | 
										if (current_scope.count(enode->str) == 0) {
 | 
				
			||||||
 | 
											current_scope[enode->str] = enode;
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										//	while (enode->simplify(true, false, false, 1, -1, false, true))
 | 
				
			||||||
 | 
										//		did_something = true;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		for (size_t i = 0; i < children.size(); i++) {
 | 
							for (size_t i = 0; i < children.size(); i++) {
 | 
				
			||||||
			AstNode *node = children[i];
 | 
								AstNode *node = children[i];
 | 
				
			||||||
| 
						 | 
					@ -492,8 +503,21 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case AST_ENUM:
 | 
				
			||||||
 | 
							// log("\nENUM %d child %d\n", basic_prep, children[0]->basic_prep);
 | 
				
			||||||
 | 
							if (!basic_prep) {
 | 
				
			||||||
 | 
								for (auto item_node : children) {
 | 
				
			||||||
 | 
									while (!item_node->basic_prep && item_node->simplify(false, false, false, stage, -1, false, true) == true)
 | 
				
			||||||
 | 
										did_something = true;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								// allocate values (called more than once)
 | 
				
			||||||
 | 
								allocateDefaultEnumValues();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	case AST_PARAMETER:
 | 
						case AST_PARAMETER:
 | 
				
			||||||
	case AST_LOCALPARAM:
 | 
						case AST_LOCALPARAM:
 | 
				
			||||||
 | 
						case AST_ENUM_ITEM:
 | 
				
			||||||
		while (!children[0]->basic_prep && children[0]->simplify(false, false, false, stage, -1, false, true) == true)
 | 
							while (!children[0]->basic_prep && children[0]->simplify(false, false, false, stage, -1, false, true) == true)
 | 
				
			||||||
			did_something = true;
 | 
								did_something = true;
 | 
				
			||||||
		children[0]->detectSignWidth(width_hint, sign_hint);
 | 
							children[0]->detectSignWidth(width_hint, sign_hint);
 | 
				
			||||||
| 
						 | 
					@ -826,7 +850,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
 | 
				
			||||||
			// Insert clones children from template at beginning
 | 
								// Insert clones children from template at beginning
 | 
				
			||||||
			for (int i  = 0; i < GetSize(templ->children); i++)
 | 
								for (int i  = 0; i < GetSize(templ->children); i++)
 | 
				
			||||||
				children.insert(children.begin() + i, templ->children[i]->clone());
 | 
									children.insert(children.begin() + i, templ->children[i]->clone());
 | 
				
			||||||
			
 | 
					
 | 
				
			||||||
			if (type == AST_MEMORY && GetSize(children) == 1) {
 | 
								if (type == AST_MEMORY && GetSize(children) == 1) {
 | 
				
			||||||
				// Single-bit memories must have [0:0] range
 | 
									// Single-bit memories must have [0:0] range
 | 
				
			||||||
				AstNode *rng = new AstNode(AST_RANGE);
 | 
									AstNode *rng = new AstNode(AST_RANGE);
 | 
				
			||||||
| 
						 | 
					@ -873,7 +897,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
 | 
				
			||||||
			did_something = true;
 | 
								did_something = true;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		log_assert(!is_custom_type);
 | 
							log_assert(!is_custom_type);
 | 
				
			||||||
	}	
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// resolve constant prefixes
 | 
						// resolve constant prefixes
 | 
				
			||||||
	if (type == AST_PREFIX) {
 | 
						if (type == AST_PREFIX) {
 | 
				
			||||||
| 
						 | 
					@ -1005,7 +1029,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// trim/extend parameters
 | 
						// trim/extend parameters
 | 
				
			||||||
	if (type == AST_PARAMETER || type == AST_LOCALPARAM) {
 | 
						if (type == AST_PARAMETER || type == AST_LOCALPARAM || type == AST_ENUM_ITEM) {
 | 
				
			||||||
		if (children.size() > 1 && children[1]->type == AST_RANGE) {
 | 
							if (children.size() > 1 && children[1]->type == AST_RANGE) {
 | 
				
			||||||
			if (!children[1]->range_valid)
 | 
								if (!children[1]->range_valid)
 | 
				
			||||||
				log_file_error(filename, linenum, "Non-constant width range on parameter decl.\n");
 | 
									log_file_error(filename, linenum, "Non-constant width range on parameter decl.\n");
 | 
				
			||||||
| 
						 | 
					@ -1046,10 +1070,32 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
 | 
				
			||||||
	if (type == AST_IDENTIFIER) {
 | 
						if (type == AST_IDENTIFIER) {
 | 
				
			||||||
		if (current_scope.count(str) == 0) {
 | 
							if (current_scope.count(str) == 0) {
 | 
				
			||||||
			for (auto node : current_ast_mod->children) {
 | 
								for (auto node : current_ast_mod->children) {
 | 
				
			||||||
				if ((node->type == AST_PARAMETER || node->type == AST_LOCALPARAM || node->type == AST_WIRE || node->type == AST_AUTOWIRE || node->type == AST_GENVAR ||
 | 
									//log("looking at mod scope child %s\n", type2str(node->type).c_str());
 | 
				
			||||||
						node->type == AST_MEMORY || node->type == AST_FUNCTION || node->type == AST_TASK || node->type == AST_DPI_FUNCTION) && str == node->str) {
 | 
									switch (node->type) {
 | 
				
			||||||
 | 
									case AST_PARAMETER:
 | 
				
			||||||
 | 
									case AST_LOCALPARAM:
 | 
				
			||||||
 | 
									case AST_WIRE:
 | 
				
			||||||
 | 
									case AST_AUTOWIRE:
 | 
				
			||||||
 | 
									case AST_GENVAR:
 | 
				
			||||||
 | 
									case AST_MEMORY:
 | 
				
			||||||
 | 
									case AST_FUNCTION:
 | 
				
			||||||
 | 
									case AST_TASK:
 | 
				
			||||||
 | 
									case AST_DPI_FUNCTION:
 | 
				
			||||||
 | 
										//log("found child %s, %s\n", type2str(node->type).c_str(), node->str.c_str());
 | 
				
			||||||
 | 
										log("add %s, type %s to scope\n", str.c_str(), type2str(node->type).c_str());
 | 
				
			||||||
					current_scope[node->str] = node;
 | 
										current_scope[node->str] = node;
 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
 | 
									case AST_ENUM:
 | 
				
			||||||
 | 
										for (auto enum_node : node->children) {
 | 
				
			||||||
 | 
											log_assert(enum_node->type==AST_ENUM_ITEM);
 | 
				
			||||||
 | 
											if (str == enum_node->str) {
 | 
				
			||||||
 | 
												log("\nadding enum %s to scope\n", str.c_str());
 | 
				
			||||||
 | 
												current_scope[str] = enum_node;
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										break;
 | 
				
			||||||
 | 
									default:
 | 
				
			||||||
 | 
										break;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -2482,7 +2528,7 @@ skip_dynamic_range_lvalue_expansion:;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for (auto child : decl->children)
 | 
							for (auto child : decl->children)
 | 
				
			||||||
			if (child->type == AST_WIRE || child->type == AST_MEMORY || child->type == AST_PARAMETER || child->type == AST_LOCALPARAM)
 | 
								if (child->type == AST_WIRE || child->type == AST_MEMORY || child->type == AST_PARAMETER || child->type == AST_LOCALPARAM || child->type == AST_ENUM_ITEM)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				AstNode *wire = nullptr;
 | 
									AstNode *wire = nullptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2588,7 +2634,7 @@ replace_fcall_later:;
 | 
				
			||||||
		switch (type)
 | 
							switch (type)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
		case AST_IDENTIFIER:
 | 
							case AST_IDENTIFIER:
 | 
				
			||||||
			if (current_scope.count(str) > 0 && (current_scope[str]->type == AST_PARAMETER || current_scope[str]->type == AST_LOCALPARAM)) {
 | 
								if (current_scope.count(str) > 0 && (current_scope[str]->type == AST_PARAMETER || current_scope[str]->type == AST_LOCALPARAM || current_scope[str]->type == AST_ENUM_ITEM)) {
 | 
				
			||||||
				if (current_scope[str]->children[0]->type == AST_CONSTANT) {
 | 
									if (current_scope[str]->children[0]->type == AST_CONSTANT) {
 | 
				
			||||||
					if (children.size() != 0 && children[0]->type == AST_RANGE && children[0]->range_valid) {
 | 
										if (children.size() != 0 && children[0]->type == AST_RANGE && children[0]->range_valid) {
 | 
				
			||||||
						std::vector<RTLIL::State> data;
 | 
											std::vector<RTLIL::State> data;
 | 
				
			||||||
| 
						 | 
					@ -3025,7 +3071,7 @@ void AstNode::expand_genblock(std::string index_var, std::string prefix, std::ma
 | 
				
			||||||
	for (size_t i = 0; i < children.size(); i++) {
 | 
						for (size_t i = 0; i < children.size(); i++) {
 | 
				
			||||||
		AstNode *child = children[i];
 | 
							AstNode *child = children[i];
 | 
				
			||||||
		if (child->type == AST_WIRE || child->type == AST_MEMORY || child->type == AST_PARAMETER || child->type == AST_LOCALPARAM ||
 | 
							if (child->type == AST_WIRE || child->type == AST_MEMORY || child->type == AST_PARAMETER || child->type == AST_LOCALPARAM ||
 | 
				
			||||||
				child->type == AST_FUNCTION || child->type == AST_TASK || child->type == AST_CELL || child->type == AST_TYPEDEF) {
 | 
									child->type == AST_FUNCTION || child->type == AST_TASK || child->type == AST_CELL || child->type == AST_TYPEDEF || child->type == AST_ENUM_ITEM) {
 | 
				
			||||||
			if (backup_name_map.size() == 0)
 | 
								if (backup_name_map.size() == 0)
 | 
				
			||||||
				backup_name_map = name_map;
 | 
									backup_name_map = name_map;
 | 
				
			||||||
			std::string new_name = prefix[0] == '\\' ? prefix.substr(1) : prefix;
 | 
								std::string new_name = prefix[0] == '\\' ? prefix.substr(1) : prefix;
 | 
				
			||||||
| 
						 | 
					@ -3782,4 +3828,31 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
 | 
				
			||||||
	return AstNode::mkconst_bits(variables.at(str).val.bits, variables.at(str).is_signed);
 | 
						return AstNode::mkconst_bits(variables.at(str).val.bits, variables.at(str).is_signed);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void AstNode::allocateDefaultEnumValues()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						log_assert(type==AST_ENUM);
 | 
				
			||||||
 | 
						int last_enum_int = -1;
 | 
				
			||||||
 | 
						for (auto node : children) {
 | 
				
			||||||
 | 
							log_assert(node->type==AST_ENUM_ITEM);
 | 
				
			||||||
 | 
							for (size_t i = 0; i < node->children.size(); i++) {
 | 
				
			||||||
 | 
								switch (node->children[i]->type) {
 | 
				
			||||||
 | 
								case AST_NONE:
 | 
				
			||||||
 | 
									// replace with auto-incremented constant
 | 
				
			||||||
 | 
									delete node->children[i];
 | 
				
			||||||
 | 
									node->children[i] = AstNode::mkconst_int(++last_enum_int, true);
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								case AST_CONSTANT:
 | 
				
			||||||
 | 
									// explicit constant (or folded expression)
 | 
				
			||||||
 | 
									// TODO: can't extend 'x or 'z item
 | 
				
			||||||
 | 
									last_enum_int = node->children[i]->integer;
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								default:
 | 
				
			||||||
 | 
									// ignore ranges
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								// TODO: range check
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
YOSYS_NAMESPACE_END
 | 
					YOSYS_NAMESPACE_END
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -108,6 +108,20 @@ struct specify_rise_fall {
 | 
				
			||||||
	specify_triple fall;
 | 
						specify_triple fall;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static AstNode *makeRange(int msb = 31, int lsb = 0, bool isSigned = true)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						auto range = new AstNode(AST_RANGE);
 | 
				
			||||||
 | 
						range->children.push_back(AstNode::mkconst_int(msb, true));
 | 
				
			||||||
 | 
						range->children.push_back(AstNode::mkconst_int(lsb, true));
 | 
				
			||||||
 | 
						range->is_signed = isSigned;
 | 
				
			||||||
 | 
						return range;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void addRange(AstNode *parent, int msb = 31, int lsb = 0, bool isSigned = true)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						auto range = makeRange(msb, lsb, isSigned);
 | 
				
			||||||
 | 
						parent->children.push_back(range);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
%}
 | 
					%}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
%define api.prefix {frontend_verilog_yy}
 | 
					%define api.prefix {frontend_verilog_yy}
 | 
				
			||||||
| 
						 | 
					@ -157,6 +171,7 @@ struct specify_rise_fall {
 | 
				
			||||||
%type <ast> range range_or_multirange  non_opt_range non_opt_multirange range_or_signed_int
 | 
					%type <ast> range range_or_multirange  non_opt_range non_opt_multirange range_or_signed_int
 | 
				
			||||||
%type <ast> wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list
 | 
					%type <ast> wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list
 | 
				
			||||||
%type <string> opt_label opt_sva_label tok_prim_wrapper hierarchical_id hierarchical_type_id
 | 
					%type <string> opt_label opt_sva_label tok_prim_wrapper hierarchical_id hierarchical_type_id
 | 
				
			||||||
 | 
					%type <ast> opt_enum_init
 | 
				
			||||||
%type <boolean> opt_signed opt_property unique_case_attr always_comb_or_latch always_or_always_ff
 | 
					%type <boolean> opt_signed opt_property unique_case_attr always_comb_or_latch always_or_always_ff
 | 
				
			||||||
%type <al> attr case_attr
 | 
					%type <al> attr case_attr
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -428,7 +443,9 @@ package:
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package_body:
 | 
					package_body:
 | 
				
			||||||
	package_body package_body_stmt |;
 | 
						package_body package_body_stmt
 | 
				
			||||||
 | 
						| // optional
 | 
				
			||||||
 | 
						;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package_body_stmt:
 | 
					package_body_stmt:
 | 
				
			||||||
	typedef_decl |
 | 
						typedef_decl |
 | 
				
			||||||
| 
						 | 
					@ -604,6 +621,7 @@ module_body:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module_body_stmt:
 | 
					module_body_stmt:
 | 
				
			||||||
	task_func_decl | specify_block | param_decl | localparam_decl | typedef_decl | defparam_decl | specparam_declaration | wire_decl | assign_stmt | cell_stmt |
 | 
						task_func_decl | specify_block | param_decl | localparam_decl | typedef_decl | defparam_decl | specparam_declaration | wire_decl | assign_stmt | cell_stmt |
 | 
				
			||||||
 | 
						enum_decl |
 | 
				
			||||||
	always_stmt | TOK_GENERATE module_gen_body TOK_ENDGENERATE | defattr | assert_property | checker_decl | ignored_specify_block;
 | 
						always_stmt | TOK_GENERATE module_gen_body TOK_ENDGENERATE | defattr | assert_property | checker_decl | ignored_specify_block;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
checker_decl:
 | 
					checker_decl:
 | 
				
			||||||
| 
						 | 
					@ -1224,6 +1242,77 @@ single_defparam_decl:
 | 
				
			||||||
		ast_stack.back()->children.push_back(node);
 | 
							ast_stack.back()->children.push_back(node);
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum_type: TOK_ENUM {
 | 
				
			||||||
 | 
							// create parent node for the enum
 | 
				
			||||||
 | 
							astbuf2 = new AstNode(AST_ENUM);
 | 
				
			||||||
 | 
							ast_stack.back()->children.push_back(astbuf2);
 | 
				
			||||||
 | 
							// create the template for the names
 | 
				
			||||||
 | 
							astbuf1 = new AstNode(AST_ENUM_ITEM);
 | 
				
			||||||
 | 
							astbuf1->children.push_back(AstNode::mkconst_int(0, true));
 | 
				
			||||||
 | 
						 } param_signed enum_base_type '{' enum_name_list '}' {  // create template for the enum vars
 | 
				
			||||||
 | 
													auto tnode = astbuf1->clone();
 | 
				
			||||||
 | 
													delete astbuf1;
 | 
				
			||||||
 | 
													astbuf1 = tnode;
 | 
				
			||||||
 | 
													tnode->type = AST_WIRE;
 | 
				
			||||||
 | 
													// drop constant but keep any range
 | 
				
			||||||
 | 
													delete tnode->children[0];
 | 
				
			||||||
 | 
													tnode->children.erase(tnode->children.begin()); }
 | 
				
			||||||
 | 
						 ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum_base_type: int_vec param_range
 | 
				
			||||||
 | 
						| int_atom
 | 
				
			||||||
 | 
						| /* nothing */		{ addRange(astbuf1); }
 | 
				
			||||||
 | 
						;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int_atom: TOK_INTEGER		{ addRange(astbuf1); }		// probably should do byte, range [7:0] here
 | 
				
			||||||
 | 
						;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int_vec: TOK_REG		{ astbuf1->is_reg = true; }	// lexer returns this for logic|bit too
 | 
				
			||||||
 | 
						;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum_name_list:
 | 
				
			||||||
 | 
						enum_name_decl
 | 
				
			||||||
 | 
						| enum_name_list ',' enum_name_decl
 | 
				
			||||||
 | 
						;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum_name_decl:
 | 
				
			||||||
 | 
						TOK_ID opt_enum_init {
 | 
				
			||||||
 | 
							// put in fn
 | 
				
			||||||
 | 
							log_assert(astbuf1);
 | 
				
			||||||
 | 
							log_assert(astbuf2);
 | 
				
			||||||
 | 
							auto node = astbuf1->clone();
 | 
				
			||||||
 | 
							node->str = *$1;
 | 
				
			||||||
 | 
							delete $1;
 | 
				
			||||||
 | 
							delete node->children[0];
 | 
				
			||||||
 | 
							node->children[0] = $2 ?: new AstNode(AST_NONE);
 | 
				
			||||||
 | 
							astbuf2->children.push_back(node);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					opt_enum_init:
 | 
				
			||||||
 | 
						'=' basic_expr		{ $$ = $2; }	// TODO: restrict this
 | 
				
			||||||
 | 
						| /* optional */	{ $$ = NULL; }
 | 
				
			||||||
 | 
						;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum_var_list:
 | 
				
			||||||
 | 
						enum_var
 | 
				
			||||||
 | 
						| enum_var_list ',' enum_var
 | 
				
			||||||
 | 
						;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum_var: TOK_ID {
 | 
				
			||||||
 | 
							log_assert(astbuf1);
 | 
				
			||||||
 | 
							log_assert(astbuf2);
 | 
				
			||||||
 | 
							auto node = astbuf1->clone();
 | 
				
			||||||
 | 
							ast_stack.back()->children.push_back(node);
 | 
				
			||||||
 | 
							node->str = *$1;
 | 
				
			||||||
 | 
							delete $1;
 | 
				
			||||||
 | 
							node->is_enum = true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum_decl: enum_type enum_var_list ';'			{ delete astbuf1; }
 | 
				
			||||||
 | 
						;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
wire_decl:
 | 
					wire_decl:
 | 
				
			||||||
	attr wire_type range {
 | 
						attr wire_type range {
 | 
				
			||||||
		albuf = $1;
 | 
							albuf = $1;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue