mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 03:32:29 +00:00 
			
		
		
		
	cxxrtl: expose port direction in debug information.
This can be useful to distinguish e.g. a combinatorially driven wire with type `CXXRTL_VALUE` from a module input with the same type, as well as general introspection.
This commit is contained in:
		
							parent
							
								
									8d6e5c6391
								
							
						
					
					
						commit
						b025ee0aa6
					
				
					 3 changed files with 51 additions and 5 deletions
				
			
		|  | @ -824,6 +824,7 @@ struct debug_alias {}; | ||||||
| // To avoid violating strict aliasing rules, this structure has to be a subclass of the one used
 | // To avoid violating strict aliasing rules, this structure has to be a subclass of the one used
 | ||||||
| // in the C API, or it would not be possible to cast between the pointers to these.
 | // in the C API, or it would not be possible to cast between the pointers to these.
 | ||||||
| struct debug_item : ::cxxrtl_object { | struct debug_item : ::cxxrtl_object { | ||||||
|  | 	// Object types.
 | ||||||
| 	enum : uint32_t { | 	enum : uint32_t { | ||||||
| 		VALUE  = CXXRTL_VALUE, | 		VALUE  = CXXRTL_VALUE, | ||||||
| 		WIRE   = CXXRTL_WIRE, | 		WIRE   = CXXRTL_WIRE, | ||||||
|  | @ -831,13 +832,21 @@ struct debug_item : ::cxxrtl_object { | ||||||
| 		ALIAS  = CXXRTL_ALIAS, | 		ALIAS  = CXXRTL_ALIAS, | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
|  | 	// Object flags.
 | ||||||
|  | 	enum : uint32_t { | ||||||
|  | 		INPUT  = CXXRTL_INPUT, | ||||||
|  | 		OUTPUT = CXXRTL_OUTPUT, | ||||||
|  | 		INOUT  = CXXRTL_INOUT, | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
| 	debug_item(const ::cxxrtl_object &object) : cxxrtl_object(object) {} | 	debug_item(const ::cxxrtl_object &object) : cxxrtl_object(object) {} | ||||||
| 
 | 
 | ||||||
| 	template<size_t Bits> | 	template<size_t Bits> | ||||||
| 	debug_item(value<Bits> &item, size_t lsb_offset = 0) { | 	debug_item(value<Bits> &item, size_t lsb_offset = 0, uint32_t flags_ = 0) { | ||||||
| 		static_assert(sizeof(item) == value<Bits>::chunks * sizeof(chunk_t), | 		static_assert(sizeof(item) == value<Bits>::chunks * sizeof(chunk_t), | ||||||
| 		              "value<Bits> is not compatible with C layout"); | 		              "value<Bits> is not compatible with C layout"); | ||||||
| 		type    = VALUE; | 		type    = VALUE; | ||||||
|  | 		flags   = flags_; | ||||||
| 		width   = Bits; | 		width   = Bits; | ||||||
| 		lsb_at  = lsb_offset; | 		lsb_at  = lsb_offset; | ||||||
| 		depth   = 1; | 		depth   = 1; | ||||||
|  | @ -847,10 +856,11 @@ struct debug_item : ::cxxrtl_object { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	template<size_t Bits> | 	template<size_t Bits> | ||||||
| 	debug_item(const value<Bits> &item, size_t lsb_offset = 0) { | 	debug_item(const value<Bits> &item, size_t lsb_offset = 0, uint32_t flags_ = 0) { | ||||||
| 		static_assert(sizeof(item) == value<Bits>::chunks * sizeof(chunk_t), | 		static_assert(sizeof(item) == value<Bits>::chunks * sizeof(chunk_t), | ||||||
| 		              "value<Bits> is not compatible with C layout"); | 		              "value<Bits> is not compatible with C layout"); | ||||||
| 		type    = VALUE; | 		type    = VALUE; | ||||||
|  | 		flags   = flags_; | ||||||
| 		width   = Bits; | 		width   = Bits; | ||||||
| 		lsb_at  = lsb_offset; | 		lsb_at  = lsb_offset; | ||||||
| 		depth   = 1; | 		depth   = 1; | ||||||
|  | @ -860,11 +870,12 @@ struct debug_item : ::cxxrtl_object { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	template<size_t Bits> | 	template<size_t Bits> | ||||||
| 	debug_item(wire<Bits> &item, size_t lsb_offset = 0) { | 	debug_item(wire<Bits> &item, size_t lsb_offset = 0, uint32_t flags_ = 0) { | ||||||
| 		static_assert(sizeof(item.curr) == value<Bits>::chunks * sizeof(chunk_t) && | 		static_assert(sizeof(item.curr) == value<Bits>::chunks * sizeof(chunk_t) && | ||||||
| 		              sizeof(item.next) == value<Bits>::chunks * sizeof(chunk_t), | 		              sizeof(item.next) == value<Bits>::chunks * sizeof(chunk_t), | ||||||
| 		              "wire<Bits> is not compatible with C layout"); | 		              "wire<Bits> is not compatible with C layout"); | ||||||
| 		type    = WIRE; | 		type    = WIRE; | ||||||
|  | 		flags   = flags_; | ||||||
| 		width   = Bits; | 		width   = Bits; | ||||||
| 		lsb_at  = lsb_offset; | 		lsb_at  = lsb_offset; | ||||||
| 		depth   = 1; | 		depth   = 1; | ||||||
|  | @ -878,6 +889,7 @@ struct debug_item : ::cxxrtl_object { | ||||||
| 		static_assert(sizeof(item.data[0]) == value<Width>::chunks * sizeof(chunk_t), | 		static_assert(sizeof(item.data[0]) == value<Width>::chunks * sizeof(chunk_t), | ||||||
| 		              "memory<Width> is not compatible with C layout"); | 		              "memory<Width> is not compatible with C layout"); | ||||||
| 		type    = MEMORY; | 		type    = MEMORY; | ||||||
|  | 		flags   = 0; | ||||||
| 		width   = Width; | 		width   = Width; | ||||||
| 		lsb_at  = 0; | 		lsb_at  = 0; | ||||||
| 		depth   = item.data.size(); | 		depth   = item.data.size(); | ||||||
|  | @ -891,6 +903,7 @@ struct debug_item : ::cxxrtl_object { | ||||||
| 		static_assert(sizeof(item) == value<Bits>::chunks * sizeof(chunk_t), | 		static_assert(sizeof(item) == value<Bits>::chunks * sizeof(chunk_t), | ||||||
| 		              "value<Bits> is not compatible with C layout"); | 		              "value<Bits> is not compatible with C layout"); | ||||||
| 		type    = ALIAS; | 		type    = ALIAS; | ||||||
|  | 		flags   = 0; | ||||||
| 		width   = Bits; | 		width   = Bits; | ||||||
| 		lsb_at  = lsb_offset; | 		lsb_at  = lsb_offset; | ||||||
| 		depth   = 1; | 		depth   = 1; | ||||||
|  | @ -905,6 +918,7 @@ struct debug_item : ::cxxrtl_object { | ||||||
| 		              sizeof(item.next) == value<Bits>::chunks * sizeof(chunk_t), | 		              sizeof(item.next) == value<Bits>::chunks * sizeof(chunk_t), | ||||||
| 		              "wire<Bits> is not compatible with C layout"); | 		              "wire<Bits> is not compatible with C layout"); | ||||||
| 		type    = ALIAS; | 		type    = ALIAS; | ||||||
|  | 		flags   = 0; | ||||||
| 		width   = Bits; | 		width   = Bits; | ||||||
| 		lsb_at  = lsb_offset; | 		lsb_at  = lsb_offset; | ||||||
| 		depth   = 1; | 		depth   = 1; | ||||||
|  |  | ||||||
|  | @ -1662,7 +1662,14 @@ struct CxxrtlWorker { | ||||||
| 					// Member wire
 | 					// Member wire
 | ||||||
| 					f << indent << "items.add(path + " << escape_cxx_string(get_hdl_name(wire)); | 					f << indent << "items.add(path + " << escape_cxx_string(get_hdl_name(wire)); | ||||||
| 					f << ", debug_item(" << mangle(wire) << ", "; | 					f << ", debug_item(" << mangle(wire) << ", "; | ||||||
| 					f << wire->start_offset << "));\n"; | 					f << wire->start_offset; | ||||||
|  | 					if (wire->port_input && wire->port_output) | ||||||
|  | 						f << ", debug_item::INOUT"; | ||||||
|  | 					else if (wire->port_input) | ||||||
|  | 						f << ", debug_item::INPUT"; | ||||||
|  | 					else if (wire->port_output) | ||||||
|  | 						f << ", debug_item::OUTPUT"; | ||||||
|  | 					f << "));\n"; | ||||||
| 					count_member_wires++; | 					count_member_wires++; | ||||||
| 				} else { | 				} else { | ||||||
| 					count_skipped_wires++; | 					count_skipped_wires++; | ||||||
|  |  | ||||||
|  | @ -112,6 +112,28 @@ enum cxxrtl_type { | ||||||
| 	// More object types may be added in the future, but the existing ones will never change.
 | 	// More object types may be added in the future, but the existing ones will never change.
 | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | // Flags of a simulated object.
 | ||||||
|  | enum cxxrtl_flag { | ||||||
|  | 	// Node is a module input port.
 | ||||||
|  | 	//
 | ||||||
|  | 	// This flag can be set on objects of type `CXXRTL_VALUE` and `CXXRTL_WIRE`. It may be combined
 | ||||||
|  | 	// with `CXXRTL_OUTPUT`, as well as other flags.
 | ||||||
|  | 	CXXRTL_INPUT = 1 << 0, | ||||||
|  | 
 | ||||||
|  | 	// Node is a module output port.
 | ||||||
|  | 	//
 | ||||||
|  | 	// This flag can be set on objects of type `CXXRTL_WIRE`. It may be combined with `CXXRTL_INPUT`,
 | ||||||
|  | 	// as well as other flags.
 | ||||||
|  | 	CXXRTL_OUTPUT = 1 << 1, | ||||||
|  | 
 | ||||||
|  | 	// Node is a module inout port.
 | ||||||
|  | 	//
 | ||||||
|  | 	// This flag can be set on objects of type `CXXRTL_WIRE`. It may be combined with other flags.
 | ||||||
|  | 	CXXRTL_INOUT = (CXXRTL_INPUT|CXXRTL_OUTPUT), | ||||||
|  | 
 | ||||||
|  | 	// More object flags may be added in the future, but the existing ones will never change.
 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| // Description of a simulated object.
 | // Description of a simulated object.
 | ||||||
| //
 | //
 | ||||||
| // The `data` array can be accessed directly to inspect and, if applicable, modify the bits
 | // The `data` array can be accessed directly to inspect and, if applicable, modify the bits
 | ||||||
|  | @ -123,6 +145,9 @@ struct cxxrtl_object { | ||||||
| 	// determines all other properties of the object.
 | 	// determines all other properties of the object.
 | ||||||
| 	uint32_t type; // actually `enum cxxrtl_type`
 | 	uint32_t type; // actually `enum cxxrtl_type`
 | ||||||
| 
 | 
 | ||||||
|  | 	// Flags of the object.
 | ||||||
|  | 	uint32_t flags; // actually bit mask of `enum cxxrtl_flags`
 | ||||||
|  | 
 | ||||||
| 	// Width of the object in bits.
 | 	// Width of the object in bits.
 | ||||||
| 	size_t width; | 	size_t width; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue