2014-02-05 23:59:55 +01:00
/*
* yosys - - Yosys Open SYnthesis Suite
*
2021-06-08 00:39:36 +02:00
* Copyright ( C ) 2012 Claire Xenia Wolf < claire @ yosyshq . com >
2015-07-02 11:14:30 +02:00
*
2014-02-05 23:59:55 +01:00
* Permission to use , copy , modify , and / or distribute this software for any
* purpose with or without fee is hereby granted , provided that the above
* copyright notice and this permission notice appear in all copies .
2015-07-02 11:14:30 +02:00
*
2014-02-05 23:59:55 +01:00
* THE SOFTWARE IS PROVIDED " AS IS " AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS . IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL , DIRECT , INDIRECT , OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE , DATA OR PROFITS , WHETHER IN AN
* ACTION OF CONTRACT , NEGLIGENCE OR OTHER TORTIOUS ACTION , ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE .
*
*/
2025-08-06 03:52:12 +02:00
# include "kernel/yosys.h"
2014-02-06 15:48:42 +01:00
# include "kernel/celltypes.h"
# include "kernel/sigtools.h"
2025-08-06 03:52:12 +02:00
# include "kernel/log_help.h"
2014-02-05 23:59:55 +01:00
2014-09-27 16:17:53 +02:00
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
2014-02-08 21:08:38 +01:00
struct dff_map_info_t {
RTLIL : : SigSpec sig_d , sig_clk , sig_arst ;
bool clk_polarity , arst_polarity ;
RTLIL : : Const arst_value ;
2014-08-02 13:11:01 +02:00
std : : vector < RTLIL : : IdString > cells ;
2014-02-08 21:08:38 +01:00
} ;
struct dff_map_bit_info_t {
RTLIL : : SigBit bit_d , bit_clk , bit_arst ;
bool clk_polarity , arst_polarity ;
RTLIL : : State arst_value ;
RTLIL : : Cell * cell ;
} ;
2014-09-27 16:17:53 +02:00
bool consider_wire ( RTLIL : : Wire * wire , std : : map < RTLIL : : IdString , dff_map_info_t > & dff_dq_map )
2014-02-05 23:59:55 +01:00
{
2014-02-08 21:08:38 +01:00
if ( wire - > name [ 0 ] = = ' $ ' | | dff_dq_map . count ( wire - > name ) )
2014-02-05 23:59:55 +01:00
return false ;
if ( wire - > port_input )
return false ;
return true ;
}
2014-09-27 16:17:53 +02:00
bool consider_cell ( RTLIL : : Design * design , std : : set < RTLIL : : IdString > & dff_cells , RTLIL : : Cell * cell )
2014-02-05 23:59:55 +01:00
{
2014-02-08 21:08:38 +01:00
if ( cell - > name [ 0 ] = = ' $ ' | | dff_cells . count ( cell - > name ) )
2014-02-05 23:59:55 +01:00
return false ;
2020-03-28 07:18:09 +01:00
if ( cell - > type [ 0 ] = = ' \\ ' & & ( design - > module ( cell - > type ) = = nullptr ) )
2014-02-05 23:59:55 +01:00
return false ;
return true ;
}
2014-09-27 16:17:53 +02:00
bool compare_wires ( RTLIL : : Wire * wire1 , RTLIL : : Wire * wire2 )
2014-02-05 23:59:55 +01:00
{
log_assert ( wire1 - > name = = wire2 - > name ) ;
if ( wire1 - > width ! = wire2 - > width )
return false ;
return true ;
}
2014-09-27 16:17:53 +02:00
bool compare_cells ( RTLIL : : Cell * cell1 , RTLIL : : Cell * cell2 )
2014-02-05 23:59:55 +01:00
{
log_assert ( cell1 - > name = = cell2 - > name ) ;
if ( cell1 - > type ! = cell2 - > type )
return false ;
if ( cell1 - > parameters ! = cell2 - > parameters )
return false ;
return true ;
}
2014-09-27 16:17:53 +02:00
void find_dff_wires ( std : : set < RTLIL : : IdString > & dff_wires , RTLIL : : Module * module )
2014-02-06 15:48:42 +01:00
{
CellTypes ct ;
ct . setup_internals_mem ( ) ;
ct . setup_stdcells_mem ( ) ;
SigMap sigmap ( module ) ;
SigPool dffsignals ;
2020-03-30 18:16:16 +02:00
for ( auto cell : module - > cells ( ) ) {
2026-06-12 00:18:53 +02:00
if ( ct . cell_known ( cell - > type_impl ) & & cell - > hasPort ( TW : : Q ) )
2026-06-10 19:22:53 +02:00
dffsignals . add ( sigmap ( cell - > getPort ( TW : : Q ) ) ) ;
2014-02-06 15:48:42 +01:00
}
2020-03-30 18:16:16 +02:00
for ( auto w : module - > wires ( ) ) {
if ( dffsignals . check_any ( w ) )
dff_wires . insert ( w - > name ) ;
2014-02-06 15:48:42 +01:00
}
}
2020-03-30 20:00:19 +02:00
void create_dff_dq_map ( std : : map < RTLIL : : IdString , dff_map_info_t > & map , RTLIL : : Module * module )
2014-02-08 21:08:38 +01:00
{
std : : map < RTLIL : : SigBit , dff_map_bit_info_t > bit_info ;
SigMap sigmap ( module ) ;
2020-03-30 19:56:07 +02:00
for ( auto cell : module - > selected_cells ( ) )
2014-02-08 21:08:38 +01:00
{
dff_map_bit_info_t info ;
info . bit_d = RTLIL : : State : : Sm ;
info . bit_clk = RTLIL : : State : : Sm ;
info . bit_arst = RTLIL : : State : : Sm ;
info . clk_polarity = false ;
info . arst_polarity = false ;
info . arst_value = RTLIL : : State : : Sm ;
2020-03-30 18:16:16 +02:00
info . cell = cell ;
2014-02-08 21:08:38 +01:00
2026-06-12 00:18:53 +02:00
if ( info . cell - > type = = TW ( $ dff ) ) {
2026-06-10 19:22:53 +02:00
info . bit_clk = sigmap ( info . cell - > getPort ( TW : : CLK ) ) . as_bit ( ) ;
2020-04-02 18:51:32 +02:00
info . clk_polarity = info . cell - > parameters . at ( ID : : CLK_POLARITY ) . as_bool ( ) ;
2026-06-10 19:22:53 +02:00
std : : vector < RTLIL : : SigBit > sig_d = sigmap ( info . cell - > getPort ( TW : : D ) ) . to_sigbit_vector ( ) ;
std : : vector < RTLIL : : SigBit > sig_q = sigmap ( info . cell - > getPort ( TW : : Q ) ) . to_sigbit_vector ( ) ;
2014-02-08 21:08:38 +01:00
for ( size_t i = 0 ; i < sig_d . size ( ) ; i + + ) {
info . bit_d = sig_d . at ( i ) ;
bit_info [ sig_q . at ( i ) ] = info ;
}
continue ;
}
2026-06-12 00:18:53 +02:00
if ( info . cell - > type = = TW ( $ adff ) ) {
2026-06-10 19:22:53 +02:00
info . bit_clk = sigmap ( info . cell - > getPort ( TW : : CLK ) ) . as_bit ( ) ;
info . bit_arst = sigmap ( info . cell - > getPort ( TW : : ARST ) ) . as_bit ( ) ;
2020-04-02 18:51:32 +02:00
info . clk_polarity = info . cell - > parameters . at ( ID : : CLK_POLARITY ) . as_bool ( ) ;
info . arst_polarity = info . cell - > parameters . at ( ID : : ARST_POLARITY ) . as_bool ( ) ;
2026-06-10 19:22:53 +02:00
std : : vector < RTLIL : : SigBit > sig_d = sigmap ( info . cell - > getPort ( TW : : D ) ) . to_sigbit_vector ( ) ;
std : : vector < RTLIL : : SigBit > sig_q = sigmap ( info . cell - > getPort ( TW : : Q ) ) . to_sigbit_vector ( ) ;
2024-10-09 19:39:45 +02:00
std : : vector < RTLIL : : State > arst_value = info . cell - > parameters . at ( ID : : ARST_VALUE ) . to_bits ( ) ;
2014-02-08 21:08:38 +01:00
for ( size_t i = 0 ; i < sig_d . size ( ) ; i + + ) {
info . bit_d = sig_d . at ( i ) ;
info . arst_value = arst_value . at ( i ) ;
bit_info [ sig_q . at ( i ) ] = info ;
}
continue ;
}
2026-06-12 00:18:53 +02:00
if ( info . cell - > type . in ( TW ( $ _DFF_N_ ) , TW ( $ _DFF_P_ ) ) ) {
2026-06-10 19:22:53 +02:00
info . bit_clk = sigmap ( info . cell - > getPort ( TW : : C ) ) . as_bit ( ) ;
2026-06-12 00:18:53 +02:00
info . clk_polarity = info . cell - > type = = TW ( $ _DFF_P_ ) ;
2026-06-10 19:22:53 +02:00
info . bit_d = sigmap ( info . cell - > getPort ( TW : : D ) ) . as_bit ( ) ;
bit_info [ sigmap ( info . cell - > getPort ( TW : : Q ) ) . as_bit ( ) ] = info ;
2014-02-08 21:08:38 +01:00
continue ;
}
2019-08-07 21:20:08 +02:00
if ( info . cell - > type . size ( ) = = 10 & & info . cell - > type . begins_with ( " $_DFF_ " ) ) {
2026-06-10 19:22:53 +02:00
info . bit_clk = sigmap ( info . cell - > getPort ( TW : : C ) ) . as_bit ( ) ;
info . bit_arst = sigmap ( info . cell - > getPort ( TW : : R ) ) . as_bit ( ) ;
2014-02-08 21:08:38 +01:00
info . clk_polarity = info . cell - > type [ 6 ] = = ' P ' ;
info . arst_polarity = info . cell - > type [ 7 ] = = ' P ' ;
info . arst_value = info . cell - > type [ 0 ] = = ' 1 ' ? RTLIL : : State : : S1 : RTLIL : : State : : S0 ;
2026-06-10 19:22:53 +02:00
info . bit_d = sigmap ( info . cell - > getPort ( TW : : D ) ) . as_bit ( ) ;
bit_info [ sigmap ( info . cell - > getPort ( TW : : Q ) ) . as_bit ( ) ] = info ;
2014-02-08 21:08:38 +01:00
continue ;
}
}
2014-08-02 13:11:01 +02:00
std : : map < RTLIL : : IdString , dff_map_info_t > empty_dq_map ;
2020-03-30 18:16:16 +02:00
for ( auto w : module - > wires ( ) )
2014-02-08 21:08:38 +01:00
{
2020-03-30 18:16:16 +02:00
if ( ! consider_wire ( w , empty_dq_map ) )
2014-02-08 21:08:38 +01:00
continue ;
2020-03-30 18:16:16 +02:00
std : : vector < RTLIL : : SigBit > bits_q = sigmap ( w ) . to_sigbit_vector ( ) ;
2014-02-08 21:08:38 +01:00
std : : vector < RTLIL : : SigBit > bits_d ;
std : : vector < RTLIL : : State > arst_value ;
std : : set < RTLIL : : Cell * > cells ;
if ( bits_q . empty ( ) | | ! bit_info . count ( bits_q . front ( ) ) )
continue ;
dff_map_bit_info_t ref_info = bit_info . at ( bits_q . front ( ) ) ;
for ( auto & bit : bits_q ) {
if ( ! bit_info . count ( bit ) )
break ;
dff_map_bit_info_t info = bit_info . at ( bit ) ;
if ( info . bit_clk ! = ref_info . bit_clk )
break ;
if ( info . bit_arst ! = ref_info . bit_arst )
break ;
if ( info . clk_polarity ! = ref_info . clk_polarity )
break ;
if ( info . arst_polarity ! = ref_info . arst_polarity )
break ;
bits_d . push_back ( info . bit_d ) ;
arst_value . push_back ( info . arst_value ) ;
cells . insert ( info . cell ) ;
}
if ( bits_d . size ( ) ! = bits_q . size ( ) )
continue ;
dff_map_info_t info ;
info . sig_d = bits_d ;
info . sig_clk = ref_info . bit_clk ;
info . sig_arst = ref_info . bit_arst ;
info . clk_polarity = ref_info . clk_polarity ;
info . arst_polarity = ref_info . arst_polarity ;
2014-02-08 21:26:40 +01:00
info . arst_value = arst_value ;
2014-02-08 21:08:38 +01:00
for ( auto it : cells )
info . cells . push_back ( it - > name ) ;
2020-03-30 18:16:16 +02:00
map [ w - > name ] = info ;
2014-02-08 21:08:38 +01:00
}
}
2014-09-27 16:17:53 +02:00
RTLIL : : Wire * add_new_wire ( RTLIL : : Module * module , RTLIL : : IdString name , int width = 1 )
2014-02-09 11:07:46 +01:00
{
2014-07-26 21:16:05 +02:00
if ( module - > count_id ( name ) )
2026-06-12 00:18:53 +02:00
log_error ( " Attempting to create wire %s, but a wire of this name exists already! Hint: Try another value for -sep. \n " , design - > twines . unescaped_str ( name ) ) ;
2014-07-26 21:16:05 +02:00
return module - > addWire ( name , width ) ;
2014-02-09 11:07:46 +01:00
}
2014-02-05 23:59:55 +01:00
struct ExposePass : public Pass {
ExposePass ( ) : Pass ( " expose " , " convert internal signals to module ports " ) { }
2025-08-06 03:52:12 +02:00
bool formatted_help ( ) override {
auto * help = PrettyHelp : : get_current ( ) ;
help - > set_group ( " passes/cmds " ) ;
return false ;
}
2020-06-19 01:34:52 +02:00
void help ( ) override
2014-02-05 23:59:55 +01:00
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log ( " \n " ) ;
log ( " expose [options] [selection] \n " ) ;
log ( " \n " ) ;
log ( " This command exposes all selected internal signals of a module as additional \n " ) ;
log ( " outputs. \n " ) ;
log ( " \n " ) ;
2014-02-06 15:48:42 +01:00
log ( " -dff \n " ) ;
log ( " only consider wires that are directly driven by register cell. \n " ) ;
log ( " \n " ) ;
2014-02-09 11:07:46 +01:00
log ( " -cut \n " ) ;
log ( " when exposing a wire, create an input/output pair and cut the internal \n " ) ;
log ( " signal path at that wire. \n " ) ;
log ( " \n " ) ;
2018-03-12 13:52:52 +01:00
log ( " -input \n " ) ;
log ( " when exposing a wire, create an input port and disconnect the internal \n " ) ;
log ( " driver. \n " ) ;
log ( " \n " ) ;
2014-02-05 23:59:55 +01:00
log ( " -shared \n " ) ;
2015-08-14 10:56:05 +02:00
log ( " only expose those signals that are shared among the selected modules. \n " ) ;
log ( " this is useful for preparing modules for equivalence checking. \n " ) ;
2014-02-05 23:59:55 +01:00
log ( " \n " ) ;
log ( " -evert \n " ) ;
log ( " also turn connections to instances of other modules to additional \n " ) ;
log ( " inputs and outputs and remove the module instances. \n " ) ;
log ( " \n " ) ;
2014-02-08 21:08:38 +01:00
log ( " -evert-dff \n " ) ;
log ( " turn flip-flops to sets of inputs and outputs. \n " ) ;
log ( " \n " ) ;
2014-02-09 11:07:46 +01:00
log ( " -sep <separator> \n " ) ;
log ( " when creating new wire/port names, the original object name is suffixed \n " ) ;
log ( " with this separator (default: '.') and the port name or a type \n " ) ;
log ( " designator for the exposed signal. \n " ) ;
log ( " \n " ) ;
2014-02-05 23:59:55 +01:00
}
2020-06-19 01:34:52 +02:00
void execute ( std : : vector < std : : string > args , RTLIL : : Design * design ) override
2014-02-05 23:59:55 +01:00
{
bool flag_shared = false ;
bool flag_evert = false ;
2014-02-06 15:48:42 +01:00
bool flag_dff = false ;
2014-02-09 11:07:46 +01:00
bool flag_cut = false ;
2018-03-12 13:52:52 +01:00
bool flag_input = false ;
2014-02-08 21:08:38 +01:00
bool flag_evert_dff = false ;
2014-02-09 11:07:46 +01:00
std : : string sep = " . " ;
2014-02-05 23:59:55 +01:00
2016-04-21 23:28:37 +02:00
log_header ( design , " Executing EXPOSE pass (exposing internal signals as outputs). \n " ) ;
2014-05-28 18:05:38 +02:00
2014-02-05 23:59:55 +01:00
size_t argidx ;
for ( argidx = 1 ; argidx < args . size ( ) ; argidx + + )
{
if ( args [ argidx ] = = " -shared " ) {
flag_shared = true ;
continue ;
}
if ( args [ argidx ] = = " -evert " ) {
flag_evert = true ;
continue ;
}
2014-02-06 15:48:42 +01:00
if ( args [ argidx ] = = " -dff " ) {
flag_dff = true ;
continue ;
}
2020-06-29 14:45:49 +02:00
if ( args [ argidx ] = = " -cut " ) {
if ( flag_input )
log_cmd_error ( " Options -cut and -input are mutually exclusive. \n " ) ;
2014-02-09 11:07:46 +01:00
flag_cut = true ;
continue ;
}
2020-06-29 14:45:49 +02:00
if ( args [ argidx ] = = " -input " ) {
if ( flag_cut )
log_cmd_error ( " Options -cut and -input are mutually exclusive. \n " ) ;
2018-03-12 13:52:52 +01:00
flag_input = true ;
continue ;
}
2014-02-08 21:08:38 +01:00
if ( args [ argidx ] = = " -evert-dff " ) {
flag_evert_dff = true ;
continue ;
}
2014-02-09 11:07:46 +01:00
if ( args [ argidx ] = = " -sep " & & argidx + 1 < args . size ( ) ) {
sep = args [ + + argidx ] ;
continue ;
}
2014-02-05 23:59:55 +01:00
break ;
}
extra_args ( args , argidx , design ) ;
2014-02-09 11:07:46 +01:00
CellTypes ct ( design ) ;
2014-08-02 13:11:01 +02:00
std : : map < RTLIL : : Module * , std : : map < RTLIL : : IdString , dff_map_info_t > > dff_dq_maps ;
std : : map < RTLIL : : Module * , std : : set < RTLIL : : IdString > > dff_cells ;
2014-02-08 21:08:38 +01:00
if ( flag_evert_dff )
{
RTLIL : : Module * first_module = NULL ;
2014-08-02 13:11:01 +02:00
std : : set < RTLIL : : IdString > shared_dff_wires ;
2014-02-08 21:08:38 +01:00
2020-03-30 19:56:07 +02:00
for ( auto mod : design - > selected_modules ( ) )
2014-02-08 21:08:38 +01:00
{
2020-03-30 20:00:19 +02:00
create_dff_dq_map ( dff_dq_maps [ mod ] , mod ) ;
2014-02-08 21:08:38 +01:00
if ( ! flag_shared )
continue ;
if ( first_module = = NULL ) {
2020-03-28 07:18:09 +01:00
for ( auto & it : dff_dq_maps [ mod ] )
2014-02-08 21:08:38 +01:00
shared_dff_wires . insert ( it . first ) ;
2020-03-28 07:18:09 +01:00
first_module = mod ;
2014-02-08 21:08:38 +01:00
} else {
2014-08-02 13:11:01 +02:00
std : : set < RTLIL : : IdString > new_shared_dff_wires ;
2014-02-08 21:08:38 +01:00
for ( auto & it : shared_dff_wires ) {
2020-03-28 07:18:09 +01:00
if ( ! dff_dq_maps [ mod ] . count ( it ) )
2014-02-08 21:08:38 +01:00
continue ;
2020-03-30 18:16:16 +02:00
if ( ! compare_wires ( first_module - > wire ( it ) , mod - > wire ( it ) ) )
2014-02-08 21:08:38 +01:00
continue ;
new_shared_dff_wires . insert ( it ) ;
}
shared_dff_wires . swap ( new_shared_dff_wires ) ;
}
}
if ( flag_shared )
for ( auto & map_it : dff_dq_maps )
{
2014-08-02 13:11:01 +02:00
std : : map < RTLIL : : IdString , dff_map_info_t > new_map ;
2014-02-08 21:08:38 +01:00
for ( auto & it : map_it . second )
if ( shared_dff_wires . count ( it . first ) )
new_map [ it . first ] = it . second ;
map_it . second . swap ( new_map ) ;
}
for ( auto & it1 : dff_dq_maps )
for ( auto & it2 : it1 . second )
for ( auto & it3 : it2 . second . cells )
dff_cells [ it1 . first ] . insert ( it3 ) ;
}
2014-08-02 13:11:01 +02:00
std : : set < RTLIL : : IdString > shared_wires , shared_cells ;
std : : set < RTLIL : : IdString > used_names ;
2014-02-05 23:59:55 +01:00
if ( flag_shared )
{
RTLIL : : Module * first_module = NULL ;
2020-03-30 19:56:07 +02:00
for ( auto module : design - > selected_modules ( ) )
2014-02-05 23:59:55 +01:00
{
2014-08-02 13:11:01 +02:00
std : : set < RTLIL : : IdString > dff_wires ;
2014-02-06 15:48:42 +01:00
if ( flag_dff )
find_dff_wires ( dff_wires , module ) ;
2014-02-05 23:59:55 +01:00
if ( first_module = = NULL )
{
2020-03-30 18:16:16 +02:00
for ( auto w : module - > wires ( ) )
if ( design - > selected ( module , w ) & & consider_wire ( w , dff_dq_maps [ module ] ) )
if ( ! flag_dff | | dff_wires . count ( w - > name ) )
shared_wires . insert ( w - > name ) ;
2014-02-05 23:59:55 +01:00
if ( flag_evert )
2020-03-30 18:16:16 +02:00
for ( auto cell : module - > cells ( ) )
if ( design - > selected ( module , cell ) & & consider_cell ( design , dff_cells [ module ] , cell ) )
shared_cells . insert ( cell - > name ) ;
2014-02-05 23:59:55 +01:00
first_module = module ;
}
else
{
2014-08-02 13:11:01 +02:00
std : : vector < RTLIL : : IdString > delete_shared_wires , delete_shared_cells ;
2014-02-05 23:59:55 +01:00
for ( auto & it : shared_wires )
{
RTLIL : : Wire * wire ;
2020-03-30 18:16:16 +02:00
if ( module - > wire ( it ) = = nullptr )
2014-02-05 23:59:55 +01:00
goto delete_shared_wire ;
2020-03-30 18:16:16 +02:00
wire = module - > wire ( it ) ;
2014-02-05 23:59:55 +01:00
if ( ! design - > selected ( module , wire ) )
goto delete_shared_wire ;
2014-02-08 21:08:38 +01:00
if ( ! consider_wire ( wire , dff_dq_maps [ module ] ) )
2014-02-05 23:59:55 +01:00
goto delete_shared_wire ;
2020-03-30 18:16:16 +02:00
if ( ! compare_wires ( first_module - > wire ( it ) , wire ) )
2014-02-05 23:59:55 +01:00
goto delete_shared_wire ;
2014-02-06 15:48:42 +01:00
if ( flag_dff & & ! dff_wires . count ( it ) )
goto delete_shared_wire ;
2014-02-05 23:59:55 +01:00
if ( 0 )
delete_shared_wire :
delete_shared_wires . push_back ( it ) ;
}
if ( flag_evert )
for ( auto & it : shared_cells )
{
RTLIL : : Cell * cell ;
2020-03-30 18:16:16 +02:00
if ( module - > cell ( it ) = = nullptr )
2014-02-05 23:59:55 +01:00
goto delete_shared_cell ;
2020-03-30 18:16:16 +02:00
cell = module - > cell ( it ) ;
2014-02-05 23:59:55 +01:00
if ( ! design - > selected ( module , cell ) )
goto delete_shared_cell ;
2014-02-08 21:08:38 +01:00
if ( ! consider_cell ( design , dff_cells [ module ] , cell ) )
2014-02-05 23:59:55 +01:00
goto delete_shared_cell ;
2020-03-30 18:16:16 +02:00
if ( ! compare_cells ( first_module - > cell ( it ) , cell ) )
2014-02-05 23:59:55 +01:00
goto delete_shared_cell ;
if ( 0 )
delete_shared_cell :
delete_shared_cells . push_back ( it ) ;
}
for ( auto & it : delete_shared_wires )
shared_wires . erase ( it ) ;
for ( auto & it : delete_shared_cells )
shared_cells . erase ( it ) ;
}
}
}
2020-03-30 19:56:07 +02:00
for ( auto module : design - > selected_modules ( ) )
2014-02-05 23:59:55 +01:00
{
2014-08-02 13:11:01 +02:00
std : : set < RTLIL : : IdString > dff_wires ;
2014-02-06 15:48:42 +01:00
if ( flag_dff & & ! flag_shared )
find_dff_wires ( dff_wires , module ) ;
2014-02-09 11:07:46 +01:00
SigMap sigmap ( module ) ;
SigMap out_to_in_map ;
2020-06-29 11:56:43 +02:00
std : : map < RTLIL : : Wire * , RTLIL : : IdString > wire_map ;
2020-03-30 18:16:16 +02:00
for ( auto w : module - > wires ( ) )
2014-02-05 23:59:55 +01:00
{
if ( flag_shared ) {
2020-03-30 18:16:16 +02:00
if ( shared_wires . count ( w - > name ) = = 0 )
2014-02-05 23:59:55 +01:00
continue ;
} else {
2020-03-30 18:16:16 +02:00
if ( ! design - > selected ( module , w ) | | ! consider_wire ( w , dff_dq_maps [ module ] ) )
2014-02-05 23:59:55 +01:00
continue ;
2020-03-30 18:16:16 +02:00
if ( flag_dff & & ! dff_wires . count ( w - > name ) )
2014-02-06 15:48:42 +01:00
continue ;
2014-02-05 23:59:55 +01:00
}
2018-03-12 13:52:52 +01:00
if ( flag_input )
{
2020-03-30 18:16:16 +02:00
if ( ! w - > port_input ) {
w - > port_input = true ;
2026-05-15 15:16:09 +02:00
log ( " New module port: %s/%s \n " , module , w ) ;
2020-06-29 11:56:43 +02:00
wire_map [ w ] = NEW_ID ;
2018-03-12 13:52:52 +01:00
}
}
else
{
2020-03-30 18:16:16 +02:00
if ( ! w - > port_output ) {
w - > port_output = true ;
2026-05-15 15:16:09 +02:00
log ( " New module port: %s/%s \n " , module , w ) ;
2018-03-12 13:52:52 +01:00
}
if ( flag_cut ) {
2020-06-29 11:56:43 +02:00
wire_map [ w ] = w - > name . str ( ) + sep + " i " ;
2018-03-12 13:52:52 +01:00
}
2014-02-05 23:59:55 +01:00
}
2018-03-12 13:52:52 +01:00
}
2014-02-09 11:07:46 +01:00
2018-03-12 13:52:52 +01:00
if ( flag_input )
{
2020-06-29 14:42:48 +02:00
for ( auto & wm : wire_map )
{
RTLIL : : Wire * in_wire = module - > addWire ( wm . second , GetSize ( wm . first ) ) ;
out_to_in_map . add ( wm . first , in_wire ) ;
}
2020-03-30 18:16:16 +02:00
for ( auto cell : module - > cells ( ) ) {
2026-06-12 00:18:53 +02:00
if ( ! ct . cell_known ( cell - > type_impl ) )
2018-03-12 13:52:52 +01:00
continue ;
2020-03-30 18:16:16 +02:00
for ( auto & conn : cell - > connections_ )
2026-06-12 00:18:53 +02:00
if ( ct . cell_output ( cell - > type_impl , conn . first ) )
2018-03-12 13:52:52 +01:00
conn . second = out_to_in_map ( sigmap ( conn . second ) ) ;
2014-02-09 11:07:46 +01:00
}
2018-03-12 13:52:52 +01:00
for ( auto & conn : module - > connections_ )
2019-05-06 13:30:43 +02:00
conn . first = out_to_in_map ( conn . first ) ;
2014-02-09 11:07:46 +01:00
}
if ( flag_cut )
{
2020-06-29 14:42:48 +02:00
for ( auto & wm : wire_map )
{
RTLIL : : Wire * in_wire = add_new_wire ( module , wm . second , wm . first - > width ) ;
in_wire - > port_input = true ;
out_to_in_map . add ( sigmap ( wm . first ) , in_wire ) ;
}
2020-03-30 18:16:16 +02:00
for ( auto cell : module - > cells ( ) ) {
2026-06-12 00:18:53 +02:00
if ( ! ct . cell_known ( cell - > type_impl ) )
2014-02-09 11:07:46 +01:00
continue ;
2020-03-30 18:16:16 +02:00
for ( auto & conn : cell - > connections_ )
2026-06-12 00:18:53 +02:00
if ( ct . cell_input ( cell - > type_impl , conn . first ) )
2014-02-09 11:07:46 +01:00
conn . second = out_to_in_map ( sigmap ( conn . second ) ) ;
}
2014-07-26 15:57:57 +02:00
for ( auto & conn : module - > connections_ )
2014-02-09 11:07:46 +01:00
conn . second = out_to_in_map ( sigmap ( conn . second ) ) ;
2014-02-05 23:59:55 +01:00
}
2014-02-08 21:08:38 +01:00
std : : set < RTLIL : : SigBit > set_q_bits ;
for ( auto & dq : dff_dq_maps [ module ] )
{
2020-03-30 18:16:16 +02:00
if ( module - > wire ( dq . first ) = = nullptr )
2014-02-08 21:08:38 +01:00
continue ;
2020-03-30 18:16:16 +02:00
RTLIL : : Wire * wire = module - > wire ( dq . first ) ;
2014-02-08 21:08:38 +01:00
std : : set < RTLIL : : SigBit > wire_bits_set = sigmap ( wire ) . to_sigbit_set ( ) ;
std : : vector < RTLIL : : SigBit > wire_bits_vec = sigmap ( wire ) . to_sigbit_vector ( ) ;
dff_map_info_t & info = dq . second ;
2014-07-26 21:16:05 +02:00
RTLIL : : Wire * wire_dummy_q = add_new_wire ( module , NEW_ID , 0 ) ;
2014-02-08 21:08:38 +01:00
for ( auto & cell_name : info . cells ) {
2020-03-30 18:16:16 +02:00
RTLIL : : Cell * cell = module - > cell ( cell_name ) ;
2026-06-10 19:22:53 +02:00
std : : vector < RTLIL : : SigBit > cell_q_bits = sigmap ( cell - > getPort ( TW : : Q ) ) . to_sigbit_vector ( ) ;
2014-02-08 21:08:38 +01:00
for ( auto & bit : cell_q_bits )
if ( wire_bits_set . count ( bit ) )
bit = RTLIL : : SigBit ( wire_dummy_q , wire_dummy_q - > width + + ) ;
2026-06-10 19:22:53 +02:00
cell - > setPort ( TW : : Q , cell_q_bits ) ;
2014-02-08 21:08:38 +01:00
}
2014-08-02 13:11:01 +02:00
RTLIL : : Wire * wire_q = add_new_wire ( module , wire - > name . str ( ) + sep + " q " , wire - > width ) ;
2014-02-08 21:08:38 +01:00
wire_q - > port_input = true ;
2026-05-15 15:16:09 +02:00
log ( " New module port: %s/%s \n " , module , wire_q ) ;
2014-02-08 21:08:38 +01:00
RTLIL : : SigSig connect_q ;
for ( size_t i = 0 ; i < wire_bits_vec . size ( ) ; i + + ) {
if ( set_q_bits . count ( wire_bits_vec [ i ] ) )
continue ;
connect_q . first . append ( wire_bits_vec [ i ] ) ;
connect_q . second . append ( RTLIL : : SigBit ( wire_q , i ) ) ;
set_q_bits . insert ( wire_bits_vec [ i ] ) ;
}
2014-07-26 14:32:50 +02:00
module - > connect ( connect_q ) ;
2014-02-08 21:08:38 +01:00
2014-08-02 13:11:01 +02:00
RTLIL : : Wire * wire_d = add_new_wire ( module , wire - > name . str ( ) + sep + " d " , wire - > width ) ;
2014-02-08 21:08:38 +01:00
wire_d - > port_output = true ;
2026-05-15 15:16:09 +02:00
log ( " New module port: %s/%s \n " , module , wire_d ) ;
2014-07-26 14:32:50 +02:00
module - > connect ( RTLIL : : SigSig ( wire_d , info . sig_d ) ) ;
2014-02-08 21:08:38 +01:00
2014-08-02 13:11:01 +02:00
RTLIL : : Wire * wire_c = add_new_wire ( module , wire - > name . str ( ) + sep + " c " ) ;
2014-02-08 21:08:38 +01:00
wire_c - > port_output = true ;
2026-05-15 15:16:09 +02:00
log ( " New module port: %s/%s \n " , module , wire_c ) ;
2014-02-08 21:08:38 +01:00
if ( info . clk_polarity ) {
2014-07-26 14:32:50 +02:00
module - > connect ( RTLIL : : SigSig ( wire_c , info . sig_clk ) ) ;
2014-02-08 21:08:38 +01:00
} else {
2026-06-12 00:18:53 +02:00
RTLIL : : Cell * c = module - > addCell ( NEW_TWINE , TW ( $ not ) ) ;
2020-04-02 18:51:32 +02:00
c - > parameters [ ID : : A_SIGNED ] = 0 ;
c - > parameters [ ID : : A_WIDTH ] = 1 ;
c - > parameters [ ID : : Y_WIDTH ] = 1 ;
2026-06-10 19:22:53 +02:00
c - > setPort ( TW : : A , info . sig_clk ) ;
c - > setPort ( TW : : Y , wire_c ) ;
2014-02-08 21:08:38 +01:00
}
if ( info . sig_arst ! = RTLIL : : State : : Sm )
{
2014-08-02 13:11:01 +02:00
RTLIL : : Wire * wire_r = add_new_wire ( module , wire - > name . str ( ) + sep + " r " ) ;
2014-02-08 21:08:38 +01:00
wire_r - > port_output = true ;
2026-05-15 15:16:09 +02:00
log ( " New module port: %s/%s \n " , module , wire_r ) ;
2014-02-08 21:08:38 +01:00
if ( info . arst_polarity ) {
2014-07-26 14:32:50 +02:00
module - > connect ( RTLIL : : SigSig ( wire_r , info . sig_arst ) ) ;
2014-02-08 21:08:38 +01:00
} else {
2026-06-12 00:18:53 +02:00
RTLIL : : Cell * c = module - > addCell ( NEW_TWINE , TW ( $ not ) ) ;
2020-04-02 18:51:32 +02:00
c - > parameters [ ID : : A_SIGNED ] = 0 ;
c - > parameters [ ID : : A_WIDTH ] = 1 ;
c - > parameters [ ID : : Y_WIDTH ] = 1 ;
2026-06-10 19:22:53 +02:00
c - > setPort ( TW : : A , info . sig_arst ) ;
c - > setPort ( TW : : Y , wire_r ) ;
2014-02-08 21:08:38 +01:00
}
2014-08-02 13:11:01 +02:00
RTLIL : : Wire * wire_v = add_new_wire ( module , wire - > name . str ( ) + sep + " v " , wire - > width ) ;
2014-02-08 21:08:38 +01:00
wire_v - > port_output = true ;
2026-05-15 15:16:09 +02:00
log ( " New module port: %s/%s \n " , module , wire_v ) ;
2014-07-26 14:32:50 +02:00
module - > connect ( RTLIL : : SigSig ( wire_v , info . arst_value ) ) ;
2014-02-08 21:08:38 +01:00
}
}
2014-02-05 23:59:55 +01:00
if ( flag_evert )
{
2014-07-25 15:05:18 +02:00
std : : vector < RTLIL : : Cell * > delete_cells ;
2014-02-05 23:59:55 +01:00
2020-03-30 18:16:16 +02:00
for ( auto cell : module - > cells ( ) )
2014-02-05 23:59:55 +01:00
{
if ( flag_shared ) {
2020-03-30 18:16:16 +02:00
if ( shared_cells . count ( cell - > name ) = = 0 )
2014-02-05 23:59:55 +01:00
continue ;
} else {
2020-03-30 18:16:16 +02:00
if ( ! design - > selected ( module , cell ) | | ! consider_cell ( design , dff_cells [ module ] , cell ) )
2014-02-05 23:59:55 +01:00
continue ;
}
2020-03-30 18:16:16 +02:00
if ( design - > module ( cell - > type ) ! = nullptr )
2014-02-05 23:59:55 +01:00
{
2020-03-30 18:16:16 +02:00
RTLIL : : Module * mod = design - > module ( cell - > type ) ;
2014-02-05 23:59:55 +01:00
2020-03-30 18:16:16 +02:00
for ( auto p : mod - > wires ( ) )
2014-02-09 11:07:46 +01:00
{
if ( ! p - > port_input & & ! p - > port_output )
continue ;
2026-06-12 00:18:53 +02:00
RTLIL : : Wire * w = add_new_wire ( module , cell - > name . str ( ) + sep + design - > twines . unescaped_str ( p - > name ) , p - > width ) ;
2014-02-09 11:07:46 +01:00
if ( p - > port_input )
w - > port_output = true ;
if ( p - > port_output )
w - > port_input = true ;
2026-06-12 00:18:53 +02:00
log ( " New module port: %s/%s (%s) \n " , module , w , cell - > type . unescaped ( ) ) ;
2014-02-09 11:07:46 +01:00
RTLIL : : SigSpec sig ;
2014-07-31 16:38:54 +02:00
if ( cell - > hasPort ( p - > name ) )
sig = cell - > getPort ( p - > name ) ;
2014-12-24 09:51:17 +01:00
sig . extend_u0 ( w - > width ) ;
2014-02-09 11:07:46 +01:00
if ( w - > port_input )
2014-07-26 14:32:50 +02:00
module - > connect ( RTLIL : : SigSig ( sig , w ) ) ;
2014-02-09 11:07:46 +01:00
else
2014-07-26 14:32:50 +02:00
module - > connect ( RTLIL : : SigSig ( w , sig ) ) ;
2014-02-09 11:07:46 +01:00
}
}
else
{
2014-07-26 14:32:50 +02:00
for ( auto & it : cell - > connections ( ) )
2014-02-09 11:07:46 +01:00
{
2026-06-12 00:18:53 +02:00
RTLIL : : Wire * w = add_new_wire ( module , cell - > name . str ( ) + sep + design - > twines . unescaped_str ( it . first ) , it . second . size ( ) ) ;
if ( ct . cell_input ( cell - > type_impl , it . first ) )
2014-02-09 11:07:46 +01:00
w - > port_output = true ;
2026-06-12 00:18:53 +02:00
if ( ct . cell_output ( cell - > type_impl , it . first ) )
2014-02-09 11:07:46 +01:00
w - > port_input = true ;
2026-06-12 00:18:53 +02:00
log ( " New module port: %s/%s (%s) \n " , module , w , cell - > type . unescaped ( ) ) ;
2014-02-09 11:07:46 +01:00
if ( w - > port_input )
2014-07-26 14:32:50 +02:00
module - > connect ( RTLIL : : SigSig ( it . second , w ) ) ;
2014-02-09 11:07:46 +01:00
else
2014-07-26 14:32:50 +02:00
module - > connect ( RTLIL : : SigSig ( w , it . second ) ) ;
2014-02-09 11:07:46 +01:00
}
2014-02-05 23:59:55 +01:00
}
2014-07-25 15:05:18 +02:00
delete_cells . push_back ( cell ) ;
2014-02-05 23:59:55 +01:00
}
2014-07-25 15:05:18 +02:00
for ( auto cell : delete_cells ) {
2026-06-12 00:18:53 +02:00
log ( " Removing cell: %s/%s (%s) \n " , module , cell , cell - > type . unescaped ( ) ) ;
2014-07-25 15:05:18 +02:00
module - > remove ( cell ) ;
2014-02-05 23:59:55 +01:00
}
}
module - > fixup_ports ( ) ;
}
}
} ExposePass ;
2015-07-02 11:14:30 +02:00
2014-09-27 16:17:53 +02:00
PRIVATE_NAMESPACE_END