mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-27 01:39:23 +00:00 
			
		
		
		
	Bugfix in partial mem write handling in verilog back-end
This commit is contained in:
		
							parent
							
								
									d77a914683
								
							
						
					
					
						commit
						75bf7416f0
					
				
					 1 changed files with 26 additions and 42 deletions
				
			
		|  | @ -908,13 +908,9 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell) | |||
| 		} | ||||
| 
 | ||||
| 		int nwrite_ports = cell->parameters["\\WR_PORTS"].as_int(); | ||||
| 		RTLIL::SigSpec sig_wr_clk, sig_wr_data, sig_wr_addr, sig_wr_en, sig_wr_en_bit; | ||||
| 		RTLIL::SigBit last_bit; | ||||
| 		RTLIL::SigSpec sig_wr_clk, sig_wr_data, sig_wr_addr, sig_wr_en; | ||||
| 		bool wr_clk_posedge; | ||||
| 		RTLIL::SigSpec lof_wen; | ||||
| 		dict<RTLIL::SigSpec, int> wen_to_width; | ||||
| 		SigMap sigmap(active_module); | ||||
| 		int n, wen_width; | ||||
| 		// write ports
 | ||||
| 		for (int i=0; i < nwrite_ports; i++) | ||||
| 		{ | ||||
|  | @ -922,7 +918,6 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell) | |||
| 			sig_wr_data = cell->getPort("\\WR_DATA").extract(i*width, width); | ||||
| 			sig_wr_addr = cell->getPort("\\WR_ADDR").extract(i*abits, abits); | ||||
| 			sig_wr_en = cell->getPort("\\WR_EN").extract(i*width, width); | ||||
| 			sig_wr_en_bit = sig_wr_en.extract(0); | ||||
| 			wr_clk_posedge = cell->parameters["\\WR_CLK_POLARITY"].extract(i).as_bool(); | ||||
| 			{ | ||||
| 				std::ostringstream os; | ||||
|  | @ -931,48 +926,37 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell) | |||
| 				if( clk_to_lof_body.count(clk_domain_str) == 0 ) | ||||
| 					clk_to_lof_body[clk_domain_str] = std::vector<std::string>(); | ||||
| 			} | ||||
| 			// group the wen bits
 | ||||
| 			last_bit = sig_wr_en.extract(0); | ||||
| 			lof_wen = RTLIL::SigSpec(last_bit); | ||||
| 			wen_to_width.clear(); | ||||
| 			wen_to_width[last_bit] = 0; | ||||
| 			for (auto ¤t_bit : sig_wr_en.bits()) | ||||
| 			{ | ||||
| 				if (sigmap(current_bit) == sigmap(last_bit)){ | ||||
| 					wen_to_width[current_bit] += 1; | ||||
| 				} else { | ||||
| 					lof_wen.append_bit(current_bit); | ||||
| 					wen_to_width[current_bit] = 1; | ||||
| 				} | ||||
| 				last_bit = current_bit; | ||||
| 			} | ||||
| 			//   make something like:
 | ||||
| 			//   always @(posedge clk)
 | ||||
| 			//      if (wr_en_bit) memid[w_addr][??] <= w_data[??];
 | ||||
| 			//   ...
 | ||||
| 			n = 0; | ||||
| 			for (auto &wen_bit : lof_wen) { | ||||
| 				wen_width = wen_to_width[wen_bit]; | ||||
| 				if (wen_bit != RTLIL::SigBit(false)) | ||||
| 			for (int i = 0; i < GetSize(sig_wr_en); i++) | ||||
| 			{ | ||||
| 				int start_i = i, width = 1; | ||||
| 				SigBit wen_bit = sig_wr_en[i]; | ||||
| 
 | ||||
| 				while (i+1 < GetSize(sig_wr_en) && sigmap(sig_wr_en[i+1]) == sigmap(wen_bit)) | ||||
| 					i++, width++; | ||||
| 
 | ||||
| 				if (wen_bit == State::S0) | ||||
| 					continue; | ||||
| 
 | ||||
| 				std::ostringstream os; | ||||
| 				if (wen_bit != State::S1) | ||||
| 				{ | ||||
| 					std::ostringstream os; | ||||
| 					if (wen_bit != RTLIL::SigBit(true)) | ||||
| 					{ | ||||
| 						os << stringf("if ("); | ||||
| 						dump_sigspec(os, wen_bit); | ||||
| 						os << stringf(") "); | ||||
| 					} | ||||
| 					os << stringf("%s[", mem_id.c_str()); | ||||
| 					dump_sigspec(os, sig_wr_addr); | ||||
| 					if (wen_width == width) | ||||
| 						os << stringf("] <= "); | ||||
| 					else | ||||
| 						os << stringf("][%d:%d] <= ", n+wen_width-1, n); | ||||
| 					dump_sigspec(os, sig_wr_data.extract(n, wen_width)); | ||||
| 					os << stringf(";\n"); | ||||
| 					clk_to_lof_body[clk_domain_str].push_back(os.str()); | ||||
| 					os << stringf("if ("); | ||||
| 					dump_sigspec(os, wen_bit); | ||||
| 					os << stringf(") "); | ||||
| 				} | ||||
| 				n += wen_width; | ||||
| 				os << stringf("%s[", mem_id.c_str()); | ||||
| 				dump_sigspec(os, sig_wr_addr); | ||||
| 				if (width == GetSize(sig_wr_en)) | ||||
| 					os << stringf("] <= "); | ||||
| 				else | ||||
| 					os << stringf("][%d:%d] <= ", i, start_i); | ||||
| 				dump_sigspec(os, sig_wr_data.extract(start_i, width)); | ||||
| 				os << stringf(";\n"); | ||||
| 				clk_to_lof_body[clk_domain_str].push_back(os.str()); | ||||
| 			} | ||||
| 		} | ||||
| 		// Output Verilog that looks something like this:
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue