mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-11-04 05:19:11 +00:00 
			
		
		
		
	abstract: -value MVP, use buffer-normalized mode
This commit is contained in:
		
							parent
							
								
									4637fa74e3
								
							
						
					
					
						commit
						6027030215
					
				
					 2 changed files with 121 additions and 62 deletions
				
			
		| 
						 | 
					@ -57,70 +57,70 @@ bool abstract_state(Module* mod, Cell* cell, Wire* enable, bool enable_pol) {
 | 
				
			||||||
	return true;
 | 
						return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool abstract_value(Module* mod, Wire* wire, Wire* enable, bool enable_pol) {
 | 
					struct AbstractPortCtx {
 | 
				
			||||||
	// (void)mod->addMux(NEW_ID,
 | 
					 | 
				
			||||||
	// 	mux_a,
 | 
					 | 
				
			||||||
	// 	mux_b,
 | 
					 | 
				
			||||||
	// 	enable,
 | 
					 | 
				
			||||||
	// 	abstracted);
 | 
					 | 
				
			||||||
	// 	cell->setPort(ID::D, SigSpec(abstracted));
 | 
					 | 
				
			||||||
	return false;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct AbstractInitCtx {
 | 
					 | 
				
			||||||
	Module* mod;
 | 
						Module* mod;
 | 
				
			||||||
	SigMap sigmap;
 | 
						SigMap sigmap;
 | 
				
			||||||
	pool<SigBit> init_bits;
 | 
						pool<std::pair<Cell*, IdString>> outs;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void collect_init_bits_cells(AbstractInitCtx& ctx) {
 | 
					void collect_selected_ports(AbstractPortCtx& ctx) {
 | 
				
			||||||
	// TODO Should this discriminate between FFs and other cells?
 | 
						for (Cell* cell : ctx.mod->cells()) {
 | 
				
			||||||
	for (auto cell : ctx.mod->selected_cells()) {
 | 
							for (auto& conn : cell->connections()) {
 | 
				
			||||||
		// Add all sigbits on all cell outputs to init_bits
 | 
								// we bufnorm
 | 
				
			||||||
		for (auto &conn : cell->connections()) {
 | 
								log_assert(conn.second.is_wire() || conn.second.is_fully_const());
 | 
				
			||||||
			if (cell->output(conn.first)) {
 | 
								if (conn.second.is_wire() && cell->output(conn.first))
 | 
				
			||||||
				for (auto bit : conn.second) {
 | 
									if (ctx.mod->selected(cell) || ctx.mod->selected(conn.second.as_wire()))
 | 
				
			||||||
					log_debug("init: cell %s output %s\n", cell->name.c_str(), log_signal(bit));
 | 
										ctx.outs.insert(std::make_pair(cell, conn.first));
 | 
				
			||||||
					ctx.init_bits.insert(ctx.sigmap(bit));
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void collect_init_bits_wires(AbstractInitCtx& ctx) {
 | 
					unsigned int abstract_value(Module* mod, Wire* enable, bool enable_pol) {
 | 
				
			||||||
	for (auto wire : ctx.mod->selected_wires()) {
 | 
						AbstractPortCtx ctx {mod, SigMap(mod), {}};
 | 
				
			||||||
		auto canonical = ctx.sigmap(wire);
 | 
						collect_selected_ports(ctx);
 | 
				
			||||||
		// Find canonical drivers of all the wire bits and add them to init_bits
 | 
						unsigned int changed = 0;
 | 
				
			||||||
		for (auto bit : canonical.bits()) {
 | 
						for (auto [cell, port] : ctx.outs) {
 | 
				
			||||||
			log_debug("init: wire %s bit %s\n", wire->name.c_str(), log_signal(bit));
 | 
							SigSpec sig = cell->getPort(port);
 | 
				
			||||||
			ctx.init_bits.insert(ctx.sigmap(bit));
 | 
							log_assert(sig.is_wire());
 | 
				
			||||||
 | 
							Wire* original = mod->addWire(NEW_ID, sig.size());
 | 
				
			||||||
 | 
							cell->setPort(port, original);
 | 
				
			||||||
 | 
							auto anyseq = mod->Anyseq(NEW_ID, sig.size());
 | 
				
			||||||
 | 
							// This code differs from abstract_state
 | 
				
			||||||
 | 
							// in that we reuse the original signal as the mux output,
 | 
				
			||||||
 | 
							// not input
 | 
				
			||||||
 | 
							SigSpec mux_a, mux_b;
 | 
				
			||||||
 | 
							if (enable_pol) {
 | 
				
			||||||
 | 
								mux_a = original;
 | 
				
			||||||
 | 
								mux_b = anyseq;
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								mux_a = anyseq;
 | 
				
			||||||
 | 
								mux_b = original;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							(void)mod->addMux(NEW_ID,
 | 
				
			||||||
 | 
								mux_a,
 | 
				
			||||||
 | 
								mux_b,
 | 
				
			||||||
 | 
								enable,
 | 
				
			||||||
 | 
								sig);
 | 
				
			||||||
 | 
							changed++;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						return changed;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
unsigned int abstract_init(Module* mod) {
 | 
					unsigned int abstract_init(Module* mod) {
 | 
				
			||||||
	AbstractInitCtx ctx {mod, SigMap(mod), pool<SigBit>()};
 | 
						AbstractPortCtx ctx {mod, SigMap(mod), {}};
 | 
				
			||||||
	pool<SigBit> init_bits;
 | 
						collect_selected_ports(ctx);
 | 
				
			||||||
	collect_init_bits_cells(ctx);
 | 
					
 | 
				
			||||||
	collect_init_bits_wires(ctx);
 | 
					 | 
				
			||||||
	unsigned int changed = 0;
 | 
						unsigned int changed = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (SigBit bit : ctx.init_bits) {
 | 
						for (auto [cell, port] : ctx.outs) {
 | 
				
			||||||
next_sigbit:
 | 
							SigSpec sig = cell->getPort(port);
 | 
				
			||||||
		if (!bit.is_wire() || !bit.wire->has_attribute(ID::init))
 | 
							log_assert(sig.is_wire());
 | 
				
			||||||
 | 
							if (!sig.as_wire()->has_attribute(ID::init))
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Const init = bit.wire->attributes.at(ID::init);
 | 
							Const init = sig.as_wire()->attributes.at(ID::init);
 | 
				
			||||||
		std::vector<RTLIL::State>& bits = init.bits();
 | 
							sig.as_wire()->attributes.erase(ID::init);
 | 
				
			||||||
		bits[bit.offset] = RTLIL::State::Sx;
 | 
							changed += sig.size();
 | 
				
			||||||
		changed++;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		for (auto bit : bits)
 | 
					 | 
				
			||||||
			if (bit != RTLIL::State::Sx)
 | 
					 | 
				
			||||||
				goto next_sigbit;
 | 
					 | 
				
			||||||
		// All bits are Sx, erase init attribute entirely
 | 
					 | 
				
			||||||
		bit.wire->attributes.erase(ID::init);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return changed;
 | 
						return changed;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -174,6 +174,7 @@ struct AbstractPass : public Pass {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		extra_args(args, argidx, design);
 | 
							extra_args(args, argidx, design);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							design->bufNormalize(true);
 | 
				
			||||||
		unsigned int changed = 0;
 | 
							unsigned int changed = 0;
 | 
				
			||||||
		if ((mode == State) || (mode == Value)) {
 | 
							if ((mode == State) || (mode == Value)) {
 | 
				
			||||||
			if (!enable_name.length())
 | 
								if (!enable_name.length())
 | 
				
			||||||
| 
						 | 
					@ -191,14 +192,13 @@ struct AbstractPass : public Pass {
 | 
				
			||||||
						if (ct.cell_types.count(cell->type))
 | 
											if (ct.cell_types.count(cell->type))
 | 
				
			||||||
							changed += abstract_state(mod, cell, enable_wire, enable_pol);
 | 
												changed += abstract_state(mod, cell, enable_wire, enable_pol);
 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
					// Value
 | 
										changed += abstract_value(mod, enable_wire, enable_pol);
 | 
				
			||||||
					for (auto wire : mod->selected_wires()) {
 | 
					 | 
				
			||||||
						changed += abstract_value(mod, wire, enable_wire, enable_pol);
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
					log_cmd_error("Unsupported (TODO)\n");
 | 
					 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			log("Abstracted %d cells.\n", changed);
 | 
								if (mode == State)
 | 
				
			||||||
 | 
									log("Abstracted %d cells.\n", changed);
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
									log("Abstracted %d values.\n", changed);
 | 
				
			||||||
		} else if (mode == Initial) {
 | 
							} else if (mode == Initial) {
 | 
				
			||||||
			for (auto mod : design->selected_modules()) {
 | 
								for (auto mod : design->selected_modules()) {
 | 
				
			||||||
				changed += abstract_init(mod);
 | 
									changed += abstract_init(mod);
 | 
				
			||||||
| 
						 | 
					@ -207,6 +207,7 @@ struct AbstractPass : public Pass {
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			log_cmd_error("No mode selected, see help message\n");
 | 
								log_cmd_error("No mode selected, see help message\n");
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							design->bufNormalize(false);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
} AbstractPass;
 | 
					} AbstractPass;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,9 +1,9 @@
 | 
				
			||||||
read_verilog <<EOT
 | 
					read_verilog <<EOT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module half_clock (CLK, Q);
 | 
					module half_clock (CLK, Q, magic);
 | 
				
			||||||
	input CLK;
 | 
						input CLK;
 | 
				
			||||||
	output reg Q;
 | 
						output reg Q;
 | 
				
			||||||
	reg magic;
 | 
						input magic;
 | 
				
			||||||
	always @(posedge CLK)
 | 
						always @(posedge CLK)
 | 
				
			||||||
		Q <= ~Q;
 | 
							Q <= ~Q;
 | 
				
			||||||
endmodule
 | 
					endmodule
 | 
				
			||||||
| 
						 | 
					@ -12,16 +12,16 @@ EOT
 | 
				
			||||||
proc
 | 
					proc
 | 
				
			||||||
# show -prefix before_base
 | 
					# show -prefix before_base
 | 
				
			||||||
abstract -state -enablen magic
 | 
					abstract -state -enablen magic
 | 
				
			||||||
check
 | 
					check -assert
 | 
				
			||||||
# show -prefix after_base
 | 
					# show -prefix after_base
 | 
				
			||||||
 | 
					
 | 
				
			||||||
design -reset
 | 
					design -reset
 | 
				
			||||||
read_verilog <<EOT
 | 
					read_verilog <<EOT
 | 
				
			||||||
module half_clock_en (CLK, E, Q);
 | 
					module half_clock_en (CLK, E, Q, magic);
 | 
				
			||||||
	input CLK;
 | 
						input CLK;
 | 
				
			||||||
	input E;
 | 
						input E;
 | 
				
			||||||
	output reg Q;
 | 
						output reg Q;
 | 
				
			||||||
	reg magic;
 | 
						input magic;
 | 
				
			||||||
	always @(posedge CLK)
 | 
						always @(posedge CLK)
 | 
				
			||||||
        if (E)
 | 
					        if (E)
 | 
				
			||||||
            Q <= ~Q;
 | 
					            Q <= ~Q;
 | 
				
			||||||
| 
						 | 
					@ -33,7 +33,7 @@ opt_expr
 | 
				
			||||||
opt_dff
 | 
					opt_dff
 | 
				
			||||||
# show -prefix before_en
 | 
					# show -prefix before_en
 | 
				
			||||||
abstract -state -enablen magic
 | 
					abstract -state -enablen magic
 | 
				
			||||||
check
 | 
					check -assert
 | 
				
			||||||
# show -prefix after_en
 | 
					# show -prefix after_en
 | 
				
			||||||
 | 
					
 | 
				
			||||||
design -reset
 | 
					design -reset
 | 
				
			||||||
| 
						 | 
					@ -50,9 +50,35 @@ proc
 | 
				
			||||||
opt_expr
 | 
					opt_expr
 | 
				
			||||||
opt_dff
 | 
					opt_dff
 | 
				
			||||||
dump
 | 
					dump
 | 
				
			||||||
 | 
					select -none
 | 
				
			||||||
abstract -init
 | 
					abstract -init
 | 
				
			||||||
check
 | 
					select -clear
 | 
				
			||||||
 | 
					check -assert
 | 
				
			||||||
 | 
					# dump
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					design -reset
 | 
				
			||||||
 | 
					read_verilog <<EOT
 | 
				
			||||||
 | 
					module main (input [3:0] baz);
 | 
				
			||||||
 | 
					  reg foo;
 | 
				
			||||||
 | 
					  reg bar;
 | 
				
			||||||
 | 
					  assign foo = bar;
 | 
				
			||||||
 | 
					  assign bar = baz[0];
 | 
				
			||||||
 | 
					  reg aaa = 1'b1;
 | 
				
			||||||
 | 
					  always @(posedge bar)
 | 
				
			||||||
 | 
					  	aaa <= ~aaa;
 | 
				
			||||||
 | 
					endmodule
 | 
				
			||||||
 | 
					EOT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					proc -noopt
 | 
				
			||||||
 | 
					# show -prefix before_init
 | 
				
			||||||
dump
 | 
					dump
 | 
				
			||||||
 | 
					select -none
 | 
				
			||||||
 | 
					abstract -init
 | 
				
			||||||
 | 
					select -clear
 | 
				
			||||||
 | 
					# show -prefix after_init
 | 
				
			||||||
 | 
					dump
 | 
				
			||||||
 | 
					check -assert
 | 
				
			||||||
 | 
					# dump
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
design -reset
 | 
					design -reset
 | 
				
			||||||
| 
						 | 
					@ -85,6 +111,38 @@ opt_expr
 | 
				
			||||||
opt_dff
 | 
					opt_dff
 | 
				
			||||||
# show -prefix before_a
 | 
					# show -prefix before_a
 | 
				
			||||||
abstract -state -enablen magic
 | 
					abstract -state -enablen magic
 | 
				
			||||||
check
 | 
					check -assert
 | 
				
			||||||
# show -prefix after_a
 | 
					# show -prefix after_a
 | 
				
			||||||
# opt_clean
 | 
					# opt_clean
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					design -reset
 | 
				
			||||||
 | 
					read_verilog <<EOT
 | 
				
			||||||
 | 
					module this_adff (CLK, ARST, D, Q, magic);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					parameter WIDTH = 2;
 | 
				
			||||||
 | 
					parameter CLK_POLARITY = 1'b1;
 | 
				
			||||||
 | 
					parameter ARST_POLARITY = 1'b1;
 | 
				
			||||||
 | 
					parameter ARST_VALUE = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					input CLK, ARST, magic;
 | 
				
			||||||
 | 
					input [WIDTH-1:0] D;
 | 
				
			||||||
 | 
					output reg [WIDTH-1:0] Q;
 | 
				
			||||||
 | 
					wire pos_clk = CLK == CLK_POLARITY;
 | 
				
			||||||
 | 
					wire pos_arst = ARST == ARST_POLARITY;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					always @(posedge pos_clk, posedge pos_arst) begin
 | 
				
			||||||
 | 
						if (pos_arst)
 | 
				
			||||||
 | 
							Q <= ARST_VALUE;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							Q <= D;
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					endmodule
 | 
				
			||||||
 | 
					EOT
 | 
				
			||||||
 | 
					proc
 | 
				
			||||||
 | 
					# show -prefix before_value
 | 
				
			||||||
 | 
					abstract -value -enablen magic
 | 
				
			||||||
 | 
					check -assert
 | 
				
			||||||
 | 
					clean
 | 
				
			||||||
 | 
					# show -prefix after_value
 | 
				
			||||||
 | 
					# dump
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue