diff options
Diffstat (limited to 'frontends/ast')
| -rw-r--r-- | frontends/ast/ast.cc | 6 | ||||
| -rw-r--r-- | frontends/ast/ast.h | 3 | ||||
| -rw-r--r-- | frontends/ast/genrtlil.cc | 60 | ||||
| -rw-r--r-- | frontends/ast/simplify.cc | 113 | 
4 files changed, 135 insertions, 47 deletions
| diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 6a9af3f57..689fa9fb4 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -94,6 +94,7 @@ std::string AST::type2str(AstNodeType type)  	X(AST_TO_BITS)  	X(AST_TO_SIGNED)  	X(AST_TO_UNSIGNED) +	X(AST_SELFSZ)  	X(AST_CONCAT)  	X(AST_REPLICATE)  	X(AST_BIT_NOT) @@ -110,6 +111,8 @@ std::string AST::type2str(AstNodeType type)  	X(AST_SHIFT_RIGHT)  	X(AST_SHIFT_SLEFT)  	X(AST_SHIFT_SRIGHT) +	X(AST_SHIFTX) +	X(AST_SHIFT)  	X(AST_LT)  	X(AST_LE)  	X(AST_EQ) @@ -615,6 +618,7 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const  	if (0) { case AST_POS:         txt = "+";  }  	if (0) { case AST_NEG:         txt = "-";  }  	if (0) { case AST_LOGIC_NOT:   txt = "!";  } +	if (0) { case AST_SELFSZ:      txt = "@selfsz@";  }  		fprintf(f, "%s(", txt.c_str());  		children[0]->dumpVlog(f, "");  		fprintf(f, ")"); @@ -628,6 +632,8 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const  	if (0) { case AST_SHIFT_RIGHT:  txt = ">>";  }  	if (0) { case AST_SHIFT_SLEFT:  txt = "<<<"; }  	if (0) { case AST_SHIFT_SRIGHT: txt = ">>>"; } +	if (0) { case AST_SHIFTX:       txt = "@shiftx@"; } +	if (0) { case AST_SHIFT:        txt = "@shift@"; }  	if (0) { case AST_LT:           txt = "<";   }  	if (0) { case AST_LE:           txt = "<=";  }  	if (0) { case AST_EQ:           txt = "==";  } diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index 3f6329112..8932108e3 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -75,6 +75,7 @@ namespace AST  		AST_TO_BITS,  		AST_TO_SIGNED,  		AST_TO_UNSIGNED, +		AST_SELFSZ,  		AST_CONCAT,  		AST_REPLICATE,  		AST_BIT_NOT, @@ -91,6 +92,8 @@ namespace AST  		AST_SHIFT_RIGHT,  		AST_SHIFT_SLEFT,  		AST_SHIFT_SRIGHT, +		AST_SHIFTX, +		AST_SHIFT,  		AST_LT,  		AST_LE,  		AST_EQ, diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index d35335747..cdc3adc9c 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -43,12 +43,12 @@ using namespace AST_INTERNAL;  // helper function for creating RTLIL code for unary operations  static RTLIL::SigSpec uniop2rtlil(AstNode *that, IdString type, int result_width, const RTLIL::SigSpec &arg, bool gen_attributes = true)  { -        IdString name = stringf("%s$%s:%d$%d", type.c_str(), that->filename.c_str(), that->location.first_line, autoidx++); +	IdString name = stringf("%s$%s:%d$%d", type.c_str(), that->filename.c_str(), that->location.first_line, autoidx++);  	RTLIL::Cell *cell = current_module->addCell(name, type); -	cell->attributes[ID::src] = stringf("%s:%d", that->filename.c_str(), that->location.first_line); +	cell->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", that->filename.c_str(), that->location.first_line, that->location.first_column, that->location.last_line, that->location.last_column);  	RTLIL::Wire *wire = current_module->addWire(cell->name.str() + "_Y", result_width); -	wire->attributes[ID::src] = stringf("%s:%d", that->filename.c_str(), that->location.first_line); +	wire->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", that->filename.c_str(), that->location.first_line, that->location.first_column, that->location.last_line, that->location.last_column);  	if (gen_attributes)  		for (auto &attr : that->attributes) { @@ -74,12 +74,12 @@ static void widthExtend(AstNode *that, RTLIL::SigSpec &sig, int width, bool is_s  		return;  	} -        IdString name = stringf("$extend$%s:%d$%d", that->filename.c_str(), that->location.first_line, autoidx++); +	IdString name = stringf("$extend$%s:%d$%d", that->filename.c_str(), that->location.first_line, autoidx++);  	RTLIL::Cell *cell = current_module->addCell(name, ID($pos)); -	cell->attributes[ID::src] = stringf("%s:%d", that->filename.c_str(), that->location.first_line); +	cell->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", that->filename.c_str(), that->location.first_line, that->location.first_column, that->location.last_line, that->location.last_column);  	RTLIL::Wire *wire = current_module->addWire(cell->name.str() + "_Y", width); -	wire->attributes[ID::src] = stringf("%s:%d", that->filename.c_str(), that->location.first_line); +	wire->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", that->filename.c_str(), that->location.first_line, that->location.first_column, that->location.last_line, that->location.last_column);  	if (that != NULL)  		for (auto &attr : that->attributes) { @@ -100,12 +100,12 @@ static void widthExtend(AstNode *that, RTLIL::SigSpec &sig, int width, bool is_s  // helper function for creating RTLIL code for binary operations  static RTLIL::SigSpec binop2rtlil(AstNode *that, IdString type, int result_width, const RTLIL::SigSpec &left, const RTLIL::SigSpec &right)  { -        IdString name = stringf("%s$%s:%d$%d", type.c_str(), that->filename.c_str(), that->location.first_line, autoidx++); +	IdString name = stringf("%s$%s:%d$%d", type.c_str(), that->filename.c_str(), that->location.first_line, autoidx++);  	RTLIL::Cell *cell = current_module->addCell(name, type); -	cell->attributes[ID::src] = stringf("%s:%d", that->filename.c_str(), that->location.first_line); +	cell->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", that->filename.c_str(), that->location.first_line, that->location.first_column, that->location.last_line, that->location.last_column);  	RTLIL::Wire *wire = current_module->addWire(cell->name.str() + "_Y", result_width); -	wire->attributes[ID::src] = stringf("%s:%d", that->filename.c_str(), that->location.first_line); +	wire->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", that->filename.c_str(), that->location.first_line, that->location.first_column, that->location.last_line, that->location.last_column);  	for (auto &attr : that->attributes) {  		if (attr.second->type != AST_CONSTANT) @@ -136,10 +136,10 @@ static RTLIL::SigSpec mux2rtlil(AstNode *that, const RTLIL::SigSpec &cond, const  	sstr << "$ternary$" << that->filename << ":" << that->location.first_line << "$" << (autoidx++);  	RTLIL::Cell *cell = current_module->addCell(sstr.str(), ID($mux)); -	cell->attributes[ID::src] = stringf("%s:%d", that->filename.c_str(), that->location.first_line); +	cell->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", that->filename.c_str(), that->location.first_line, that->location.first_column, that->location.last_line, that->location.last_column);  	RTLIL::Wire *wire = current_module->addWire(cell->name.str() + "_Y", left.size()); -	wire->attributes[ID::src] = stringf("%s:%d", that->filename.c_str(), that->location.first_line); +	wire->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", that->filename.c_str(), that->location.first_line, that->location.first_column, that->location.last_line, that->location.last_column);  	for (auto &attr : that->attributes) {  		if (attr.second->type != AST_CONSTANT) @@ -171,7 +171,7 @@ struct AST_INTERNAL::LookaheadRewriter  				for (auto c : node->id2ast->children)  					wire->children.push_back(c->clone());  				wire->str = stringf("$lookahead%s$%d", node->str.c_str(), autoidx++); -				wire->attributes["\\nosync"] = AstNode::mkconst_int(1, false); +				wire->attributes[ID::nosync] = AstNode::mkconst_int(1, false);  				wire->is_logic = true;  				while (wire->simplify(true, false, false, 1, -1, false, false)) { }  				current_ast_mod->children.push_back(wire); @@ -809,6 +809,11 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun  		sign_hint = false;  		break; +	case AST_SELFSZ: +		sub_width_hint = 0; +		children.at(0)->detectSignWidthWorker(sub_width_hint, sign_hint); +		break; +  	case AST_CONCAT:  		for (auto child : children) {  			sub_width_hint = 0; @@ -856,6 +861,8 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun  	case AST_SHIFT_RIGHT:  	case AST_SHIFT_SLEFT:  	case AST_SHIFT_SRIGHT: +	case AST_SHIFTX: +	case AST_SHIFT:  	case AST_POW:  		children[0]->detectSignWidthWorker(width_hint, sign_hint, found_real);  		break; @@ -923,7 +930,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun  			}  			break;  		} -		/* fall through */ +		YS_FALLTHROUGH  	// everything should have been handled above -> print error if not.  	default: @@ -1019,7 +1026,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)  		if (GetSize(children) >= 1 && children[0]->type == AST_CONSTANT) {  			current_module->parameter_default_values[str] = children[0]->asParaConst();  		} -		/* fall through */ +		YS_FALLTHROUGH  	case AST_LOCALPARAM:  		if (flag_pwires)  		{ @@ -1048,7 +1055,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)  			if (!range_valid)  				log_file_error(filename, location.first_line, "Signal `%s' with non-constant width!\n", str.c_str()); -			if (!(range_left >= range_right || (range_left == -1 && range_right == 0))) +			if (!(range_left + 1 >= range_right))  				log_file_error(filename, location.first_line, "Signal `%s' with invalid width range %d!\n", str.c_str(), range_left - range_right + 1);  			RTLIL::Wire *wire = current_module->addWire(str, range_left - range_right + 1); @@ -1205,13 +1212,18 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)  					AstNode *fake_ast = new AstNode(AST_NONE, clone(), children[0]->children.size() >= 2 ?  							children[0]->children[1]->clone() : children[0]->children[0]->clone());  					fake_ast->children[0]->delete_children(); -					RTLIL::SigSpec shift_val = fake_ast->children[1]->genRTLIL(); + +					int fake_ast_width = 0; +					bool fake_ast_sign = true; +					fake_ast->children[1]->detectSignWidth(fake_ast_width, fake_ast_sign); +					RTLIL::SigSpec shift_val = fake_ast->children[1]->genRTLIL(fake_ast_width, fake_ast_sign); +  					if (id2ast->range_right != 0) { -						shift_val = current_module->Sub(NEW_ID, shift_val, id2ast->range_right, fake_ast->children[1]->is_signed); +						shift_val = current_module->Sub(NEW_ID, shift_val, id2ast->range_right, fake_ast_sign);  						fake_ast->children[1]->is_signed = true;  					}  					if (id2ast->range_swapped) { -						shift_val = current_module->Sub(NEW_ID, RTLIL::SigSpec(source_width - width), shift_val, fake_ast->children[1]->is_signed); +						shift_val = current_module->Sub(NEW_ID, RTLIL::SigSpec(source_width - width), shift_val, fake_ast_sign);  						fake_ast->children[1]->is_signed = true;  					}  					if (GetSize(shift_val) >= 32) @@ -1265,7 +1277,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)  	// just pass thru the signal. the parent will evaluate the is_signed property and interpret the SigSpec accordingly  	case AST_TO_SIGNED: -	case AST_TO_UNSIGNED: { +	case AST_TO_UNSIGNED: +	case AST_SELFSZ: {  			RTLIL::SigSpec sig = children[0]->genRTLIL();  			if (sig.size() < width_hint)  				sig.extend_u0(width_hint, sign_hint); @@ -1356,6 +1369,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)  	if (0) { case AST_SHIFT_RIGHT:  type_name = ID($shr); }  	if (0) { case AST_SHIFT_SLEFT:  type_name = ID($sshl); }  	if (0) { case AST_SHIFT_SRIGHT: type_name = ID($sshr); } +	if (0) { case AST_SHIFTX:       type_name = ID($shiftx); } +	if (0) { case AST_SHIFT:        type_name = ID($shift); }  		{  			if (width_hint < 0)  				detectSignWidth(width_hint, sign_hint); @@ -1500,10 +1515,10 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)  			sstr << "$memrd$" << str << "$" << filename << ":" << location.first_line << "$" << (autoidx++);  			RTLIL::Cell *cell = current_module->addCell(sstr.str(), ID($memrd)); -			cell->attributes[ID::src] = stringf("%s:%d", filename.c_str(), location.first_line); +			cell->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column);  			RTLIL::Wire *wire = current_module->addWire(cell->name.str() + "_DATA", current_module->memories[str]->width); -			wire->attributes[ID::src] = stringf("%s:%d", filename.c_str(), location.first_line); +			wire->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column);  			int mem_width, mem_size, addr_bits;  			is_signed = id2ast->is_signed; @@ -1807,7 +1822,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)  				is_signed = sign_hint;  				return SigSpec(wire);  			} -		} /* fall through */ +		} +		YS_FALLTHROUGH  	// everything should have been handled above -> print error if not.  	default: diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 9453937e3..3d690c1f5 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -91,7 +91,7 @@ std::string AstNode::process_format_str(const std::string &sformat, int next_arg  				case 'D':  					if (got_len)  						goto unsupported_format; -					/* fall through */ +					YS_FALLTHROUGH  				case 'x':  				case 'X':  					if (next_arg >= GetSize(children)) @@ -608,6 +608,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,  	case AST_TO_BITS:  	case AST_TO_SIGNED:  	case AST_TO_UNSIGNED: +	case AST_SELFSZ:  	case AST_CONCAT:  	case AST_REPLICATE:  	case AST_REDUCE_AND: @@ -920,11 +921,11 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,  			range_swapped = templ->range_swapped;  			range_left = templ->range_left;  			range_right = templ->range_right; -			attributes["\\wiretype"] = mkconst_str(resolved_type->str); +			attributes[ID::wiretype] = mkconst_str(resolved_type->str);  			//check if enum -			if (templ->attributes.count("\\enum_type")){ +			if (templ->attributes.count(ID::enum_type)){  				//get reference to enum node: -				std::string enum_type = templ->attributes["\\enum_type"]->str.c_str(); +				const std::string &enum_type = templ->attributes[ID::enum_type]->str;  				// 				log("enum_type=%s (count=%lu)\n", enum_type.c_str(), current_scope.count(enum_type));  				// 				log("current scope:\n");  				// 				for (auto &it : current_scope) @@ -972,7 +973,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,  					RTLIL::Const val = enum_item->children[0]->bitsAsConst(width, is_signed);  					enum_item_str.append(val.as_string());  					//set attribute for available val to enum item name mappings -					attributes[enum_item_str.c_str()] = mkconst_str(enum_item->str); +					attributes[enum_item_str] = mkconst_str(enum_item->str);  				}  			} @@ -1021,7 +1022,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,  			range_swapped = templ->range_swapped;  			range_left = templ->range_left;  			range_right = templ->range_right; -			attributes["\\wiretype"] = mkconst_str(resolved_type->str); +			attributes[ID::wiretype] = mkconst_str(resolved_type->str);  			for (auto template_child : templ->children)  				children.push_back(template_child->clone());  			did_something = true; @@ -1079,7 +1080,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,  		}  		if (old_range_valid != range_valid)  			did_something = true; -		if (range_valid && range_left >= 0 && range_right > range_left) { +		if (range_valid && range_right > range_left) {  			int tmp = range_right;  			range_right = range_left;  			range_left = tmp; @@ -1097,6 +1098,25 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,  				range_swapped = children[0]->range_swapped;  				range_left = children[0]->range_left;  				range_right = children[0]->range_right; +				bool force_upto = false, force_downto = false; +				if (attributes.count(ID::force_upto)) { +					AstNode *val = attributes[ID::force_upto]; +					if (val->type != AST_CONSTANT) +						log_file_error(filename, location.first_line, "Attribute `force_upto' with non-constant value!\n"); +					force_upto = val->asAttrConst().as_bool(); +				} +				if (attributes.count(ID::force_downto)) { +					AstNode *val = attributes[ID::force_downto]; +					if (val->type != AST_CONSTANT) +						log_file_error(filename, location.first_line, "Attribute `force_downto' with non-constant value!\n"); +					force_downto = val->asAttrConst().as_bool(); +				} +				if (force_upto && force_downto) +					log_file_error(filename, location.first_line, "Attributes `force_downto' and `force_upto' cannot be both set!\n"); +				if ((force_upto && !range_swapped) || (force_downto && range_swapped)) { +					std::swap(range_left, range_right); +					range_swapped = force_upto; +				}  			}  		} else {  			if (!range_valid) @@ -1739,8 +1759,10 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,  			AstNode *node = children_list[1];  			if (op_type != AST_POS) -				for (size_t i = 2; i < children_list.size(); i++) +				for (size_t i = 2; i < children_list.size(); i++) {  					node = new AstNode(op_type, node, children_list[i]); +					node->location = location; +				}  			if (invert_results)  				node = new AstNode(AST_BIT_NOT, node); @@ -1786,7 +1808,18 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,  			result_width = abs(int(left_at_zero_ast->integer - right_at_zero_ast->integer)) + 1;  		} -		if (0) +		bool use_case_method = false; + +		if (children[0]->id2ast->attributes.count(ID::nowrshmsk)) { +			AstNode *node = children[0]->id2ast->attributes.at(ID::nowrshmsk); +			while (node->simplify(true, false, false, stage, -1, false, false)) { } +			if (node->type != AST_CONSTANT) +				log_file_error(filename, location.first_line, "Non-constant value for `nowrshmsk' attribute on `%s'!\n", children[0]->id2ast->str.c_str()); +			if (node->asAttrConst().as_bool()) +				use_case_method = true; +		} + +		if (use_case_method)  		{  			// big case block @@ -1794,10 +1827,10 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,  			newNode = new AstNode(AST_CASE, shift_expr);  			for (int i = 0; i < source_width; i++) {  				int start_bit = children[0]->id2ast->range_right + i; +				int end_bit = std::min(start_bit+result_width,source_width) - 1;  				AstNode *cond = new AstNode(AST_COND, mkconst_int(start_bit, true));  				AstNode *lvalue = children[0]->clone();  				lvalue->delete_children(); -				int end_bit = std::min(start_bit+result_width,source_width) - 1;  				lvalue->children.push_back(new AstNode(AST_RANGE,  						mkconst_int(end_bit, true), mkconst_int(start_bit, true)));  				cond->children.push_back(new AstNode(AST_BLOCK, new AstNode(type, lvalue, children[1]->clone()))); @@ -1810,14 +1843,14 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,  			AstNode *wire_mask = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(source_width-1, true), mkconst_int(0, true)));  			wire_mask->str = stringf("$bitselwrite$mask$%s:%d$%d", filename.c_str(), location.first_line, autoidx++); -			wire_mask->attributes["\\nosync"] = AstNode::mkconst_int(1, false); +			wire_mask->attributes[ID::nosync] = AstNode::mkconst_int(1, false);  			wire_mask->is_logic = true;  			while (wire_mask->simplify(true, false, false, 1, -1, false, false)) { }  			current_ast_mod->children.push_back(wire_mask);  			AstNode *wire_data = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(source_width-1, true), mkconst_int(0, true)));  			wire_data->str = stringf("$bitselwrite$data$%s:%d$%d", filename.c_str(), location.first_line, autoidx++); -			wire_data->attributes["\\nosync"] = AstNode::mkconst_int(1, false); +			wire_data->attributes[ID::nosync] = AstNode::mkconst_int(1, false);  			wire_data->is_logic = true;  			while (wire_data->simplify(true, false, false, 1, -1, false, false)) { }  			current_ast_mod->children.push_back(wire_data); @@ -1844,11 +1877,40 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,  			AstNode *shamt = shift_expr; -			newNode->children.push_back(new AstNode(AST_ASSIGN_EQ, ref_mask->clone(), -					new AstNode(AST_SHIFT_LEFT, mkconst_bits(std::vector<RTLIL::State>(result_width, State::S1), false), shamt->clone()))); -			newNode->children.push_back(new AstNode(AST_ASSIGN_EQ, ref_data->clone(), -					new AstNode(AST_SHIFT_LEFT, new AstNode(AST_BIT_AND, mkconst_bits(std::vector<RTLIL::State>(result_width, State::S1), false), children[1]->clone()), shamt))); -			newNode->children.push_back(new AstNode(type, lvalue, new AstNode(AST_BIT_OR, new AstNode(AST_BIT_AND, old_data, new AstNode(AST_BIT_NOT, ref_mask)), ref_data))); +			int shamt_width_hint = 0; +			bool shamt_sign_hint = true; +			shamt->detectSignWidth(shamt_width_hint, shamt_sign_hint); + +			int start_bit = children[0]->id2ast->range_right; +			bool use_shift = shamt_sign_hint; + +			if (start_bit != 0) { +				shamt = new AstNode(AST_SUB, shamt, mkconst_int(start_bit, true)); +				use_shift = true; +			} + +			AstNode *t; + +			t = mkconst_bits(std::vector<RTLIL::State>(result_width, State::S1), false); +			if (use_shift) +				t = new AstNode(AST_SHIFT, t, new AstNode(AST_NEG, shamt->clone())); +			else +				t = new AstNode(AST_SHIFT_LEFT, t, shamt->clone()); +			t = new AstNode(AST_ASSIGN_EQ, ref_mask->clone(), t); +			newNode->children.push_back(t); + +			t = new AstNode(AST_BIT_AND, mkconst_bits(std::vector<RTLIL::State>(result_width, State::S1), false), children[1]->clone()); +			if (use_shift) +				t = new AstNode(AST_SHIFT, t, new AstNode(AST_NEG, shamt)); +			else +				t = new AstNode(AST_SHIFT_LEFT, t, shamt); +			t = new AstNode(AST_ASSIGN_EQ, ref_data->clone(), t); +			newNode->children.push_back(t); + +			t = new AstNode(AST_BIT_AND, old_data, new AstNode(AST_BIT_NOT, ref_mask)); +			t = new AstNode(AST_BIT_OR, t, ref_data); +			t = new AstNode(type, lvalue, t); +			newNode->children.push_back(t);  		}  		goto apply_newNode; @@ -2637,7 +2699,7 @@ skip_dynamic_range_lvalue_expansion:;  		bool recommend_const_eval = false;  		bool require_const_eval = in_param ? false : has_const_only_constructs(recommend_const_eval); -		if ((in_param || recommend_const_eval || require_const_eval) && !decl->attributes.count("\\via_celltype")) +		if ((in_param || recommend_const_eval || require_const_eval) && !decl->attributes.count(ID::via_celltype))  		{  			bool all_args_const = true;  			for (auto child : children) { @@ -2696,9 +2758,9 @@ skip_dynamic_range_lvalue_expansion:;  			goto replace_fcall_with_id;  		} -		if (decl->attributes.count("\\via_celltype")) +		if (decl->attributes.count(ID::via_celltype))  		{ -			std::string celltype = decl->attributes.at("\\via_celltype")->asAttrConst().decode_string(); +			std::string celltype = decl->attributes.at(ID::via_celltype)->asAttrConst().decode_string();  			std::string outport = str;  			if (celltype.find(' ') != std::string::npos) { @@ -2792,7 +2854,7 @@ skip_dynamic_range_lvalue_expansion:;  					wire->is_reg = true;  					wire->attributes[ID::nosync] = AstNode::mkconst_int(1, false);  					if (child->type == AST_ENUM_ITEM) -						wire->attributes["\\enum_base_type"] = child->attributes["\\enum_base_type"]; +						wire->attributes[ID::enum_base_type] = child->attributes[ID::enum_base_type];  					wire_cache[child->str] = wire; @@ -3024,6 +3086,7 @@ replace_fcall_later:;  				}  			}  			break; +		if (0) { case AST_SELFSZ: const_func = RTLIL::const_pos; }  		if (0) { case AST_POS: const_func = RTLIL::const_pos; }  		if (0) { case AST_NEG: const_func = RTLIL::const_neg; }  			if (children[0]->type == AST_CONSTANT) { @@ -3032,10 +3095,10 @@ replace_fcall_later:;  			} else  			if (children[0]->isConst()) {  				newNode = new AstNode(AST_REALVALUE); -				if (type == AST_POS) -					newNode->realvalue = +children[0]->asReal(sign_hint); -				else +				if (type == AST_NEG)  					newNode->realvalue = -children[0]->asReal(sign_hint); +				else +					newNode->realvalue = +children[0]->asReal(sign_hint);  			}  			break;  		case AST_TERNARY: @@ -4092,7 +4155,7 @@ void AstNode::allocateDefaultEnumValues()  	int last_enum_int = -1;  	for (auto node : children) {  		log_assert(node->type==AST_ENUM_ITEM); -		node->attributes["\\enum_base_type"] = mkconst_str(str); +		node->attributes[ID::enum_base_type] = mkconst_str(str);  		for (size_t i = 0; i < node->children.size(); i++) {  			switch (node->children[i]->type) {  			case AST_NONE: | 
