mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-11-03 21:09:12 +00:00 
			
		
		
		
	create duplicate IOFFs if multiple output ports are connected to the same register
This commit is contained in:
		
							parent
							
								
									25b400982b
								
							
						
					
					
						commit
						303a386ecc
					
				
					 3 changed files with 93 additions and 15 deletions
				
			
		| 
						 | 
				
			
			@ -29,7 +29,17 @@ struct QlIoffPass : public Pass {
 | 
			
		|||
		if (!module)
 | 
			
		||||
			return;
 | 
			
		||||
		modwalker.setup(module);
 | 
			
		||||
		pool<RTLIL::Cell *> cells_to_replace;
 | 
			
		||||
		pool<RTLIL::Cell *> input_ffs;
 | 
			
		||||
		dict<RTLIL::Wire *, std::vector<Cell*>> output_ffs;
 | 
			
		||||
		dict<SigBit, pool<SigBit>> output_bit_aliases;
 | 
			
		||||
 | 
			
		||||
		for (Wire* wire : module->wires())
 | 
			
		||||
			if (wire->port_output) {
 | 
			
		||||
				output_ffs[wire].resize(wire->width, nullptr);
 | 
			
		||||
				for (SigBit bit : SigSpec(wire))
 | 
			
		||||
					output_bit_aliases[modwalker.sigmap(bit)].insert(bit);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		for (auto cell : module->selected_cells()) {
 | 
			
		||||
			if (cell->type.in(ID(dffsre), ID(sdffsre))) {
 | 
			
		||||
				log_debug("Checking cell %s.\n", cell->name.c_str());
 | 
			
		||||
| 
						 | 
				
			
			@ -53,32 +63,62 @@ struct QlIoffPass : public Pass {
 | 
			
		|||
						log_debug("not promoting: D has other consumers\n");
 | 
			
		||||
						continue;
 | 
			
		||||
					}
 | 
			
		||||
					cells_to_replace.insert(cell);
 | 
			
		||||
					continue; // no need to check Q if we already put it on the list
 | 
			
		||||
					input_ffs.insert(cell);
 | 
			
		||||
					continue; // prefer input FFs over output FFs
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				SigSpec q = cell->getPort(ID::Q);
 | 
			
		||||
				log_assert(GetSize(q) == 1);
 | 
			
		||||
				if (modwalker.has_outputs(q)) {
 | 
			
		||||
				if (modwalker.has_outputs(q) && !modwalker.has_consumers(q)) {
 | 
			
		||||
					log_debug("Cell %s is potentially eligible for promotion to output IOFF.\n", cell->name.c_str());
 | 
			
		||||
					// check that q_sig has no other consumers
 | 
			
		||||
					pool<ModWalker::PortBit> portbits;
 | 
			
		||||
					modwalker.get_consumers(portbits, q);
 | 
			
		||||
					if (GetSize(portbits) > 0) {
 | 
			
		||||
						log_debug("not promoting: Q has other consumers\n");
 | 
			
		||||
						continue;
 | 
			
		||||
					for (SigBit bit : output_bit_aliases[modwalker.sigmap(q)]) {
 | 
			
		||||
						log_assert(bit.is_wire());
 | 
			
		||||
						output_ffs[bit.wire][bit.offset] = cell;
 | 
			
		||||
					}
 | 
			
		||||
					cells_to_replace.insert(cell);
 | 
			
		||||
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		for (auto cell : cells_to_replace) {
 | 
			
		||||
			log("Promoting register %s to IOFF.\n", log_signal(cell->getPort(ID::Q)));
 | 
			
		||||
		for (auto cell : input_ffs) {
 | 
			
		||||
			log("Promoting register %s to input IOFF.\n", log_signal(cell->getPort(ID::Q)));
 | 
			
		||||
			cell->type = ID(dff);
 | 
			
		||||
			cell->unsetPort(ID::E);
 | 
			
		||||
			cell->unsetPort(ID::R);
 | 
			
		||||
			cell->unsetPort(ID::S);
 | 
			
		||||
		}
 | 
			
		||||
		for (auto & [old_port_output, ioff_cells] : output_ffs) {
 | 
			
		||||
			if (std::any_of(ioff_cells.begin(), ioff_cells.end(), [](Cell * c) { return c != nullptr; }))
 | 
			
		||||
			{
 | 
			
		||||
				// create replacement output wire
 | 
			
		||||
				RTLIL::Wire* new_port_output = module->addWire(NEW_ID, old_port_output->width);
 | 
			
		||||
				new_port_output->start_offset = old_port_output->start_offset;
 | 
			
		||||
				module->swap_names(old_port_output, new_port_output);
 | 
			
		||||
				std::swap(old_port_output->port_id, new_port_output->port_id);
 | 
			
		||||
				std::swap(old_port_output->port_input, new_port_output->port_input);
 | 
			
		||||
				std::swap(old_port_output->port_output, new_port_output->port_output);
 | 
			
		||||
				std::swap(old_port_output->upto, new_port_output->upto);
 | 
			
		||||
				std::swap(old_port_output->is_signed, new_port_output->is_signed);
 | 
			
		||||
				std::swap(old_port_output->attributes, new_port_output->attributes);
 | 
			
		||||
 | 
			
		||||
				// create new output FFs
 | 
			
		||||
				SigSpec sig_o(old_port_output);
 | 
			
		||||
				SigSpec sig_n(new_port_output);
 | 
			
		||||
				for (int i = 0; i < new_port_output->width; i++) {
 | 
			
		||||
					if (ioff_cells[i]) {
 | 
			
		||||
						log("Promoting %s to output IOFF.\n", log_signal(sig_n[i]));
 | 
			
		||||
 | 
			
		||||
						RTLIL::Cell *new_cell = module->addCell(NEW_ID, ID(dff));
 | 
			
		||||
						new_cell->setPort(ID::C, ioff_cells[i]->getPort(ID::C));
 | 
			
		||||
						new_cell->setPort(ID::D, ioff_cells[i]->getPort(ID::D));
 | 
			
		||||
						new_cell->setPort(ID::Q, sig_n[i]);
 | 
			
		||||
						new_cell->set_bool_attribute(ID::keep);
 | 
			
		||||
					} else {
 | 
			
		||||
						module->connect(sig_n[i], sig_o[i]);
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
} QlIoffPass;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -334,9 +334,10 @@ struct SynthQuickLogicPass : public ScriptPass {
 | 
			
		|||
			run("opt_lut");
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		if (check_label("iomap", "(for qlf_k6n10f)") && (family == "qlf_k6n10f" || help_mode)) {
 | 
			
		||||
		if (check_label("iomap", "(for qlf_k6n10f, skip if -noioff)") && (family == "qlf_k6n10f" || help_mode)) {
 | 
			
		||||
			if (ioff || help_mode) {
 | 
			
		||||
				run("ql_ioff", "(unless -noioff)");
 | 
			
		||||
				run("ql_ioff");
 | 
			
		||||
				run("opt_clean");
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue