mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-11-04 05:19:11 +00:00 
			
		
		
		
	Merge branch 'YosysHQ:main' into master
This commit is contained in:
		
						commit
						818fd2e0fa
					
				
					 6 changed files with 210 additions and 74 deletions
				
			
		
							
								
								
									
										16
									
								
								CHANGELOG
									
										
									
									
									
								
							
							
						
						
									
										16
									
								
								CHANGELOG
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -2,9 +2,23 @@
 | 
			
		|||
List of major changes and improvements between releases
 | 
			
		||||
=======================================================
 | 
			
		||||
 | 
			
		||||
Yosys 0.40 .. Yosys 0.41-dev
 | 
			
		||||
Yosys 0.41 .. Yosys 0.42-dev
 | 
			
		||||
--------------------------
 | 
			
		||||
 | 
			
		||||
Yosys 0.40 .. Yosys 0.41
 | 
			
		||||
--------------------------
 | 
			
		||||
 * New commands and options
 | 
			
		||||
    - Added "cellmatch" pass for picking out standard cells automatically. 
 | 
			
		||||
 | 
			
		||||
 * Various
 | 
			
		||||
    - Extended the experimental incremental JSON API to allow arbitrary
 | 
			
		||||
      smtlib subexpressions.
 | 
			
		||||
    - Added support for using ABCs library merging when providing multiple
 | 
			
		||||
      liberty files.
 | 
			
		||||
 | 
			
		||||
 * Verific support
 | 
			
		||||
    - Expose library name as module attribute.
 | 
			
		||||
 | 
			
		||||
Yosys 0.39 .. Yosys 0.40
 | 
			
		||||
--------------------------
 | 
			
		||||
 * New commands and options
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										6
									
								
								Makefile
									
										
									
									
									
								
							
							
						
						
									
										6
									
								
								Makefile
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -141,7 +141,7 @@ LIBS += -lrt
 | 
			
		|||
endif
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
YOSYS_VER := 0.40+68
 | 
			
		||||
YOSYS_VER := 0.41+0
 | 
			
		||||
 | 
			
		||||
# Note: We arrange for .gitcommit to contain the (short) commit hash in
 | 
			
		||||
# tarballs generated with git-archive(1) using .gitattributes. The git repo
 | 
			
		||||
| 
						 | 
				
			
			@ -157,7 +157,7 @@ endif
 | 
			
		|||
OBJS = kernel/version_$(GIT_REV).o
 | 
			
		||||
 | 
			
		||||
bumpversion:
 | 
			
		||||
	sed -i "/^YOSYS_VER := / s/+[0-9][0-9]*$$/+`git log --oneline a1bb025.. | wc -l`/;" Makefile
 | 
			
		||||
	sed -i "/^YOSYS_VER := / s/+[0-9][0-9]*$$/+`git log --oneline c1ad377.. | wc -l`/;" Makefile
 | 
			
		||||
 | 
			
		||||
# set 'ABCREV = default' to use abc/ as it is
 | 
			
		||||
#
 | 
			
		||||
| 
						 | 
				
			
			@ -165,7 +165,7 @@ bumpversion:
 | 
			
		|||
# is just a symlink to your actual ABC working directory, as 'make mrproper'
 | 
			
		||||
# will remove the 'abc' directory and you do not want to accidentally
 | 
			
		||||
# delete your work on ABC..
 | 
			
		||||
ABCREV = 03da96f
 | 
			
		||||
ABCREV = 237d813
 | 
			
		||||
ABCPULL = 1
 | 
			
		||||
ABCURL ?= https://github.com/YosysHQ/abc
 | 
			
		||||
ABCMKARGS = CC="$(CXX)" CXX="$(CXX)" ABC_USE_LIBSTDCXX=1 ABC_USE_NAMESPACE=abc VERBOSE=$(Q)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -606,22 +606,30 @@ std::vector<std::string> split_by(const std::string &str, const std::string &sep
 | 
			
		|||
	return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::string escape_cxx_string(const std::string &input)
 | 
			
		||||
std::string escape_c_string(const std::string &input)
 | 
			
		||||
{
 | 
			
		||||
	std::string output = "\"";
 | 
			
		||||
	std::string output;
 | 
			
		||||
	output.push_back('"');
 | 
			
		||||
	for (auto c : input) {
 | 
			
		||||
		if (::isprint(c)) {
 | 
			
		||||
			if (c == '\\')
 | 
			
		||||
				output.push_back('\\');
 | 
			
		||||
			output.push_back(c);
 | 
			
		||||
		} else {
 | 
			
		||||
			char l = c & 0xf, h = (c >> 4) & 0xf;
 | 
			
		||||
			output.append("\\x");
 | 
			
		||||
			output.push_back((h < 10 ? '0' + h : 'a' + h - 10));
 | 
			
		||||
			output.push_back((l < 10 ? '0' + l : 'a' + l - 10));
 | 
			
		||||
			char l = c & 0x3, m = (c >> 3) & 0x3, h = (c >> 6) & 0x3;
 | 
			
		||||
			output.append("\\");
 | 
			
		||||
			output.push_back('0' + h);
 | 
			
		||||
			output.push_back('0' + m);
 | 
			
		||||
			output.push_back('0' + l);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	output.push_back('"');
 | 
			
		||||
	return output;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::string escape_cxx_string(const std::string &input)
 | 
			
		||||
{
 | 
			
		||||
	std::string output = escape_c_string(input);
 | 
			
		||||
	if (output.find('\0') != std::string::npos) {
 | 
			
		||||
		output.insert(0, "std::string {");
 | 
			
		||||
		output.append(stringf(", %zu}", input.size()));
 | 
			
		||||
| 
						 | 
				
			
			@ -2275,46 +2283,92 @@ struct CxxrtlWorker {
 | 
			
		|||
		dec_indent();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void dump_metadata_map(const dict<RTLIL::IdString, RTLIL::Const> &metadata_map)
 | 
			
		||||
	{
 | 
			
		||||
		if (metadata_map.empty()) {
 | 
			
		||||
			f << "metadata_map()";
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
		f << "metadata_map({\n";
 | 
			
		||||
		inc_indent();
 | 
			
		||||
			for (auto metadata_item : metadata_map) {
 | 
			
		||||
				if (!metadata_item.first.isPublic())
 | 
			
		||||
					continue;
 | 
			
		||||
				if (metadata_item.second.size() > 64 && (metadata_item.second.flags & RTLIL::CONST_FLAG_STRING) == 0) {
 | 
			
		||||
					f << indent << "/* attribute " << metadata_item.first.str().substr(1) << " is over 64 bits wide */\n";
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
				f << indent << "{ " << escape_cxx_string(metadata_item.first.str().substr(1)) << ", ";
 | 
			
		||||
				// In Yosys, a real is a type of string.
 | 
			
		||||
				if (metadata_item.second.flags & RTLIL::CONST_FLAG_REAL) {
 | 
			
		||||
					f << std::showpoint << std::stod(metadata_item.second.decode_string()) << std::noshowpoint;
 | 
			
		||||
				} else if (metadata_item.second.flags & RTLIL::CONST_FLAG_STRING) {
 | 
			
		||||
					f << escape_cxx_string(metadata_item.second.decode_string());
 | 
			
		||||
				} else if (metadata_item.second.flags & RTLIL::CONST_FLAG_SIGNED) {
 | 
			
		||||
					f << "INT64_C(" << metadata_item.second.as_int(/*is_signed=*/true) << ")";
 | 
			
		||||
				} else {
 | 
			
		||||
					f << "UINT64_C(" << metadata_item.second.as_int(/*is_signed=*/false) << ")";
 | 
			
		||||
				}
 | 
			
		||||
				f << " },\n";
 | 
			
		||||
	void dump_serialized_metadata(const dict<RTLIL::IdString, RTLIL::Const> &metadata_map) {
 | 
			
		||||
		// Creating thousands metadata_map objects using initializer lists in a single function results in one of:
 | 
			
		||||
		// 1. Megabytes of stack usage (with __attribute__((optnone))).
 | 
			
		||||
		// 2. Minutes of compile time (without __attribute__((optnone))).
 | 
			
		||||
		// So, don't create them.
 | 
			
		||||
		std::string data;
 | 
			
		||||
		auto put_u64 = [&](uint64_t value) {
 | 
			
		||||
			for (size_t count = 0; count < 8; count++) {
 | 
			
		||||
				data += (char)(value >> 56);
 | 
			
		||||
				value <<= 8;
 | 
			
		||||
			}
 | 
			
		||||
		dec_indent();
 | 
			
		||||
		f << indent << "})";
 | 
			
		||||
		};
 | 
			
		||||
		for (auto metadata_item : metadata_map) {
 | 
			
		||||
			if (!metadata_item.first.isPublic())
 | 
			
		||||
				continue;
 | 
			
		||||
			if (metadata_item.second.size() > 64 && (metadata_item.second.flags & RTLIL::CONST_FLAG_STRING) == 0) {
 | 
			
		||||
				f << indent << "/* attribute " << metadata_item.first.str().substr(1) << " is over 64 bits wide */\n";
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			data += metadata_item.first.str().substr(1) + '\0';
 | 
			
		||||
			// In Yosys, a real is a type of string.
 | 
			
		||||
			if (metadata_item.second.flags & RTLIL::CONST_FLAG_REAL) {
 | 
			
		||||
				double dvalue = std::stod(metadata_item.second.decode_string());
 | 
			
		||||
				uint64_t uvalue;
 | 
			
		||||
				static_assert(sizeof(dvalue) == sizeof(uvalue), "double must be 64 bits in size");
 | 
			
		||||
				memcpy(&uvalue, &dvalue, sizeof(uvalue));
 | 
			
		||||
				data += 'd';
 | 
			
		||||
				put_u64(uvalue);
 | 
			
		||||
			} else if (metadata_item.second.flags & RTLIL::CONST_FLAG_STRING) {
 | 
			
		||||
				data += 's';
 | 
			
		||||
				data += metadata_item.second.decode_string();
 | 
			
		||||
				data += '\0';
 | 
			
		||||
			} else if (metadata_item.second.flags & RTLIL::CONST_FLAG_SIGNED) {
 | 
			
		||||
				data += 'i';
 | 
			
		||||
				put_u64((uint64_t)metadata_item.second.as_int(/*is_signed=*/true));
 | 
			
		||||
			} else {
 | 
			
		||||
				data += 'u';
 | 
			
		||||
				put_u64(metadata_item.second.as_int(/*is_signed=*/false));
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		f << escape_c_string(data);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void dump_debug_attrs(const RTLIL::AttrObject *object)
 | 
			
		||||
	void dump_metadata_map(const dict<RTLIL::IdString, RTLIL::Const> &metadata_map) {
 | 
			
		||||
		if (metadata_map.empty()) {
 | 
			
		||||
			f << "metadata_map()";
 | 
			
		||||
		} else {
 | 
			
		||||
			f << "metadata_map({\n";
 | 
			
		||||
			inc_indent();
 | 
			
		||||
				for (auto metadata_item : metadata_map) {
 | 
			
		||||
					if (!metadata_item.first.isPublic())
 | 
			
		||||
						continue;
 | 
			
		||||
					if (metadata_item.second.size() > 64 && (metadata_item.second.flags & RTLIL::CONST_FLAG_STRING) == 0) {
 | 
			
		||||
						f << indent << "/* attribute " << metadata_item.first.str().substr(1) << " is over 64 bits wide */\n";
 | 
			
		||||
						continue;
 | 
			
		||||
					}
 | 
			
		||||
					f << indent << "{ " << escape_cxx_string(metadata_item.first.str().substr(1)) << ", ";
 | 
			
		||||
					// In Yosys, a real is a type of string.
 | 
			
		||||
					if (metadata_item.second.flags & RTLIL::CONST_FLAG_REAL) {
 | 
			
		||||
						f << std::showpoint << std::stod(metadata_item.second.decode_string()) << std::noshowpoint;
 | 
			
		||||
					} else if (metadata_item.second.flags & RTLIL::CONST_FLAG_STRING) {
 | 
			
		||||
						f << escape_cxx_string(metadata_item.second.decode_string());
 | 
			
		||||
					} else if (metadata_item.second.flags & RTLIL::CONST_FLAG_SIGNED) {
 | 
			
		||||
						f << "INT64_C(" << metadata_item.second.as_int(/*is_signed=*/true) << ")";
 | 
			
		||||
					} else {
 | 
			
		||||
						f << "UINT64_C(" << metadata_item.second.as_int(/*is_signed=*/false) << ")";
 | 
			
		||||
					}
 | 
			
		||||
					f << " },\n";
 | 
			
		||||
				}
 | 
			
		||||
			dec_indent();
 | 
			
		||||
			f << indent << "})";
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void dump_debug_attrs(const RTLIL::AttrObject *object, bool serialize = true)
 | 
			
		||||
	{
 | 
			
		||||
		dict<RTLIL::IdString, RTLIL::Const> attributes = object->attributes;
 | 
			
		||||
		// Inherently necessary to get access to the object, so a waste of space to emit.
 | 
			
		||||
		attributes.erase(ID::hdlname);
 | 
			
		||||
		// Internal Yosys attribute that should be removed but isn't.
 | 
			
		||||
		attributes.erase(ID::module_not_derived);
 | 
			
		||||
		dump_metadata_map(attributes);
 | 
			
		||||
		if (serialize) {
 | 
			
		||||
			dump_serialized_metadata(attributes);
 | 
			
		||||
		} else {
 | 
			
		||||
			dump_metadata_map(attributes);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void dump_debug_info_method(RTLIL::Module *module)
 | 
			
		||||
| 
						 | 
				
			
			@ -2337,7 +2391,7 @@ struct CxxrtlWorker {
 | 
			
		|||
				// The module is responsible for adding its own scope.
 | 
			
		||||
				f << indent << "scopes->add(path.empty() ? path : path.substr(0, path.size() - 1), ";
 | 
			
		||||
				f << escape_cxx_string(get_hdl_name(module)) << ", ";
 | 
			
		||||
				dump_debug_attrs(module);
 | 
			
		||||
				dump_debug_attrs(module, /*serialize=*/false);
 | 
			
		||||
				f << ", std::move(cell_attrs));\n";
 | 
			
		||||
				count_scopes++;
 | 
			
		||||
				// If there were any submodules that were flattened, the module is also responsible for adding them.
 | 
			
		||||
| 
						 | 
				
			
			@ -2347,11 +2401,11 @@ struct CxxrtlWorker {
 | 
			
		|||
						auto module_attrs = scopeinfo_attributes(cell, ScopeinfoAttrs::Module);
 | 
			
		||||
						auto cell_attrs = scopeinfo_attributes(cell, ScopeinfoAttrs::Cell);
 | 
			
		||||
						cell_attrs.erase(ID::module_not_derived);
 | 
			
		||||
						f << indent << "scopes->add(path + " << escape_cxx_string(get_hdl_name(cell)) << ", ";
 | 
			
		||||
						f << indent << "scopes->add(path, " << escape_cxx_string(get_hdl_name(cell)) << ", ";
 | 
			
		||||
						f << escape_cxx_string(cell->get_string_attribute(ID(module))) << ", ";
 | 
			
		||||
						dump_metadata_map(module_attrs);
 | 
			
		||||
						dump_serialized_metadata(module_attrs);
 | 
			
		||||
						f << ", ";
 | 
			
		||||
						dump_metadata_map(cell_attrs);
 | 
			
		||||
						dump_serialized_metadata(cell_attrs);
 | 
			
		||||
						f << ");\n";
 | 
			
		||||
					} else log_assert(false && "Unknown $scopeinfo type");
 | 
			
		||||
					count_scopes++;
 | 
			
		||||
| 
						 | 
				
			
			@ -2419,20 +2473,22 @@ struct CxxrtlWorker {
 | 
			
		|||
							if (has_driven_sync + has_driven_comb + has_undriven > 1)
 | 
			
		||||
								count_mixed_driver++;
 | 
			
		||||
 | 
			
		||||
							f << indent << "items->add(path + " << escape_cxx_string(get_hdl_name(wire));
 | 
			
		||||
							f << ", debug_item(" << mangle(wire) << ", " << wire->start_offset;
 | 
			
		||||
							bool first = true;
 | 
			
		||||
							for (auto flag : flags) {
 | 
			
		||||
								if (first) {
 | 
			
		||||
									first = false;
 | 
			
		||||
									f << ", ";
 | 
			
		||||
								} else {
 | 
			
		||||
									f << "|";
 | 
			
		||||
								}
 | 
			
		||||
								f << "debug_item::" << flag;
 | 
			
		||||
							}
 | 
			
		||||
							f << "), ";
 | 
			
		||||
							f << indent << "items->add(path, " << escape_cxx_string(get_hdl_name(wire)) << ", ";
 | 
			
		||||
							dump_debug_attrs(wire);
 | 
			
		||||
							f << ", " << mangle(wire);
 | 
			
		||||
							if (wire->start_offset != 0 || !flags.empty()) {
 | 
			
		||||
								f << ", " << wire->start_offset;
 | 
			
		||||
								bool first = true;
 | 
			
		||||
								for (auto flag : flags) {
 | 
			
		||||
									if (first) {
 | 
			
		||||
										first = false;
 | 
			
		||||
										f << ", ";
 | 
			
		||||
									} else {
 | 
			
		||||
										f << "|";
 | 
			
		||||
									}
 | 
			
		||||
									f << "debug_item::" << flag;
 | 
			
		||||
								}
 | 
			
		||||
							}
 | 
			
		||||
							f << ");\n";
 | 
			
		||||
							count_member_wires++;
 | 
			
		||||
							break;
 | 
			
		||||
| 
						 | 
				
			
			@ -2440,16 +2496,18 @@ struct CxxrtlWorker {
 | 
			
		|||
						case WireType::ALIAS: {
 | 
			
		||||
							// Alias of a member wire
 | 
			
		||||
							const RTLIL::Wire *aliasee = debug_wire_type.sig_subst.as_wire();
 | 
			
		||||
							f << indent << "items->add(path + " << escape_cxx_string(get_hdl_name(wire));
 | 
			
		||||
							f << ", debug_item(";
 | 
			
		||||
							f << indent << "items->add(path, " << escape_cxx_string(get_hdl_name(wire)) << ", ";
 | 
			
		||||
							dump_debug_attrs(aliasee);
 | 
			
		||||
							f << ", ";
 | 
			
		||||
							// If the aliasee is an outline, then the alias must be an outline, too; otherwise downstream
 | 
			
		||||
							// tooling has no way to find out about the outline.
 | 
			
		||||
							if (debug_wire_types[aliasee].is_outline())
 | 
			
		||||
								f << "debug_eval_outline";
 | 
			
		||||
							else
 | 
			
		||||
								f << "debug_alias()";
 | 
			
		||||
							f << ", " << mangle(aliasee) << ", " << wire->start_offset << "), ";
 | 
			
		||||
							dump_debug_attrs(aliasee);
 | 
			
		||||
							f << ", " << mangle(aliasee);
 | 
			
		||||
							if (wire->start_offset != 0)
 | 
			
		||||
								f << ", " << wire->start_offset;
 | 
			
		||||
							f << ");\n";
 | 
			
		||||
							count_alias_wires++;
 | 
			
		||||
							break;
 | 
			
		||||
| 
						 | 
				
			
			@ -2459,18 +2517,22 @@ struct CxxrtlWorker {
 | 
			
		|||
							f << indent << "static const value<" << wire->width << "> const_" << mangle(wire) << " = ";
 | 
			
		||||
							dump_const(debug_wire_type.sig_subst.as_const());
 | 
			
		||||
							f << ";\n";
 | 
			
		||||
							f << indent << "items->add(path + " << escape_cxx_string(get_hdl_name(wire));
 | 
			
		||||
							f << ", debug_item(const_" << mangle(wire) << ", " << wire->start_offset << "), ";
 | 
			
		||||
							f << indent << "items->add(path, " << escape_cxx_string(get_hdl_name(wire)) << ", ";
 | 
			
		||||
							dump_debug_attrs(wire);
 | 
			
		||||
							f << ", const_" << mangle(wire);
 | 
			
		||||
							if (wire->start_offset != 0)
 | 
			
		||||
								f << ", " << wire->start_offset;
 | 
			
		||||
							f << ");\n";
 | 
			
		||||
							count_const_wires++;
 | 
			
		||||
							break;
 | 
			
		||||
						}
 | 
			
		||||
						case WireType::OUTLINE: {
 | 
			
		||||
							// Localized or inlined, but rematerializable wire
 | 
			
		||||
							f << indent << "items->add(path + " << escape_cxx_string(get_hdl_name(wire));
 | 
			
		||||
							f << ", debug_item(debug_eval_outline, " << mangle(wire) << ", " << wire->start_offset << "), ";
 | 
			
		||||
							f << indent << "items->add(path, " << escape_cxx_string(get_hdl_name(wire)) << ", ";
 | 
			
		||||
							dump_debug_attrs(wire);
 | 
			
		||||
							f << ", debug_eval_outline, " << mangle(wire);
 | 
			
		||||
							if (wire->start_offset != 0)
 | 
			
		||||
								f << ", " << wire->start_offset;
 | 
			
		||||
							f << ");\n";
 | 
			
		||||
							count_inline_wires++;
 | 
			
		||||
							break;
 | 
			
		||||
| 
						 | 
				
			
			@ -2486,15 +2548,14 @@ struct CxxrtlWorker {
 | 
			
		|||
					for (auto &mem : mod_memories[module]) {
 | 
			
		||||
						if (!mem.memid.isPublic())
 | 
			
		||||
							continue;
 | 
			
		||||
						f << indent << "items->add(path + " << escape_cxx_string(mem.packed ? get_hdl_name(mem.cell) : get_hdl_name(mem.mem));
 | 
			
		||||
						f << ", debug_item(" << mangle(&mem) << ", ";
 | 
			
		||||
						f << mem.start_offset << "), ";
 | 
			
		||||
						f << indent << "items->add(path, " << escape_cxx_string(mem.packed ? get_hdl_name(mem.cell) : get_hdl_name(mem.mem)) << ", ";
 | 
			
		||||
						if (mem.packed) {
 | 
			
		||||
							dump_debug_attrs(mem.cell);
 | 
			
		||||
						} else {
 | 
			
		||||
							dump_debug_attrs(mem.mem);
 | 
			
		||||
						}
 | 
			
		||||
						f << ");\n";
 | 
			
		||||
						f << ", " << mangle(&mem) << ", ";
 | 
			
		||||
						f << mem.start_offset << ");\n";
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			dec_indent();
 | 
			
		||||
| 
						 | 
				
			
			@ -2506,7 +2567,7 @@ struct CxxrtlWorker {
 | 
			
		|||
					const char *access = is_cxxrtl_blackbox_cell(cell) ? "->" : ".";
 | 
			
		||||
					f << indent << mangle(cell) << access;
 | 
			
		||||
					f << "debug_info(items, scopes, path + " << escape_cxx_string(get_hdl_name(cell) + ' ') << ", ";
 | 
			
		||||
					dump_debug_attrs(cell);
 | 
			
		||||
					dump_debug_attrs(cell, /*serialize=*/false);
 | 
			
		||||
					f << ");\n";
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -941,6 +941,55 @@ struct metadata {
 | 
			
		|||
		assert(value_type == DOUBLE);
 | 
			
		||||
		return double_value;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Internal CXXRTL use only.
 | 
			
		||||
	static std::map<std::string, metadata> deserialize(const char *ptr) {
 | 
			
		||||
		std::map<std::string, metadata> result;
 | 
			
		||||
		std::string name;
 | 
			
		||||
		// Grammar:
 | 
			
		||||
		// string   ::= [^\0]+ \0
 | 
			
		||||
		// metadata ::= [uid] .{8} | s <string>
 | 
			
		||||
		// map      ::= ( <string> <metadata> )* \0
 | 
			
		||||
		for (;;) {
 | 
			
		||||
			if (*ptr) {
 | 
			
		||||
				name += *ptr++;
 | 
			
		||||
			} else if (!name.empty()) {
 | 
			
		||||
				ptr++;
 | 
			
		||||
				auto get_u64 = [&]() {
 | 
			
		||||
					uint64_t result = 0;
 | 
			
		||||
					for (size_t count = 0; count < 8; count++)
 | 
			
		||||
						result = (result << 8) | *ptr++;
 | 
			
		||||
					return result;
 | 
			
		||||
				};
 | 
			
		||||
				char type = *ptr++;
 | 
			
		||||
				if (type == 'u') {
 | 
			
		||||
					uint64_t value = get_u64();
 | 
			
		||||
					result.emplace(name, value);
 | 
			
		||||
				} else if (type == 'i') {
 | 
			
		||||
					int64_t value = (int64_t)get_u64();
 | 
			
		||||
					result.emplace(name, value);
 | 
			
		||||
				} else if (type == 'd') {
 | 
			
		||||
					double dvalue;
 | 
			
		||||
					uint64_t uvalue = get_u64();
 | 
			
		||||
					static_assert(sizeof(dvalue) == sizeof(uvalue), "double must be 64 bits in size");
 | 
			
		||||
					memcpy(&dvalue, &uvalue, sizeof(dvalue));
 | 
			
		||||
					result.emplace(name, dvalue);
 | 
			
		||||
				} else if (type == 's') {
 | 
			
		||||
					std::string value;
 | 
			
		||||
					while (*ptr)
 | 
			
		||||
						value += *ptr++;
 | 
			
		||||
					ptr++;
 | 
			
		||||
					result.emplace(name, value);
 | 
			
		||||
				} else {
 | 
			
		||||
					assert(false && "Unknown type specifier");
 | 
			
		||||
					return result;
 | 
			
		||||
				}
 | 
			
		||||
				name.clear();
 | 
			
		||||
			} else {
 | 
			
		||||
				return result;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef std::map<std::string, metadata> metadata_map;
 | 
			
		||||
| 
						 | 
				
			
			@ -1417,6 +1466,12 @@ struct debug_items {
 | 
			
		|||
			});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// This overload exists to reduce excessive stack slot allocation in `CXXRTL_EXTREMELY_COLD void debug_info()`.
 | 
			
		||||
	template<class... T>
 | 
			
		||||
	void add(const std::string &base_path, const char *path, const char *serialized_item_attrs, T&&... args) {
 | 
			
		||||
		add(base_path + path, debug_item(std::forward<T>(args)...), metadata::deserialize(serialized_item_attrs));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	size_t count(const std::string &path) const {
 | 
			
		||||
		if (table.count(path) == 0)
 | 
			
		||||
			return 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -1463,6 +1518,11 @@ struct debug_scopes {
 | 
			
		|||
		scope.cell_attrs = std::unique_ptr<debug_attrs>(new debug_attrs { cell_attrs });
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// This overload exists to reduce excessive stack slot allocation in `CXXRTL_EXTREMELY_COLD void debug_info()`.
 | 
			
		||||
	void add(const std::string &base_path, const char *path, const char *module_name, const char *serialized_module_attrs, const char *serialized_cell_attrs) {
 | 
			
		||||
		add(base_path + path, module_name, metadata::deserialize(serialized_module_attrs), metadata::deserialize(serialized_cell_attrs));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	size_t contains(const std::string &path) const {
 | 
			
		||||
		return table.count(path);
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -512,9 +512,10 @@ public:
 | 
			
		|||
	spool &operator=(const spool &) = delete;
 | 
			
		||||
 | 
			
		||||
	~spool() {
 | 
			
		||||
		if (int fd = writefd.exchange(-1))
 | 
			
		||||
		int fd;
 | 
			
		||||
		if ((fd = writefd.exchange(-1)) != -1)
 | 
			
		||||
			close(fd);
 | 
			
		||||
		if (int fd = readfd.exchange(-1))
 | 
			
		||||
		if ((fd = readfd.exchange(-1)) != -1)
 | 
			
		||||
			close(fd);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,7 +5,7 @@ import os
 | 
			
		|||
project = 'YosysHQ Yosys'
 | 
			
		||||
author = 'YosysHQ GmbH'
 | 
			
		||||
copyright ='2024 YosysHQ GmbH'
 | 
			
		||||
yosys_ver = "0.40"
 | 
			
		||||
yosys_ver = "0.41"
 | 
			
		||||
 | 
			
		||||
# select HTML theme
 | 
			
		||||
html_theme = 'furo'
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue