mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 03:32:29 +00:00 
			
		
		
		
	fmt,cxxrtl: fix printing of non-decimal signed numbers.
Also fix interaction of `NUMERIC` justification with `show_base`.
This commit is contained in:
		
							parent
							
								
									00c5b60dfd
								
							
						
					
					
						commit
						ddf7b46955
					
				
					 2 changed files with 100 additions and 68 deletions
				
			
		|  | @ -1058,6 +1058,7 @@ struct fmt_part { | ||||||
| 		// We might want to replace some of these bit() calls with direct
 | 		// We might want to replace some of these bit() calls with direct
 | ||||||
| 		// chunk access if it turns out to be slow enough to matter.
 | 		// chunk access if it turns out to be slow enough to matter.
 | ||||||
| 		std::string buf; | 		std::string buf; | ||||||
|  | 		std::string prefix; | ||||||
| 		switch (type) { | 		switch (type) { | ||||||
| 			case LITERAL: | 			case LITERAL: | ||||||
| 				return str; | 				return str; | ||||||
|  | @ -1096,24 +1097,38 @@ struct fmt_part { | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			case INTEGER: { | 			case INTEGER: { | ||||||
|  | 				bool negative = signed_ && val.is_neg(); | ||||||
|  | 				if (negative) { | ||||||
|  | 					prefix = "-"; | ||||||
|  | 					val = val.neg(); | ||||||
|  | 				} else { | ||||||
|  | 					switch (sign) { | ||||||
|  | 						case MINUS:       break; | ||||||
|  | 						case PLUS_MINUS:  prefix = "+"; break; | ||||||
|  | 						case SPACE_MINUS: prefix = " "; break; | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
| 				size_t width = Bits; | 				size_t width = Bits; | ||||||
| 				if (base != 10) { | 				if (base != 10) { | ||||||
| 					width = 0; | 					width = 1; | ||||||
| 					for (size_t index = 0; index < Bits; index++) | 					for (size_t index = 0; index < Bits; index++) | ||||||
| 						if (val.bit(index)) | 						if (val.bit(index)) | ||||||
| 							width = index + 1; | 							width = index + 1; | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
| 				if (base == 2) { | 				if (base == 2) { | ||||||
|  | 					if (show_base) | ||||||
|  | 						prefix += "0b"; | ||||||
| 					for (size_t index = 0; index < width; index++) { | 					for (size_t index = 0; index < width; index++) { | ||||||
| 						if (group && index > 0 && index % 4 == 0) | 						if (group && index > 0 && index % 4 == 0) | ||||||
| 							buf += '_'; | 							buf += '_'; | ||||||
| 						buf += (val.bit(index) ? '1' : '0'); | 						buf += (val.bit(index) ? '1' : '0'); | ||||||
| 					} | 					} | ||||||
| 					if (show_base) |  | ||||||
| 						buf += "b0"; |  | ||||||
| 					std::reverse(buf.begin(), buf.end()); | 					std::reverse(buf.begin(), buf.end()); | ||||||
| 				} else if (base == 8 || base == 16) { | 				} else if (base == 8 || base == 16) { | ||||||
|  | 					if (show_base) | ||||||
|  | 						prefix += (base == 16) ? (hex_upper ? "0X" : "0x") : "0o"; | ||||||
| 					size_t step = (base == 16) ? 4 : 3; | 					size_t step = (base == 16) ? 4 : 3; | ||||||
| 					for (size_t index = 0; index < width; index += step) { | 					for (size_t index = 0; index < width; index += step) { | ||||||
| 						if (group && index > 0 && index % (4 * step) == 0) | 						if (group && index > 0 && index % (4 * step) == 0) | ||||||
|  | @ -1123,13 +1138,10 @@ struct fmt_part { | ||||||
| 							value |= val.bit(index + 3) << 3; | 							value |= val.bit(index + 3) << 3; | ||||||
| 						buf += (hex_upper ? "0123456789ABCDEF" : "0123456789abcdef")[value]; | 						buf += (hex_upper ? "0123456789ABCDEF" : "0123456789abcdef")[value]; | ||||||
| 					} | 					} | ||||||
| 					if (show_base) |  | ||||||
| 						buf += (base == 16) ? (hex_upper ? "X0" : "x0") : "o0"; |  | ||||||
| 					std::reverse(buf.begin(), buf.end()); | 					std::reverse(buf.begin(), buf.end()); | ||||||
| 				} else if (base == 10) { | 				} else if (base == 10) { | ||||||
| 					bool negative = signed_ && val.is_neg(); | 					if (show_base) | ||||||
| 					if (negative) | 						prefix += "0d"; | ||||||
| 						val = val.neg(); |  | ||||||
| 					if (val.is_zero()) | 					if (val.is_zero()) | ||||||
| 						buf += '0'; | 						buf += '0'; | ||||||
| 					value<(Bits > 4 ? Bits : 4)> xval = val.template zext<(Bits > 4 ? Bits : 4)>(); | 					value<(Bits > 4 ? Bits : 4)> xval = val.template zext<(Bits > 4 ? Bits : 4)>(); | ||||||
|  | @ -1146,13 +1158,6 @@ struct fmt_part { | ||||||
| 						xval = quotient; | 						xval = quotient; | ||||||
| 						index++; | 						index++; | ||||||
| 					} | 					} | ||||||
| 					if (show_base) |  | ||||||
| 						buf += "d0"; |  | ||||||
| 					switch (sign) { |  | ||||||
| 						case MINUS:       buf += negative ? "-" : "";  break; |  | ||||||
| 						case PLUS_MINUS:  buf += negative ? "-" : "+"; break; |  | ||||||
| 						case SPACE_MINUS: buf += negative ? "-" : " "; break; |  | ||||||
| 					} |  | ||||||
| 					std::reverse(buf.begin(), buf.end()); | 					std::reverse(buf.begin(), buf.end()); | ||||||
| 				} else assert(false && "Unsupported base for fmt_part"); | 				} else assert(false && "Unsupported base for fmt_part"); | ||||||
| 				break; | 				break; | ||||||
|  | @ -1170,17 +1175,29 @@ struct fmt_part { | ||||||
| 
 | 
 | ||||||
| 		std::string str; | 		std::string str; | ||||||
| 		assert(width == 0 || padding != '\0'); | 		assert(width == 0 || padding != '\0'); | ||||||
| 		if (justify != LEFT && buf.size() < width) { | 		if (prefix.size() + buf.size() < width) { | ||||||
| 			size_t pad_width = width - buf.size(); | 			size_t pad_width = width - prefix.size() - buf.size(); | ||||||
| 			if (justify == NUMERIC && (buf.front() == '+' || buf.front() == '-' || buf.front() == ' ')) { | 			switch (justify) { | ||||||
| 				str += buf.front(); | 				case LEFT: | ||||||
| 				buf.erase(0, 1); | 					str += prefix; | ||||||
| 			} | 					str += buf; | ||||||
| 			str += std::string(pad_width, padding); | 					str += std::string(pad_width, padding); | ||||||
|  | 					break; | ||||||
|  | 				case RIGHT: | ||||||
|  | 					str += std::string(pad_width, padding); | ||||||
|  | 					str += prefix; | ||||||
|  | 					str += buf; | ||||||
|  | 					break; | ||||||
|  | 				case NUMERIC: | ||||||
|  | 					str += prefix; | ||||||
|  | 					str += std::string(pad_width, padding); | ||||||
|  | 					str += buf; | ||||||
|  | 					break; | ||||||
|  | 				} | ||||||
|  | 		} else { | ||||||
|  | 			str += prefix; | ||||||
|  | 			str += buf; | ||||||
| 		} | 		} | ||||||
| 		str += buf; |  | ||||||
| 		if (justify == LEFT && buf.size() < width) |  | ||||||
| 			str += std::string(width - buf.size(), padding); |  | ||||||
| 		return str; | 		return str; | ||||||
| 	} | 	} | ||||||
| }; | }; | ||||||
|  |  | ||||||
							
								
								
									
										101
									
								
								kernel/fmt.cc
									
										
									
									
									
								
							
							
						
						
									
										101
									
								
								kernel/fmt.cc
									
										
									
									
									
								
							|  | @ -491,6 +491,8 @@ void Fmt::parse_verilog(const std::vector<VerilogFmtArg> &args, bool sformat_lik | ||||||
| 							if (part.type == FmtPart::INTEGER && part.base != 10 && part.sign != FmtPart::MINUS) | 							if (part.type == FmtPart::INTEGER && part.base != 10 && part.sign != FmtPart::MINUS) | ||||||
| 								log_file_error(fmtarg->filename, fmtarg->first_line, "System task `%s' called with invalid format specifier in argument %zu.\n", task_name.c_str(), fmtarg - args.begin() + 1); | 								log_file_error(fmtarg->filename, fmtarg->first_line, "System task `%s' called with invalid format specifier in argument %zu.\n", task_name.c_str(), fmtarg - args.begin() + 1); | ||||||
| 
 | 
 | ||||||
|  | 							if (part.base != 10) | ||||||
|  | 								part.signed_ = false; | ||||||
| 							if (part.type == FmtPart::INTEGER && !has_leading_zero) | 							if (part.type == FmtPart::INTEGER && !has_leading_zero) | ||||||
| 								apply_verilog_automatic_sizing_and_add(part); | 								apply_verilog_automatic_sizing_and_add(part); | ||||||
| 							else | 							else | ||||||
|  | @ -731,11 +733,34 @@ std::string Fmt::render() const | ||||||
| 			case FmtPart::STRING: | 			case FmtPart::STRING: | ||||||
| 			case FmtPart::VLOG_TIME: { | 			case FmtPart::VLOG_TIME: { | ||||||
| 				std::string buf; | 				std::string buf; | ||||||
|  | 				std::string prefix; | ||||||
| 				if (part.type == FmtPart::INTEGER) { | 				if (part.type == FmtPart::INTEGER) { | ||||||
| 					RTLIL::Const value = part.sig.as_const(); | 					RTLIL::Const value = part.sig.as_const(); | ||||||
|  | 					bool has_x = false, all_x = true, has_z = false, all_z = true; | ||||||
|  | 					for (State bit : value) { | ||||||
|  | 						if (bit == State::Sx) | ||||||
|  | 							has_x = true; | ||||||
|  | 						else | ||||||
|  | 							all_x = false; | ||||||
|  | 						if (bit == State::Sz) | ||||||
|  | 							has_z = true; | ||||||
|  | 						else | ||||||
|  | 							all_z = false; | ||||||
|  | 					} | ||||||
|  | 
 | ||||||
|  | 					if (!has_z && !has_x && part.signed_ && value[value.size() - 1]) { | ||||||
|  | 						prefix = "-"; | ||||||
|  | 						value = RTLIL::const_neg(value, {}, part.signed_, {}, value.size() + 1); | ||||||
|  | 					} else { | ||||||
|  | 						switch (part.sign) { | ||||||
|  | 							case FmtPart::MINUS:       break; | ||||||
|  | 							case FmtPart::PLUS_MINUS:  prefix = "+"; break; | ||||||
|  | 							case FmtPart::SPACE_MINUS: prefix = " "; break; | ||||||
|  | 						} | ||||||
|  | 					} | ||||||
| 
 | 
 | ||||||
| 					if (part.base != 10) { | 					if (part.base != 10) { | ||||||
| 						size_t minimum_size = 0; | 						size_t minimum_size = 1; | ||||||
| 						for (size_t index = 0; index < (size_t)value.size(); index++) | 						for (size_t index = 0; index < (size_t)value.size(); index++) | ||||||
| 							if (value[index] != State::S0) | 							if (value[index] != State::S0) | ||||||
| 								minimum_size = index + 1; | 								minimum_size = index + 1; | ||||||
|  | @ -743,6 +768,8 @@ std::string Fmt::render() const | ||||||
| 					} | 					} | ||||||
| 
 | 
 | ||||||
| 					if (part.base == 2) { | 					if (part.base == 2) { | ||||||
|  | 						if (part.show_base) | ||||||
|  | 							prefix += "0b"; | ||||||
| 						for (size_t index = 0; index < (size_t)value.size(); index++) { | 						for (size_t index = 0; index < (size_t)value.size(); index++) { | ||||||
| 							if (part.group && index > 0 && index % 4 == 0) | 							if (part.group && index > 0 && index % 4 == 0) | ||||||
| 								buf += '_'; | 								buf += '_'; | ||||||
|  | @ -756,10 +783,10 @@ std::string Fmt::render() const | ||||||
| 							else /* if (bit == State::S0) */ | 							else /* if (bit == State::S0) */ | ||||||
| 								buf += '0'; | 								buf += '0'; | ||||||
| 						} | 						} | ||||||
| 						if (part.show_base) |  | ||||||
| 							buf += "b0"; |  | ||||||
| 						std::reverse(buf.begin(), buf.end()); | 						std::reverse(buf.begin(), buf.end()); | ||||||
| 					} else if (part.base == 8 || part.base == 16) { | 					} else if (part.base == 8 || part.base == 16) { | ||||||
|  | 						if (part.show_base) | ||||||
|  | 							prefix += (part.base == 16) ? (part.hex_upper ? "0X" : "0x") : "0o"; | ||||||
| 						size_t step = (part.base == 16) ? 4 : 3; | 						size_t step = (part.base == 16) ? 4 : 3; | ||||||
| 						for (size_t index = 0; index < (size_t)value.size(); index += step) { | 						for (size_t index = 0; index < (size_t)value.size(); index += step) { | ||||||
| 							if (part.group && index > 0 && index % (4 * step) == 0) | 							if (part.group && index > 0 && index % (4 * step) == 0) | ||||||
|  | @ -787,21 +814,10 @@ std::string Fmt::render() const | ||||||
| 							else | 							else | ||||||
| 								buf += (part.hex_upper ? "0123456789ABCDEF" : "0123456789abcdef")[subvalue.as_int()]; | 								buf += (part.hex_upper ? "0123456789ABCDEF" : "0123456789abcdef")[subvalue.as_int()]; | ||||||
| 						} | 						} | ||||||
| 						if (part.show_base) |  | ||||||
| 							buf += (part.base == 16) ? (part.hex_upper ? "X0" : "x0") : "o0"; |  | ||||||
| 						std::reverse(buf.begin(), buf.end()); | 						std::reverse(buf.begin(), buf.end()); | ||||||
| 					} else if (part.base == 10) { | 					} else if (part.base == 10) { | ||||||
| 						bool has_x = false, all_x = true, has_z = false, all_z = true; | 						if (part.show_base) | ||||||
| 						for (State bit : value) { | 							prefix += "0d"; | ||||||
| 							if (bit == State::Sx) |  | ||||||
| 								has_x = true; |  | ||||||
| 							else |  | ||||||
| 								all_x = false; |  | ||||||
| 							if (bit == State::Sz) |  | ||||||
| 								has_z = true; |  | ||||||
| 							else |  | ||||||
| 								all_z = false; |  | ||||||
| 						} |  | ||||||
| 						if (all_x) | 						if (all_x) | ||||||
| 							buf += 'x'; | 							buf += 'x'; | ||||||
| 						else if (all_z) | 						else if (all_z) | ||||||
|  | @ -811,30 +827,17 @@ std::string Fmt::render() const | ||||||
| 						else if (has_z) | 						else if (has_z) | ||||||
| 							buf += 'Z'; | 							buf += 'Z'; | ||||||
| 						else { | 						else { | ||||||
| 							bool negative = part.signed_ && value[value.size() - 1]; | 							log_assert(value.is_fully_def()); | ||||||
| 							RTLIL::Const absvalue; | 							if (value.is_fully_zero()) | ||||||
| 							if (negative) |  | ||||||
| 								absvalue = RTLIL::const_neg(value, {}, part.signed_, {}, value.size() + 1); |  | ||||||
| 							else |  | ||||||
| 								absvalue = value; |  | ||||||
| 							log_assert(absvalue.is_fully_def()); |  | ||||||
| 							if (absvalue.is_fully_zero()) |  | ||||||
| 								buf += '0'; | 								buf += '0'; | ||||||
| 							size_t index = 0; | 							size_t index = 0; | ||||||
| 							while (!absvalue.is_fully_zero())	{ | 							while (!value.is_fully_zero())	{ | ||||||
| 								if (part.group && index > 0 && index % 3 == 0) | 								if (part.group && index > 0 && index % 3 == 0) | ||||||
| 									buf += '_'; | 									buf += '_'; | ||||||
| 								buf += '0' + RTLIL::const_mod(absvalue, 10, false, false, 4).as_int(); | 								buf += '0' + RTLIL::const_mod(value, 10, false, false, 4).as_int(); | ||||||
| 								absvalue = RTLIL::const_div(absvalue, 10, false, false, absvalue.size()); | 								value = RTLIL::const_div(value, 10, false, false, value.size()); | ||||||
| 								index++; | 								index++; | ||||||
| 							} | 							} | ||||||
| 							if (part.show_base) |  | ||||||
| 								buf += "d0"; |  | ||||||
| 							switch (part.sign) { |  | ||||||
| 								case FmtPart::MINUS:       buf += negative ? "-" : "";  break; |  | ||||||
| 								case FmtPart::PLUS_MINUS:  buf += negative ? "-" : "+"; break; |  | ||||||
| 								case FmtPart::SPACE_MINUS: buf += negative ? "-" : " "; break; |  | ||||||
| 							} |  | ||||||
| 							std::reverse(buf.begin(), buf.end()); | 							std::reverse(buf.begin(), buf.end()); | ||||||
| 						} | 						} | ||||||
| 					} else log_abort(); | 					} else log_abort(); | ||||||
|  | @ -846,17 +849,29 @@ std::string Fmt::render() const | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
| 				log_assert(part.width == 0 || part.padding != '\0'); | 				log_assert(part.width == 0 || part.padding != '\0'); | ||||||
| 				if (part.justify != FmtPart::LEFT && buf.size() < part.width) { | 				if (prefix.size() + buf.size() < part.width) { | ||||||
| 					size_t pad_width = part.width - buf.size(); | 					size_t pad_width = part.width - prefix.size() - buf.size(); | ||||||
| 					if (part.justify == FmtPart::NUMERIC && (!buf.empty() && (buf.front() == '+' || buf.front() == '-' || buf.front() == ' '))) { | 					switch (part.justify) { | ||||||
| 						str += buf.front(); | 						case FmtPart::LEFT: | ||||||
| 						buf.erase(0, 1); | 							str += prefix; | ||||||
|  | 							str += buf; | ||||||
|  | 							str += std::string(pad_width, part.padding); | ||||||
|  | 							break; | ||||||
|  | 						case FmtPart::RIGHT: | ||||||
|  | 							str += std::string(pad_width, part.padding); | ||||||
|  | 							str += prefix; | ||||||
|  | 							str += buf; | ||||||
|  | 							break; | ||||||
|  | 						case FmtPart::NUMERIC: | ||||||
|  | 							str += prefix; | ||||||
|  | 							str += std::string(pad_width, part.padding); | ||||||
|  | 							str += buf; | ||||||
|  | 							break; | ||||||
| 					} | 					} | ||||||
| 					str += std::string(pad_width, part.padding); | 				} else { | ||||||
|  | 					str += prefix; | ||||||
|  | 					str += buf; | ||||||
| 				} | 				} | ||||||
| 				str += buf; |  | ||||||
| 				if (part.justify == FmtPart::LEFT && buf.size() < part.width) |  | ||||||
| 					str += std::string(part.width - buf.size(), part.padding); |  | ||||||
| 				break; | 				break; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue