mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-11-04 13:29:12 +00:00 
			
		
		
		
	abc9: respect (* keep *) on cells
This commit is contained in:
		
							parent
							
								
									9ec948f396
								
							
						
					
					
						commit
						a6d4ea7463
					
				
					 3 changed files with 87 additions and 62 deletions
				
			
		| 
						 | 
					@ -186,74 +186,76 @@ struct XAigerWriter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		dict<IdString,dict<IdString,int>> arrival_cache;
 | 
							dict<IdString,dict<IdString,int>> arrival_cache;
 | 
				
			||||||
		for (auto cell : module->cells()) {
 | 
							for (auto cell : module->cells()) {
 | 
				
			||||||
			if (cell->type == "$_NOT_")
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				SigBit A = sigmap(cell->getPort("\\A").as_bit());
 | 
					 | 
				
			||||||
				SigBit Y = sigmap(cell->getPort("\\Y").as_bit());
 | 
					 | 
				
			||||||
				unused_bits.erase(A);
 | 
					 | 
				
			||||||
				undriven_bits.erase(Y);
 | 
					 | 
				
			||||||
				not_map[Y] = A;
 | 
					 | 
				
			||||||
				continue;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if (cell->type == "$_AND_")
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				SigBit A = sigmap(cell->getPort("\\A").as_bit());
 | 
					 | 
				
			||||||
				SigBit B = sigmap(cell->getPort("\\B").as_bit());
 | 
					 | 
				
			||||||
				SigBit Y = sigmap(cell->getPort("\\Y").as_bit());
 | 
					 | 
				
			||||||
				unused_bits.erase(A);
 | 
					 | 
				
			||||||
				unused_bits.erase(B);
 | 
					 | 
				
			||||||
				undriven_bits.erase(Y);
 | 
					 | 
				
			||||||
				and_map[Y] = make_pair(A, B);
 | 
					 | 
				
			||||||
				continue;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if (cell->type == "$__ABC9_FF_" &&
 | 
					 | 
				
			||||||
					// The presence of an abc9_mergeability attribute indicates
 | 
					 | 
				
			||||||
					//   that we do want to pass this flop to ABC
 | 
					 | 
				
			||||||
					cell->attributes.count("\\abc9_mergeability"))
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				SigBit D = sigmap(cell->getPort("\\D").as_bit());
 | 
					 | 
				
			||||||
				SigBit Q = sigmap(cell->getPort("\\Q").as_bit());
 | 
					 | 
				
			||||||
				unused_bits.erase(D);
 | 
					 | 
				
			||||||
				undriven_bits.erase(Q);
 | 
					 | 
				
			||||||
				alias_map[Q] = D;
 | 
					 | 
				
			||||||
				auto r YS_ATTRIBUTE(unused) = ff_bits.insert(std::make_pair(D, cell));
 | 
					 | 
				
			||||||
				log_assert(r.second);
 | 
					 | 
				
			||||||
				continue;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			RTLIL::Module* inst_module = module->design->module(cell->type);
 | 
								RTLIL::Module* inst_module = module->design->module(cell->type);
 | 
				
			||||||
			if (inst_module) {
 | 
								if (!cell->has_keep_attr()) {
 | 
				
			||||||
				auto it = cell->attributes.find("\\abc9_box_seq");
 | 
									if (cell->type == "$_NOT_")
 | 
				
			||||||
				if (it != cell->attributes.end()) {
 | 
									{
 | 
				
			||||||
					int abc9_box_seq = it->second.as_int();
 | 
										SigBit A = sigmap(cell->getPort("\\A").as_bit());
 | 
				
			||||||
					if (GetSize(box_list) <= abc9_box_seq)
 | 
										SigBit Y = sigmap(cell->getPort("\\Y").as_bit());
 | 
				
			||||||
						box_list.resize(abc9_box_seq+1);
 | 
										unused_bits.erase(A);
 | 
				
			||||||
					box_list[abc9_box_seq] = cell;
 | 
										undriven_bits.erase(Y);
 | 
				
			||||||
					// Only flop boxes may have arrival times
 | 
										not_map[Y] = A;
 | 
				
			||||||
					if (!inst_module->get_bool_attribute("\\abc9_flop"))
 | 
										continue;
 | 
				
			||||||
						continue;
 | 
					 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				auto &cell_arrivals = arrival_cache[cell->type];
 | 
									if (cell->type == "$_AND_")
 | 
				
			||||||
				for (const auto &conn : cell->connections()) {
 | 
									{
 | 
				
			||||||
					auto r = cell_arrivals.insert(conn.first);
 | 
										SigBit A = sigmap(cell->getPort("\\A").as_bit());
 | 
				
			||||||
					auto &arrival = r.first->second;
 | 
										SigBit B = sigmap(cell->getPort("\\B").as_bit());
 | 
				
			||||||
					if (r.second) {
 | 
										SigBit Y = sigmap(cell->getPort("\\Y").as_bit());
 | 
				
			||||||
						auto port_wire = inst_module->wire(conn.first);
 | 
										unused_bits.erase(A);
 | 
				
			||||||
						if (port_wire->port_output) {
 | 
										unused_bits.erase(B);
 | 
				
			||||||
							auto it = port_wire->attributes.find("\\abc9_arrival");
 | 
										undriven_bits.erase(Y);
 | 
				
			||||||
							if (it != port_wire->attributes.end()) {
 | 
										and_map[Y] = make_pair(A, B);
 | 
				
			||||||
								if (it->second.flags != 0)
 | 
										continue;
 | 
				
			||||||
									log_error("Attribute 'abc9_arrival' on port '%s' of module '%s' is not an integer.\n", log_id(port_wire), log_id(cell->type));
 | 
									}
 | 
				
			||||||
								arrival = it->second.as_int();
 | 
					
 | 
				
			||||||
 | 
									if (cell->type == "$__ABC9_FF_" &&
 | 
				
			||||||
 | 
											// The presence of an abc9_mergeability attribute indicates
 | 
				
			||||||
 | 
											//   that we do want to pass this flop to ABC
 | 
				
			||||||
 | 
											cell->attributes.count("\\abc9_mergeability"))
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										SigBit D = sigmap(cell->getPort("\\D").as_bit());
 | 
				
			||||||
 | 
										SigBit Q = sigmap(cell->getPort("\\Q").as_bit());
 | 
				
			||||||
 | 
										unused_bits.erase(D);
 | 
				
			||||||
 | 
										undriven_bits.erase(Q);
 | 
				
			||||||
 | 
										alias_map[Q] = D;
 | 
				
			||||||
 | 
										auto r YS_ATTRIBUTE(unused) = ff_bits.insert(std::make_pair(D, cell));
 | 
				
			||||||
 | 
										log_assert(r.second);
 | 
				
			||||||
 | 
										continue;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if (inst_module) {
 | 
				
			||||||
 | 
										auto it = cell->attributes.find("\\abc9_box_seq");
 | 
				
			||||||
 | 
										if (it != cell->attributes.end()) {
 | 
				
			||||||
 | 
											int abc9_box_seq = it->second.as_int();
 | 
				
			||||||
 | 
											if (GetSize(box_list) <= abc9_box_seq)
 | 
				
			||||||
 | 
												box_list.resize(abc9_box_seq+1);
 | 
				
			||||||
 | 
											box_list[abc9_box_seq] = cell;
 | 
				
			||||||
 | 
											// Only flop boxes may have arrival times
 | 
				
			||||||
 | 
											if (!inst_module->get_bool_attribute("\\abc9_flop"))
 | 
				
			||||||
 | 
												continue;
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										auto &cell_arrivals = arrival_cache[cell->type];
 | 
				
			||||||
 | 
										for (const auto &conn : cell->connections()) {
 | 
				
			||||||
 | 
											auto r = cell_arrivals.insert(conn.first);
 | 
				
			||||||
 | 
											auto &arrival = r.first->second;
 | 
				
			||||||
 | 
											if (r.second) {
 | 
				
			||||||
 | 
												auto port_wire = inst_module->wire(conn.first);
 | 
				
			||||||
 | 
												if (port_wire->port_output) {
 | 
				
			||||||
 | 
													auto it = port_wire->attributes.find("\\abc9_arrival");
 | 
				
			||||||
 | 
													if (it != port_wire->attributes.end()) {
 | 
				
			||||||
 | 
														if (it->second.flags != 0)
 | 
				
			||||||
 | 
															log_error("Attribute 'abc9_arrival' on port '%s' of module '%s' is not an integer.\n", log_id(port_wire), log_id(cell->type));
 | 
				
			||||||
 | 
														arrival = it->second.as_int();
 | 
				
			||||||
 | 
													}
 | 
				
			||||||
							}
 | 
												}
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
 | 
											if (arrival)
 | 
				
			||||||
 | 
												for (auto bit : sigmap(conn.second))
 | 
				
			||||||
 | 
													arrival_times[bit] = arrival;
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
					if (arrival)
 | 
					 | 
				
			||||||
						for (auto bit : sigmap(conn.second))
 | 
					 | 
				
			||||||
							arrival_times[bit] = arrival;
 | 
					 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -270,6 +272,9 @@ struct XAigerWriter
 | 
				
			||||||
					for (auto b : c.second) {
 | 
										for (auto b : c.second) {
 | 
				
			||||||
						Wire *w = b.wire;
 | 
											Wire *w = b.wire;
 | 
				
			||||||
						if (!w) continue;
 | 
											if (!w) continue;
 | 
				
			||||||
 | 
											// Do not add as PO if bit is already a PI
 | 
				
			||||||
 | 
											if (input_bits.count(b))
 | 
				
			||||||
 | 
												continue;
 | 
				
			||||||
						if (!w->port_output || !cell_known) {
 | 
											if (!w->port_output || !cell_known) {
 | 
				
			||||||
							SigBit I = sigmap(b);
 | 
												SigBit I = sigmap(b);
 | 
				
			||||||
							if (I != b)
 | 
												if (I != b)
 | 
				
			||||||
| 
						 | 
					@ -431,6 +436,9 @@ struct XAigerWriter
 | 
				
			||||||
		for (const auto &bit : output_bits) {
 | 
							for (const auto &bit : output_bits) {
 | 
				
			||||||
			ordered_outputs[bit] = aig_o++;
 | 
								ordered_outputs[bit] = aig_o++;
 | 
				
			||||||
			int aig;
 | 
								int aig;
 | 
				
			||||||
 | 
								// For inout/keep bits only, the output bit
 | 
				
			||||||
 | 
								//   should be driven by logic, not the PI,
 | 
				
			||||||
 | 
								//   so temporarily swap that out
 | 
				
			||||||
			if (input_bits.count(bit)) {
 | 
								if (input_bits.count(bit)) {
 | 
				
			||||||
				auto it = aig_map.find(bit);
 | 
									auto it = aig_map.find(bit);
 | 
				
			||||||
				int input_aig = it->second;
 | 
									int input_aig = it->second;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -489,6 +489,8 @@ void reintegrate(RTLIL::Module *module)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	std::vector<Cell*> boxes;
 | 
						std::vector<Cell*> boxes;
 | 
				
			||||||
	for (auto cell : module->cells().to_vector()) {
 | 
						for (auto cell : module->cells().to_vector()) {
 | 
				
			||||||
 | 
							if (cell->has_keep_attr())
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
		if (cell->type.in(ID($_AND_), ID($_NOT_), ID($__ABC9_FF_)))
 | 
							if (cell->type.in(ID($_AND_), ID($_NOT_), ID($__ABC9_FF_)))
 | 
				
			||||||
			module->remove(cell);
 | 
								module->remove(cell);
 | 
				
			||||||
		else if (cell->attributes.erase("\\abc9_box_seq"))
 | 
							else if (cell->attributes.erase("\\abc9_box_seq"))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -51,3 +51,18 @@ simplemap
 | 
				
			||||||
equiv_opt -assert abc9 -lut 4
 | 
					equiv_opt -assert abc9 -lut 4
 | 
				
			||||||
design -load postopt
 | 
					design -load postopt
 | 
				
			||||||
select -assert-count 2 t:$lut
 | 
					select -assert-count 2 t:$lut
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					design -reset
 | 
				
			||||||
 | 
					read_verilog -icells <<EOT
 | 
				
			||||||
 | 
					module top(input a, b, output o);
 | 
				
			||||||
 | 
					wire w;
 | 
				
			||||||
 | 
					(* keep *) $_AND_ gate (.Y(w), .A(a), .B(b));
 | 
				
			||||||
 | 
					assign o = ~w;
 | 
				
			||||||
 | 
					endmodule
 | 
				
			||||||
 | 
					EOT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					simplemap
 | 
				
			||||||
 | 
					equiv_opt -assert abc9 -lut 4
 | 
				
			||||||
 | 
					design -load postopt
 | 
				
			||||||
 | 
					select -assert-count 1 t:$lut
 | 
				
			||||||
 | 
					select -assert-count 1 t:$_AND_
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue