@@ -298,7 +298,7 @@ bool check_public_name(RTLIL::IdString id)
298298 return true ;
299299}
300300
301- bool rmunused_module_signals (RTLIL::Module *module , bool purge_mode, bool verbose)
301+ bool rmunused_module_signals (RTLIL::Module *module , bool purge_mode, bool x_mode, bool verbose)
302302{
303303 // `register_signals` and `connected_signals` will help us decide later on
304304 // on picking representatives out of groups of connected signals
@@ -311,39 +311,48 @@ bool rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos
311311 if (ct_reg.cell_known (cell->type )) {
312312 bool clk2fflogic = cell->get_bool_attribute (ID (clk2fflogic));
313313 for (auto &it2 : cell->connections ())
314- if (clk2fflogic ? it2.first == ID::D : ct_reg.cell_output (cell->type , it2.first ))
315- register_signals.add (it2.second );
316- }
317- for (auto &it2 : cell->connections ()) {
318- connected_signals.add (it2.second );
319- if (!ct_all.cell_known (cell->type ) || ct_all.cell_output (cell->type , it2.first ))
320- maybe_driven_signals.push_back (it2.second );
314+ if (clk2fflogic ? it2.first == ID::D : ct_reg.cell_output (cell->type , it2.first ))
315+ register_signals.add (it2.second );
321316 }
317+ for (auto &it2 : cell->connections ())
318+ connected_signals.add (it2.second );
322319 }
323320
324321 SigMap assign_map (module );
325- SigPool maybe_driven_signals_bits;
322+ if (x_mode) {
323+ for (auto [_, cell] : module ->cells_ )
324+ for (auto [port, sig] : cell->connections ())
325+ if (!ct_all.cell_known (cell->type ) || ct_all.cell_output (cell->type , port)) {
326+ log_debug (" cell %s drives sig %s\n " , log_id (cell), log_signal (sig));
327+ maybe_driven_signals.push_back (sig);
328+ }
329+
330+ SigPool maybe_driven_signals_bits;
326331
327- for (auto sig : maybe_driven_signals) {
328- for (auto bit : sig) {
329- maybe_driven_signals_bits.add (assign_map (bit));
332+ for (auto sig : maybe_driven_signals) {
333+ for (auto bit : sig) {
334+ maybe_driven_signals_bits.add (assign_map (bit));
335+ log_debug (" bit %s (rep %s) is driven by cell output\n " , log_signal (sig), log_signal (assign_map (sig)));
336+ }
330337 }
331- }
332- for (auto &it : module ->wires_ ) {
333- RTLIL::SigSpec sig = it.second ;
334- if (it.second ->port_id != 0 ) {
335- maybe_driven_signals_bits.add (assign_map (sig));
338+ for (auto &it : module ->wires_ ) {
339+ RTLIL::SigSpec sig = it.second ;
340+ if (it.second ->port_id != 0 ) {
341+ maybe_driven_signals_bits.add (assign_map (sig));
342+ log_debug (" bit %s (rep %s) is driven by port input\n " , log_signal (sig), log_signal (assign_map (sig)));
343+ }
336344 }
337- }
338- for ( auto &it : module -> wires_ ) {
339- RTLIL::SigSpec sig = it. second ;
340- for ( auto bit : sig ) {
341- if (!maybe_driven_signals_bits. check ( assign_map (bit))) {
342- log ( " add conn %s <-> %s to assign_map\n " , log_signal (bit), log_signal ( SigBit (State::Sx) ));
343- assign_map. add (bit, SigBit (State::Sx));
345+ for ( auto &it : module -> wires_ ) {
346+ RTLIL::SigSpec sig = it. second ;
347+ for ( auto bit : sig) {
348+ if (!maybe_driven_signals_bits. check ( assign_map ( bit)) ) {
349+ log_debug ( " add conn %s <-> %s to assign_map\n " , log_signal (bit), log_signal ( SigBit (State::Sx)));
350+ assign_map. add (bit, SigBit (State::Sx));
351+ }
344352 }
345353 }
346354 }
355+
347356 // construct a pool of wires which are directly driven by a known celltype,
348357 // this will influence our choice of representatives
349358 pool<RTLIL::Wire*> direct_wires;
@@ -619,7 +628,7 @@ bool rmunused_module_init(RTLIL::Module *module, bool verbose)
619628 return did_something;
620629}
621630
622- void rmunused_module (RTLIL::Module *module , bool purge_mode, bool verbose, bool rminit)
631+ void rmunused_module (RTLIL::Module *module , bool purge_mode, bool x_mode, bool verbose, bool rminit)
623632{
624633 if (verbose)
625634 log (" Finding unused cells or wires in module %s..\n " , module ->name .c_str ());
@@ -644,10 +653,10 @@ void rmunused_module(RTLIL::Module *module, bool purge_mode, bool verbose, bool
644653 module ->design ->scratchpad_set_bool (" opt.did_something" , true );
645654
646655 rmunused_module_cells (module , verbose);
647- while (rmunused_module_signals (module , purge_mode, verbose)) { }
656+ while (rmunused_module_signals (module , purge_mode, x_mode, verbose)) { }
648657
649658 if (rminit && rmunused_module_init (module , verbose))
650- while (rmunused_module_signals (module , purge_mode, verbose)) { }
659+ while (rmunused_module_signals (module , purge_mode, x_mode, verbose)) { }
651660}
652661
653662struct OptCleanPass : public Pass {
@@ -668,10 +677,14 @@ struct OptCleanPass : public Pass {
668677 log (" -purge\n " );
669678 log (" also remove internal nets if they have a public name\n " );
670679 log (" \n " );
680+ log (" -x\n " );
681+ log (" handle unconnected bits as x-bit driven\n " );
682+ log (" \n " );
671683 }
672684 void execute (std::vector<std::string> args, RTLIL::Design *design) override
673685 {
674686 bool purge_mode = false ;
687+ bool x_mode = false ;
675688
676689 log_header (design, " Executing OPT_CLEAN pass (remove unused cells and wires).\n " );
677690 log_push ();
@@ -682,6 +695,10 @@ struct OptCleanPass : public Pass {
682695 purge_mode = true ;
683696 continue ;
684697 }
698+ if (args[argidx] == " -x" ) {
699+ x_mode = true ;
700+ continue ;
701+ }
685702 break ;
686703 }
687704 extra_args (args, argidx, design);
@@ -700,7 +717,7 @@ struct OptCleanPass : public Pass {
700717 for (auto module : design->selected_whole_modules_warn ()) {
701718 if (module ->has_processes_warn ())
702719 continue ;
703- rmunused_module (module , purge_mode, true , true );
720+ rmunused_module (module , purge_mode, x_mode, true , true );
704721 }
705722
706723 if (count_rm_cells > 0 || count_rm_wires > 0 )
@@ -737,13 +754,18 @@ struct CleanPass : public Pass {
737754 void execute (std::vector<std::string> args, RTLIL::Design *design) override
738755 {
739756 bool purge_mode = false ;
757+ bool x_mode = false ;
740758
741759 size_t argidx;
742760 for (argidx = 1 ; argidx < args.size (); argidx++) {
743761 if (args[argidx] == " -purge" ) {
744762 purge_mode = true ;
745763 continue ;
746764 }
765+ if (args[argidx] == " -x" ) {
766+ x_mode = true ;
767+ continue ;
768+ }
747769 break ;
748770 }
749771 extra_args (args, argidx, design);
@@ -762,7 +784,7 @@ struct CleanPass : public Pass {
762784 for (auto module : design->selected_whole_modules ()) {
763785 if (module ->has_processes ())
764786 continue ;
765- rmunused_module (module , purge_mode, ys_debug (), true );
787+ rmunused_module (module , purge_mode, x_mode, ys_debug (), true );
766788 }
767789
768790 log_suppressed ();
0 commit comments