mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 03:32:29 +00:00 
			
		
		
		
	rtlil: Add packed extract implementation for SigSpec
				
					
				
			Previously `extract` on a `SigSpec` would always unpack it. Since a significant amount of `SigSpec`s have one or few chunks, it's worth having a dedicated implementation. This is especially true, since the RTLIL frontend calls into this for every `wire [lhs:rhs]` slice, making this `extract` take up 40% when profiling `read_rtlil` with one of the largest coarse grained RTLIL designs I had on hand. With this change the `read_rtlil` profile looks like I would expect it to look like, but I noticed that a lot of the other core RTLIL methods also are a bit too eager with unpacking or implementing `SigChunk`/`Const` overloads that just convert to a single chunk `SigSpec` and forward to the implementation for that, when a direct implementation would avoid temporary std::vector allocations. While not relevant for `read_rtlil`, to me it looks like there might be a few easy overall performance gains to be had by addressing this more generally.
This commit is contained in:
		
							parent
							
								
									171577f909
								
							
						
					
					
						commit
						0d30a4d479
					
				
					 1 changed files with 32 additions and 1 deletions
				
			
		|  | @ -4435,8 +4435,39 @@ RTLIL::SigSpec RTLIL::SigSpec::extract(int offset, int length) const | ||||||
| 	log_assert(offset >= 0); | 	log_assert(offset >= 0); | ||||||
| 	log_assert(length >= 0); | 	log_assert(length >= 0); | ||||||
| 	log_assert(offset + length <= width_); | 	log_assert(offset + length <= width_); | ||||||
| 	unpack(); | 
 | ||||||
| 	cover("kernel.rtlil.sigspec.extract_pos"); | 	cover("kernel.rtlil.sigspec.extract_pos"); | ||||||
|  | 
 | ||||||
|  | 	if (packed()) | ||||||
|  | 	{ | ||||||
|  | 		if (chunks_.size() == 1) | ||||||
|  | 			return chunks_[0].extract(offset, length); | ||||||
|  | 
 | ||||||
|  | 		SigSpec extracted; | ||||||
|  | 		int end = offset + length; | ||||||
|  | 		int chunk_end = 0; | ||||||
|  | 
 | ||||||
|  | 		for (auto const &chunk : chunks_) | ||||||
|  | 		{ | ||||||
|  | 			int chunk_begin = chunk_end; | ||||||
|  | 			chunk_end += chunk.width; | ||||||
|  | 			int extract_begin = std::max(chunk_begin, offset); | ||||||
|  | 			int extract_end = std::min(chunk_end, end); | ||||||
|  | 			if (extract_begin >= extract_end) | ||||||
|  | 				continue; | ||||||
|  | 			int extract_offset = extract_begin - chunk_begin; | ||||||
|  | 			int extract_len = extract_end - extract_begin; | ||||||
|  | 			if (extract_offset == 0 && extract_len == chunk.width) | ||||||
|  | 				extracted.chunks_.emplace_back(chunk); | ||||||
|  | 			else | ||||||
|  | 				extracted.chunks_.emplace_back( | ||||||
|  | 					chunk.extract(extract_offset, extract_len)); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		extracted.width_ = length; | ||||||
|  | 		return extracted; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	return std::vector<RTLIL::SigBit>(bits_.begin() + offset, bits_.begin() + offset + length); | 	return std::vector<RTLIL::SigBit>(bits_.begin() + offset, bits_.begin() + offset + length); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue