mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 03:32:29 +00:00 
			
		
		
		
	Consistent $mux undef handling
* Change simlib's $mux cell to use the ternary operator as $_MUX_ already does * Stop opt_expr -keepdc from changing S=x to S=0 * Change const eval of $mux and $pmux to match the updated simlib (fixes sim) * The sat behavior of $mux already matches the updated simlib The verilog frontend uses $mux for the ternary operators and this changes all interpreations of the $mux cell (that I found) to match the verilog simulation behavior for the ternary operator. For 'if' and 'case' expressions the frontend may also use $mux but uses $eqx if the verilog simulation behavior is requested with the '-ifx' option. For $pmux there is a remaining mismatch between the sat behavior and the simlib behavior. Resolving this requires more discussion, as the $pmux cell does not directly correspond to a specific verilog construct.
This commit is contained in:
		
							parent
							
								
									4f4cff0080
								
							
						
					
					
						commit
						c77b7343d0
					
				
					 5 changed files with 38 additions and 15 deletions
				
			
		|  | @ -609,6 +609,36 @@ RTLIL::Const RTLIL::const_neg(const RTLIL::Const &arg1, const RTLIL::Const&, boo | ||||||
| 	return RTLIL::const_sub(zero, arg1_ext, true, signed1, result_len); | 	return RTLIL::const_sub(zero, arg1_ext, true, signed1, result_len); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | RTLIL::Const RTLIL::const_mux(const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3) | ||||||
|  | { | ||||||
|  | 	log_assert(arg2.size() == arg1.size()); | ||||||
|  | 	if (arg3[0] == State::S0) | ||||||
|  | 		return arg1; | ||||||
|  | 	else if (arg3[0] == State::S1) | ||||||
|  | 		return arg2; | ||||||
|  | 
 | ||||||
|  | 	RTLIL::Const ret = arg1; | ||||||
|  | 	for (int i = 0; i < ret.size(); i++) | ||||||
|  | 		if (ret[i] != arg2[i]) | ||||||
|  | 			ret[i] = State::Sx; | ||||||
|  | 	return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | RTLIL::Const RTLIL::const_pmux(const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3) | ||||||
|  | { | ||||||
|  | 	if (arg3.is_fully_zero()) | ||||||
|  | 		return arg1; | ||||||
|  | 
 | ||||||
|  | 	if (!arg3.is_onehot()) | ||||||
|  | 		return RTLIL::Const(State::Sx, arg1.size()); | ||||||
|  | 
 | ||||||
|  | 	for (int i = 0; i < arg3.size(); i++) | ||||||
|  | 		if (arg3[i] == State::S1) | ||||||
|  | 			return RTLIL::Const(std::vector<RTLIL::State>(arg2.bits.begin() + i*arg1.bits.size(), arg2.bits.begin() + (i+1)*arg1.bits.size())); | ||||||
|  | 
 | ||||||
|  | 	log_abort(); // unreachable
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
| RTLIL::Const RTLIL::const_bmux(const RTLIL::Const &arg1, const RTLIL::Const &arg2) | RTLIL::Const RTLIL::const_bmux(const RTLIL::Const &arg1, const RTLIL::Const &arg2) | ||||||
| { | { | ||||||
| 	std::vector<RTLIL::State> t = arg1.bits; | 	std::vector<RTLIL::State> t = arg1.bits; | ||||||
|  |  | ||||||
|  | @ -488,16 +488,10 @@ struct CellTypes | ||||||
| 
 | 
 | ||||||
| 	static RTLIL::Const eval(RTLIL::Cell *cell, const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3, bool *errp = nullptr) | 	static RTLIL::Const eval(RTLIL::Cell *cell, const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3, bool *errp = nullptr) | ||||||
| 	{ | 	{ | ||||||
| 		if (cell->type.in(ID($mux), ID($pmux), ID($_MUX_))) { | 		if (cell->type.in(ID($mux), ID($_MUX_))) | ||||||
| 			RTLIL::Const ret = arg1; | 			return const_mux(arg1, arg2, arg3); | ||||||
| 			for (size_t i = 0; i < arg3.bits.size(); i++) | 		if (cell->type == ID($pmux)) | ||||||
| 				if (arg3.bits[i] == RTLIL::State::S1) { | 			return const_pmux(arg1, arg2, arg3); | ||||||
| 					std::vector<RTLIL::State> bits(arg2.bits.begin() + i*arg1.bits.size(), arg2.bits.begin() + (i+1)*arg1.bits.size()); |  | ||||||
| 					ret = RTLIL::Const(bits); |  | ||||||
| 				} |  | ||||||
| 			return ret; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		if (cell->type == ID($_AOI3_)) | 		if (cell->type == ID($_AOI3_)) | ||||||
| 			return eval_not(const_or(const_and(arg1, arg2, false, false, 1), arg3, false, false, 1)); | 			return eval_not(const_or(const_and(arg1, arg2, false, false, 1), arg3, false, false, 1)); | ||||||
| 		if (cell->type == ID($_OAI3_)) | 		if (cell->type == ID($_OAI3_)) | ||||||
|  |  | ||||||
|  | @ -500,6 +500,8 @@ namespace RTLIL | ||||||
| 	RTLIL::Const const_pos         (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len); | 	RTLIL::Const const_pos         (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len); | ||||||
| 	RTLIL::Const const_neg         (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len); | 	RTLIL::Const const_neg         (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len); | ||||||
| 
 | 
 | ||||||
|  | 	RTLIL::Const const_mux         (const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3); | ||||||
|  | 	RTLIL::Const const_pmux        (const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3); | ||||||
| 	RTLIL::Const const_bmux        (const RTLIL::Const &arg1, const RTLIL::Const &arg2); | 	RTLIL::Const const_bmux        (const RTLIL::Const &arg1, const RTLIL::Const &arg2); | ||||||
| 	RTLIL::Const const_demux       (const RTLIL::Const &arg1, const RTLIL::Const &arg2); | 	RTLIL::Const const_demux       (const RTLIL::Const &arg1, const RTLIL::Const &arg2); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1494,7 +1494,7 @@ skip_identity: | ||||||
| 			RTLIL::SigSpec input = assign_map(cell->getPort(ID::S)); | 			RTLIL::SigSpec input = assign_map(cell->getPort(ID::S)); | ||||||
| 			RTLIL::SigSpec inA = assign_map(cell->getPort(ID::A)); | 			RTLIL::SigSpec inA = assign_map(cell->getPort(ID::A)); | ||||||
| 			RTLIL::SigSpec inB = assign_map(cell->getPort(ID::B)); | 			RTLIL::SigSpec inB = assign_map(cell->getPort(ID::B)); | ||||||
| 			if (input.is_fully_const()) | 			if (input.is_fully_const() && (!keepdc || input.is_fully_def())) | ||||||
| 				ACTION_DO(ID::Y, input.as_bool() ? cell->getPort(ID::B) : cell->getPort(ID::A)); | 				ACTION_DO(ID::Y, input.as_bool() ? cell->getPort(ID::B) : cell->getPort(ID::A)); | ||||||
| 			else if (inA == inB) | 			else if (inA == inB) | ||||||
| 				ACTION_DO(ID::Y, cell->getPort(ID::A)); | 				ACTION_DO(ID::Y, cell->getPort(ID::A)); | ||||||
|  |  | ||||||
|  | @ -1282,10 +1282,7 @@ input S; | ||||||
| output reg [WIDTH-1:0] Y; | output reg [WIDTH-1:0] Y; | ||||||
| 
 | 
 | ||||||
| always @* begin | always @* begin | ||||||
| 	if (S) | 	assign Y = S ? B : A; | ||||||
| 		Y = B; |  | ||||||
| 	else |  | ||||||
| 		Y = A; |  | ||||||
| end | end | ||||||
| 
 | 
 | ||||||
| endmodule | endmodule | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue