mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 03:32:29 +00:00 
			
		
		
		
	kernel/mem: Add helpers for write port widening.
This commit is contained in:
		
							parent
							
								
									83a218141c
								
							
						
					
					
						commit
						b019db1f37
					
				
					 2 changed files with 57 additions and 0 deletions
				
			
		|  | @ -798,3 +798,49 @@ void Mem::prepare_wr_merge(int idx1, int idx2) { | |||
| 			oport.priority_mask[idx1] = true; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void Mem::widen_prep(int wide_log2) { | ||||
| 	// Make sure start_offset and size are aligned to the port width,
 | ||||
| 	// adjust if necessary.
 | ||||
| 	int mask = ((1 << wide_log2) - 1); | ||||
| 	int delta = start_offset & mask; | ||||
| 	start_offset -= delta; | ||||
| 	size += delta; | ||||
| 	if (size & mask) { | ||||
| 		size |= mask; | ||||
| 		size++; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void Mem::widen_wr_port(int idx, int wide_log2) { | ||||
| 	widen_prep(wide_log2); | ||||
| 	auto &port = wr_ports[idx]; | ||||
| 	log_assert(port.wide_log2 <= wide_log2); | ||||
| 	if (port.wide_log2 < wide_log2) { | ||||
| 		SigSpec new_data, new_en; | ||||
| 		SigSpec addr_lo = port.addr.extract(0, wide_log2); | ||||
| 		for (int sub = 0; sub < (1 << wide_log2); sub += (1 << port.wide_log2)) | ||||
| 		{ | ||||
| 			Const cur_addr_lo(sub, wide_log2); | ||||
| 			if (addr_lo == cur_addr_lo) { | ||||
| 				// Always writes to this subword.
 | ||||
| 				new_data.append(port.data); | ||||
| 				new_en.append(port.en); | ||||
| 			} else if (addr_lo.is_fully_const()) { | ||||
| 				// Never writes to this subword.
 | ||||
| 				new_data.append(Const(State::Sx, GetSize(port.data))); | ||||
| 				new_en.append(Const(State::S0, GetSize(port.data))); | ||||
| 			} else { | ||||
| 				// May or may not write to this subword.
 | ||||
| 				new_data.append(port.data); | ||||
| 				SigSpec addr_eq = module->Eq(NEW_ID, addr_lo, cur_addr_lo); | ||||
| 				SigSpec en = module->Mux(NEW_ID, Const(State::S0, GetSize(port.data)), port.en, addr_eq); | ||||
| 				new_en.append(en); | ||||
| 			} | ||||
| 		} | ||||
| 		port.addr.replace(port.wide_log2, Const(State::S0, wide_log2 - port.wide_log2)); | ||||
| 		port.data = new_data; | ||||
| 		port.en = new_en; | ||||
| 		port.wide_log2 = wide_log2; | ||||
| 	} | ||||
| } | ||||
|  |  | |||
							
								
								
									
										11
									
								
								kernel/mem.h
									
										
									
									
									
								
							
							
						
						
									
										11
									
								
								kernel/mem.h
									
										
									
									
									
								
							|  | @ -109,6 +109,17 @@ struct Mem { | |||
| 	// is called.
 | ||||
| 	void prepare_wr_merge(int idx1, int idx2); | ||||
| 
 | ||||
| 	// Prepares the memory for widening a port to a given width.  This
 | ||||
| 	// involves ensuring that start_offset and size are aligned to the
 | ||||
| 	// target width.
 | ||||
| 	void widen_prep(int wide_log2); | ||||
| 
 | ||||
| 	// Widens a write port up to a given width.  The newly port is
 | ||||
| 	// equivalent to the original, made by replicating enable/data bits
 | ||||
| 	// and masking enable bits with decoders on the low part of the
 | ||||
| 	// original address.
 | ||||
| 	void widen_wr_port(int idx, int wide_log2); | ||||
| 
 | ||||
| 	Mem(Module *module, IdString memid, int width, int start_offset, int size) : module(module), memid(memid), packed(false), mem(nullptr), cell(nullptr), width(width), start_offset(start_offset), size(size) {} | ||||
| }; | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue