2013-01-05 04:13:26 -06:00
/*
* yosys - - Yosys Open SYnthesis Suite
*
* Copyright ( C ) 2012 Clifford Wolf < clifford @ clifford . at >
2015-07-02 04:14:30 -05:00
*
2013-01-05 04:13:26 -06: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 04:14:30 -05:00
*
2013-01-05 04:13:26 -06: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 .
*
*/
2014-10-10 11:02:17 -05:00
# include "kernel/yosys.h"
2013-03-14 09:57:47 -05:00
# include "kernel/celltypes.h"
2014-02-08 09:31:38 -06:00
# include "kernel/sigtools.h"
2013-01-05 04:13:26 -06:00
# include <string.h>
2014-03-11 08:24:24 -05:00
# include <errno.h>
2013-01-05 04:13:26 -06:00
2014-09-27 09:17:53 -05:00
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
2013-03-03 06:18:37 -06:00
using RTLIL : : id2cstr ;
2013-01-05 04:13:26 -06:00
static std : : vector < RTLIL : : Selection > work_stack ;
static bool match_ids ( RTLIL : : IdString id , std : : string pattern )
{
2013-11-28 14:13:16 -06:00
if ( id = = pattern )
2013-01-05 04:13:26 -06:00
return true ;
2019-08-07 14:20:08 -05:00
if ( id . size ( ) > 0 & & id [ 0 ] = = ' \\ ' & & id . compare ( 1 , std : : string : : npos , pattern . c_str ( ) ) = = 0 )
2013-01-05 04:13:26 -06:00
return true ;
2014-10-10 11:02:17 -05:00
if ( patmatch ( pattern . c_str ( ) , id . c_str ( ) ) )
2013-11-28 14:13:16 -06:00
return true ;
2014-10-10 11:02:17 -05:00
if ( id . size ( ) > 0 & & id [ 0 ] = = ' \\ ' & & patmatch ( pattern . c_str ( ) , id . substr ( 1 ) . c_str ( ) ) )
2013-11-28 14:13:16 -06:00
return true ;
if ( id . size ( ) > 0 & & id [ 0 ] = = ' $ ' & & pattern . size ( ) > 0 & & pattern [ 0 ] = = ' $ ' ) {
const char * p = id . c_str ( ) ;
const char * q = strrchr ( p , ' $ ' ) ;
if ( pattern = = q )
return true ;
}
2013-01-05 04:13:26 -06:00
return false ;
}
2014-02-05 11:24:45 -06:00
static bool match_attr_val ( const RTLIL : : Const & value , std : : string pattern , char match_op )
2013-01-05 05:27:59 -06:00
{
2014-02-05 11:24:45 -06:00
if ( match_op = = 0 )
2013-01-05 05:27:59 -06:00
return true ;
2014-02-05 11:24:45 -06:00
if ( ( value . flags & RTLIL : : CONST_FLAG_STRING ) = = 0 )
{
RTLIL : : SigSpec sig_value ;
2020-03-13 23:40:14 -05:00
if ( ! RTLIL : : SigSpec : : parse ( sig_value , nullptr , pattern ) )
2014-02-05 11:24:45 -06:00
return false ;
RTLIL : : Const pattern_value = sig_value . as_const ( ) ;
if ( match_op = = ' = ' )
return value = = pattern_value ;
2014-02-15 17:16:54 -06:00
if ( match_op = = ' ! ' )
return value ! = pattern_value ;
2014-02-05 11:24:45 -06:00
if ( match_op = = ' < ' )
return value . as_int ( ) < pattern_value . as_int ( ) ;
if ( match_op = = ' > ' )
return value . as_int ( ) > pattern_value . as_int ( ) ;
if ( match_op = = ' [ ' )
return value . as_int ( ) < = pattern_value . as_int ( ) ;
if ( match_op = = ' ] ' )
return value . as_int ( ) > = pattern_value . as_int ( ) ;
}
else
{
std : : string value_str = value . decode_string ( ) ;
if ( match_op = = ' = ' )
2014-10-10 11:02:17 -05:00
if ( patmatch ( pattern . c_str ( ) , value . decode_string ( ) . c_str ( ) ) )
2014-02-05 11:24:45 -06:00
return true ;
if ( match_op = = ' = ' )
return value_str = = pattern ;
2014-02-15 17:16:54 -06:00
if ( match_op = = ' ! ' )
return value_str ! = pattern ;
2014-02-05 11:24:45 -06:00
if ( match_op = = ' < ' )
return value_str < pattern ;
if ( match_op = = ' > ' )
return value_str > pattern ;
if ( match_op = = ' [ ' )
return value_str < = pattern ;
if ( match_op = = ' ] ' )
return value_str > = pattern ;
}
log_abort ( ) ;
2013-01-05 05:27:59 -06:00
}
2014-12-26 03:53:21 -06:00
static bool match_attr ( const dict < RTLIL : : IdString , RTLIL : : Const > & attributes , std : : string name_pat , std : : string value_pat , char match_op )
2013-01-05 05:27:59 -06:00
{
if ( name_pat . find ( ' * ' ) ! = std : : string : : npos | | name_pat . find ( ' ? ' ) ! = std : : string : : npos | | name_pat . find ( ' [ ' ) ! = std : : string : : npos ) {
for ( auto & it : attributes ) {
2014-10-10 11:02:17 -05:00
if ( patmatch ( name_pat . c_str ( ) , it . first . c_str ( ) ) & & match_attr_val ( it . second , value_pat , match_op ) )
2013-01-05 05:27:59 -06:00
return true ;
2014-10-10 11:02:17 -05:00
if ( it . first . size ( ) > 0 & & it . first [ 0 ] = = ' \\ ' & & patmatch ( name_pat . c_str ( ) , it . first . substr ( 1 ) . c_str ( ) ) & & match_attr_val ( it . second , value_pat , match_op ) )
2013-01-05 05:27:59 -06:00
return true ;
}
} else {
2014-02-05 11:24:45 -06:00
if ( name_pat . size ( ) > 0 & & ( name_pat [ 0 ] = = ' \\ ' | | name_pat [ 0 ] = = ' $ ' ) & & attributes . count ( name_pat ) & & match_attr_val ( attributes . at ( name_pat ) , value_pat , match_op ) )
2013-01-05 05:27:59 -06:00
return true ;
2014-02-05 11:24:45 -06:00
if ( attributes . count ( " \\ " + name_pat ) & & match_attr_val ( attributes . at ( " \\ " + name_pat ) , value_pat , match_op ) )
2013-01-05 05:27:59 -06:00
return true ;
}
return false ;
}
2014-12-26 03:53:21 -06:00
static bool match_attr ( const dict < RTLIL : : IdString , RTLIL : : Const > & attributes , std : : string match_expr )
2014-02-05 11:24:45 -06:00
{
2014-02-15 17:16:54 -06:00
size_t pos = match_expr . find_first_of ( " <!=> " ) ;
2014-02-05 11:24:45 -06:00
if ( pos ! = std : : string : : npos ) {
2019-08-07 14:20:08 -05:00
if ( match_expr . compare ( pos , 2 , " != " ) = = 0 )
2014-02-15 17:16:54 -06:00
return match_attr ( attributes , match_expr . substr ( 0 , pos ) , match_expr . substr ( pos + 2 ) , ' ! ' ) ;
2019-08-07 14:20:08 -05:00
if ( match_expr . compare ( pos , 2 , " <= " ) = = 0 )
2014-02-05 11:24:45 -06:00
return match_attr ( attributes , match_expr . substr ( 0 , pos ) , match_expr . substr ( pos + 2 ) , ' [ ' ) ;
2019-08-07 14:20:08 -05:00
if ( match_expr . compare ( pos , 2 , " >= " ) = = 0 )
2014-02-05 11:24:45 -06:00
return match_attr ( attributes , match_expr . substr ( 0 , pos ) , match_expr . substr ( pos + 2 ) , ' ] ' ) ;
return match_attr ( attributes , match_expr . substr ( 0 , pos ) , match_expr . substr ( pos + 1 ) , match_expr [ pos ] ) ;
}
return match_attr ( attributes , match_expr , std : : string ( ) , 0 ) ;
}
2013-01-05 04:13:26 -06:00
static void select_op_neg ( RTLIL : : Design * design , RTLIL : : Selection & lhs )
{
if ( lhs . full_selection ) {
lhs . full_selection = false ;
lhs . selected_modules . clear ( ) ;
lhs . selected_members . clear ( ) ;
return ;
}
if ( lhs . selected_modules . size ( ) = = 0 & & lhs . selected_members . size ( ) = = 0 ) {
lhs . full_selection = true ;
return ;
}
RTLIL : : Selection new_sel ( false ) ;
2020-03-13 23:40:14 -05:00
for ( auto mod : design - > modules ( ) )
2013-01-05 04:13:26 -06:00
{
2020-03-13 23:40:14 -05:00
if ( lhs . selected_whole_module ( mod - > name ) )
2013-01-05 04:13:26 -06:00
continue ;
2020-03-13 23:40:14 -05:00
if ( ! lhs . selected_module ( mod - > name ) ) {
new_sel . selected_modules . insert ( mod - > name ) ;
2013-01-05 04:13:26 -06:00
continue ;
}
2020-03-13 23:40:14 -05:00
for ( auto wire : mod - > wires ( ) )
if ( ! lhs . selected_member ( mod - > name , wire - > name ) )
new_sel . selected_members [ mod - > name ] . insert ( wire - > name ) ;
2013-01-05 04:13:26 -06:00
for ( auto & it : mod - > memories )
2020-03-13 23:40:14 -05:00
if ( ! lhs . selected_member ( mod - > name , it . first ) )
2013-01-05 04:13:26 -06:00
new_sel . selected_members [ mod - > name ] . insert ( it . first ) ;
2020-03-13 23:40:14 -05:00
for ( auto cell : mod - > cells ( ) )
if ( ! lhs . selected_member ( mod - > name , cell - > name ) )
new_sel . selected_members [ mod - > name ] . insert ( cell - > name ) ;
2013-01-05 04:13:26 -06:00
for ( auto & it : mod - > processes )
2020-03-13 23:40:14 -05:00
if ( ! lhs . selected_member ( mod - > name , it . first ) )
2013-01-05 04:13:26 -06:00
new_sel . selected_members [ mod - > name ] . insert ( it . first ) ;
}
lhs . selected_modules . swap ( new_sel . selected_modules ) ;
lhs . selected_members . swap ( new_sel . selected_members ) ;
}
2015-12-20 06:35:58 -06:00
static int my_xorshift32_rng ( ) {
static uint32_t x32 = 314159265 ;
x32 ^ = x32 < < 13 ;
x32 ^ = x32 > > 17 ;
x32 ^ = x32 < < 5 ;
return x32 & 0x0fffffff ;
}
static void select_op_random ( RTLIL : : Design * design , RTLIL : : Selection & lhs , int count )
{
vector < pair < IdString , IdString > > objects ;
for ( auto mod : design - > modules ( ) )
{
if ( ! lhs . selected_module ( mod - > name ) )
continue ;
for ( auto cell : mod - > cells ( ) ) {
if ( lhs . selected_member ( mod - > name , cell - > name ) )
objects . push_back ( make_pair ( mod - > name , cell - > name ) ) ;
}
for ( auto wire : mod - > wires ( ) ) {
if ( lhs . selected_member ( mod - > name , wire - > name ) )
objects . push_back ( make_pair ( mod - > name , wire - > name ) ) ;
}
}
lhs = RTLIL : : Selection ( false ) ;
while ( ! objects . empty ( ) & & count - - > 0 )
{
int idx = my_xorshift32_rng ( ) % GetSize ( objects ) ;
lhs . selected_members [ objects [ idx ] . first ] . insert ( objects [ idx ] . second ) ;
objects [ idx ] = objects . back ( ) ;
objects . pop_back ( ) ;
}
lhs . optimize ( design ) ;
}
2014-02-06 10:36:39 -06:00
static void select_op_submod ( RTLIL : : Design * design , RTLIL : : Selection & lhs )
{
2020-03-13 23:40:14 -05:00
for ( auto mod : design - > modules ( ) )
2014-02-06 10:36:39 -06:00
{
2020-03-13 23:40:14 -05:00
if ( lhs . selected_whole_module ( mod - > name ) )
2014-02-06 10:36:39 -06:00
{
2020-03-13 23:40:14 -05:00
for ( auto cell : mod - > cells ( ) )
2014-02-06 10:36:39 -06:00
{
2020-03-16 15:32:46 -05:00
if ( design - > module ( cell - > type ) = = nullptr )
2014-02-06 10:36:39 -06:00
continue ;
2020-03-13 23:40:14 -05:00
lhs . selected_modules . insert ( cell - > type ) ;
2014-02-06 10:36:39 -06:00
}
}
}
}
2015-04-07 15:22:09 -05:00
static void select_op_cells_to_modules ( RTLIL : : Design * design , RTLIL : : Selection & lhs )
{
RTLIL : : Selection new_sel ( false ) ;
2020-03-13 23:40:14 -05:00
for ( auto mod : design - > modules ( ) )
if ( lhs . selected_module ( mod - > name ) )
for ( auto cell : mod - > cells ( ) )
2020-03-16 15:32:46 -05:00
if ( lhs . selected_member ( mod - > name , cell - > name ) & & ( design - > module ( cell - > type ) ! = nullptr ) )
2020-03-13 23:40:14 -05:00
new_sel . selected_modules . insert ( cell - > type ) ;
2015-04-07 15:22:09 -05:00
lhs = new_sel ;
}
static void select_op_module_to_cells ( RTLIL : : Design * design , RTLIL : : Selection & lhs )
{
RTLIL : : Selection new_sel ( false ) ;
2020-03-13 23:40:14 -05:00
for ( auto mod : design - > modules ( ) )
for ( auto cell : mod - > cells ( ) )
2020-03-16 15:32:46 -05:00
if ( ( design - > module ( cell - > type ) ! = nullptr ) & & lhs . selected_whole_module ( cell - > type ) )
2020-03-13 23:40:14 -05:00
new_sel . selected_members [ mod - > name ] . insert ( cell - > name ) ;
2015-04-07 15:22:09 -05:00
lhs = new_sel ;
}
2014-02-06 12:30:08 -06:00
static void select_op_fullmod ( RTLIL : : Design * design , RTLIL : : Selection & lhs )
{
lhs . optimize ( design ) ;
for ( auto & it : lhs . selected_members )
lhs . selected_modules . insert ( it . first ) ;
lhs . selected_members . clear ( ) ;
}
2014-02-08 09:31:38 -06:00
static void select_op_alias ( RTLIL : : Design * design , RTLIL : : Selection & lhs )
{
2020-03-13 23:40:14 -05:00
for ( auto mod : design - > modules ( ) )
2014-02-08 09:31:38 -06:00
{
2020-03-13 23:40:14 -05:00
if ( lhs . selected_whole_module ( mod - > name ) )
2014-02-08 09:31:38 -06:00
continue ;
2020-03-13 23:40:14 -05:00
if ( ! lhs . selected_module ( mod - > name ) )
2014-02-08 09:31:38 -06:00
continue ;
2020-03-13 23:40:14 -05:00
SigMap sigmap ( mod ) ;
2014-02-08 09:31:38 -06:00
SigPool selected_bits ;
2020-03-13 23:40:14 -05:00
for ( auto wire : mod - > wires ( ) )
if ( lhs . selected_member ( mod - > name , wire - > name ) )
selected_bits . add ( sigmap ( wire ) ) ;
2014-02-08 09:31:38 -06:00
2020-03-13 23:40:14 -05:00
for ( auto wire : mod - > wires ( ) )
if ( ! lhs . selected_member ( mod - > name , wire - > name ) & & selected_bits . check_any ( sigmap ( wire ) ) )
lhs . selected_members [ mod - > name ] . insert ( wire - > name ) ;
2014-02-08 09:31:38 -06:00
}
}
2013-01-05 04:13:26 -06:00
static void select_op_union ( RTLIL : : Design * , RTLIL : : Selection & lhs , const RTLIL : : Selection & rhs )
{
if ( rhs . full_selection ) {
lhs . full_selection = true ;
lhs . selected_modules . clear ( ) ;
lhs . selected_members . clear ( ) ;
return ;
}
if ( lhs . full_selection )
return ;
for ( auto & it : rhs . selected_members )
for ( auto & it2 : it . second )
lhs . selected_members [ it . first ] . insert ( it2 ) ;
for ( auto & it : rhs . selected_modules ) {
lhs . selected_modules . insert ( it ) ;
lhs . selected_members . erase ( it ) ;
}
}
static void select_op_diff ( RTLIL : : Design * design , RTLIL : : Selection & lhs , const RTLIL : : Selection & rhs )
{
if ( rhs . full_selection ) {
lhs . full_selection = false ;
lhs . selected_modules . clear ( ) ;
lhs . selected_members . clear ( ) ;
return ;
}
if ( lhs . full_selection ) {
if ( ! rhs . full_selection & & rhs . selected_modules . size ( ) = = 0 & & rhs . selected_members . size ( ) = = 0 )
return ;
lhs . full_selection = false ;
2020-03-13 23:40:14 -05:00
for ( auto mod : design - > modules ( ) )
lhs . selected_modules . insert ( mod - > name ) ;
2013-01-05 04:13:26 -06:00
}
for ( auto & it : rhs . selected_modules ) {
lhs . selected_modules . erase ( it ) ;
lhs . selected_members . erase ( it ) ;
}
for ( auto & it : rhs . selected_members )
{
2020-03-16 15:32:46 -05:00
if ( design - > module ( it . first ) = = nullptr )
2013-01-05 04:13:26 -06:00
continue ;
2020-03-13 23:40:14 -05:00
RTLIL : : Module * mod = design - > module ( it . first ) ;
2013-01-05 04:13:26 -06:00
if ( lhs . selected_modules . count ( mod - > name ) > 0 )
{
2020-03-13 23:40:14 -05:00
for ( auto wire : mod - > wires ( ) )
lhs . selected_members [ mod - > name ] . insert ( wire - > name ) ;
2013-01-05 04:13:26 -06:00
for ( auto & it : mod - > memories )
lhs . selected_members [ mod - > name ] . insert ( it . first ) ;
2020-03-13 23:40:14 -05:00
for ( auto cell : mod - > cells ( ) )
lhs . selected_members [ mod - > name ] . insert ( cell - > name ) ;
2013-01-05 04:13:26 -06:00
for ( auto & it : mod - > processes )
lhs . selected_members [ mod - > name ] . insert ( it . first ) ;
lhs . selected_modules . erase ( mod - > name ) ;
}
if ( lhs . selected_members . count ( mod - > name ) = = 0 )
continue ;
for ( auto & it2 : it . second )
lhs . selected_members [ mod - > name ] . erase ( it2 ) ;
}
}
static void select_op_intersect ( RTLIL : : Design * design , RTLIL : : Selection & lhs , const RTLIL : : Selection & rhs )
{
if ( rhs . full_selection )
return ;
if ( lhs . full_selection ) {
lhs . full_selection = false ;
2020-03-13 23:40:14 -05:00
for ( auto mod : design - > modules ( ) )
lhs . selected_modules . insert ( mod - > name ) ;
2013-01-05 04:13:26 -06:00
}
std : : vector < RTLIL : : IdString > del_list ;
for ( auto & it : lhs . selected_modules )
if ( rhs . selected_modules . count ( it ) = = 0 ) {
if ( rhs . selected_members . count ( it ) > 0 )
for ( auto & it2 : rhs . selected_members . at ( it ) )
lhs . selected_members [ it ] . insert ( it2 ) ;
del_list . push_back ( it ) ;
}
for ( auto & it : del_list )
lhs . selected_modules . erase ( it ) ;
del_list . clear ( ) ;
for ( auto & it : lhs . selected_members ) {
if ( rhs . selected_modules . count ( it . first ) > 0 )
continue ;
if ( rhs . selected_members . count ( it . first ) = = 0 ) {
del_list . push_back ( it . first ) ;
continue ;
}
std : : vector < RTLIL : : IdString > del_list2 ;
for ( auto & it2 : it . second )
if ( rhs . selected_members . at ( it . first ) . count ( it2 ) = = 0 )
del_list2 . push_back ( it2 ) ;
for ( auto & it2 : del_list2 )
it . second . erase ( it2 ) ;
if ( it . second . size ( ) = = 0 )
del_list . push_back ( it . first ) ;
}
for ( auto & it : del_list )
lhs . selected_members . erase ( it ) ;
}
2013-03-05 05:53:40 -06:00
namespace {
struct expand_rule_t {
char mode ;
std : : set < RTLIL : : IdString > cell_types , port_names ;
} ;
}
static int parse_comma_list ( std : : set < RTLIL : : IdString > & tokens , std : : string str , size_t pos , std : : string stopchar )
{
stopchar + = ' , ' ;
while ( 1 ) {
size_t endpos = str . find_first_of ( stopchar , pos ) ;
if ( endpos = = std : : string : : npos )
endpos = str . size ( ) ;
if ( endpos ! = pos )
tokens . insert ( RTLIL : : escape_id ( str . substr ( pos , endpos - pos ) ) ) ;
pos = endpos ;
if ( pos = = str . size ( ) | | str [ pos ] ! = ' , ' )
return pos ;
pos + + ;
}
}
2015-02-18 00:18:34 -06:00
static int select_op_expand ( RTLIL : : Design * design , RTLIL : : Selection & lhs , std : : vector < expand_rule_t > & rules , std : : set < RTLIL : : IdString > & limits , int max_objects , char mode , CellTypes & ct , bool eval_only )
2013-03-03 10:41:46 -06:00
{
2013-03-14 09:35:05 -05:00
int sel_objects = 0 ;
2013-03-14 09:57:47 -05:00
bool is_input , is_output ;
2020-03-13 23:40:14 -05:00
for ( auto mod : design - > modules ( ) )
2013-03-03 10:41:46 -06:00
{
2020-03-13 23:40:14 -05:00
if ( lhs . selected_whole_module ( mod - > name ) | | ! lhs . selected_module ( mod - > name ) )
2013-03-03 10:41:46 -06:00
continue ;
std : : set < RTLIL : : Wire * > selected_wires ;
2014-12-30 13:15:18 -06:00
auto selected_members = lhs . selected_members [ mod - > name ] ;
2013-03-03 10:41:46 -06:00
2020-03-13 23:40:14 -05:00
for ( auto wire : mod - > wires ( ) )
if ( lhs . selected_member ( mod - > name , wire - > name ) & & limits . count ( wire - > name ) = = 0 )
selected_wires . insert ( wire ) ;
2013-03-03 10:41:46 -06:00
2014-07-26 07:32:50 -05:00
for ( auto & conn : mod - > connections ( ) )
2014-01-02 11:44:24 -06:00
{
std : : vector < RTLIL : : SigBit > conn_lhs = conn . first . to_sigbit_vector ( ) ;
std : : vector < RTLIL : : SigBit > conn_rhs = conn . second . to_sigbit_vector ( ) ;
for ( size_t i = 0 ; i < conn_lhs . size ( ) ; i + + ) {
2020-03-13 23:40:14 -05:00
if ( conn_lhs [ i ] . wire = = nullptr | | conn_rhs [ i ] . wire = = nullptr )
2014-01-02 11:44:24 -06:00
continue ;
2014-12-30 13:15:18 -06:00
if ( mode ! = ' i ' & & selected_wires . count ( conn_rhs [ i ] . wire ) & & selected_members . count ( conn_lhs [ i ] . wire - > name ) = = 0 )
2014-01-02 11:44:24 -06:00
lhs . selected_members [ mod - > name ] . insert ( conn_lhs [ i ] . wire - > name ) , sel_objects + + , max_objects - - ;
2014-12-30 13:15:18 -06:00
if ( mode ! = ' o ' & & selected_wires . count ( conn_lhs [ i ] . wire ) & & selected_members . count ( conn_rhs [ i ] . wire - > name ) = = 0 )
2014-01-02 11:44:24 -06:00
lhs . selected_members [ mod - > name ] . insert ( conn_rhs [ i ] . wire - > name ) , sel_objects + + , max_objects - - ;
}
}
2020-03-13 23:40:14 -05:00
for ( auto cell : mod - > cells ( ) )
for ( auto & conn : cell - > connections ( ) )
2013-03-05 05:53:40 -06:00
{
char last_mode = ' - ' ;
2020-03-13 23:40:14 -05:00
if ( eval_only & & ! yosys_celltypes . cell_evaluable ( cell - > type ) )
2015-02-18 00:18:34 -06:00
goto exclude_match ;
2013-03-05 05:53:40 -06:00
for ( auto & rule : rules ) {
last_mode = rule . mode ;
2020-03-13 23:40:14 -05:00
if ( rule . cell_types . size ( ) > 0 & & rule . cell_types . count ( cell - > type ) = = 0 )
2013-03-05 05:53:40 -06:00
continue ;
2013-03-08 03:15:15 -06:00
if ( rule . port_names . size ( ) > 0 & & rule . port_names . count ( conn . first ) = = 0 )
2013-03-05 05:53:40 -06:00
continue ;
if ( rule . mode = = ' + ' )
goto include_match ;
else
goto exclude_match ;
2013-03-03 10:41:46 -06:00
}
2013-03-05 05:53:40 -06:00
if ( last_mode = = ' + ' )
goto exclude_match ;
include_match :
2020-03-13 23:40:14 -05:00
is_input = mode = = ' x ' | | ct . cell_input ( cell - > type , conn . first ) ;
is_output = mode = = ' x ' | | ct . cell_output ( cell - > type , conn . first ) ;
2014-07-22 13:15:14 -05:00
for ( auto & chunk : conn . second . chunks ( ) )
2020-03-13 23:40:14 -05:00
if ( chunk . wire ! = nullptr ) {
if ( max_objects ! = 0 & & selected_wires . count ( chunk . wire ) > 0 & & selected_members . count ( cell - > name ) = = 0 )
2013-03-14 09:57:47 -05:00
if ( mode = = ' x ' | | ( mode = = ' i ' & & is_output ) | | ( mode = = ' o ' & & is_input ) )
2020-03-13 23:40:14 -05:00
lhs . selected_members [ mod - > name ] . insert ( cell - > name ) , sel_objects + + , max_objects - - ;
if ( max_objects ! = 0 & & selected_members . count ( cell - > name ) > 0 & & limits . count ( cell - > name ) = = 0 & & selected_members . count ( chunk . wire - > name ) = = 0 )
2013-03-14 09:57:47 -05:00
if ( mode = = ' x ' | | ( mode = = ' i ' & & is_input ) | | ( mode = = ' o ' & & is_output ) )
lhs . selected_members [ mod - > name ] . insert ( chunk . wire - > name ) , sel_objects + + , max_objects - - ;
2013-03-05 05:53:40 -06:00
}
exclude_match : ;
}
2013-03-03 10:41:46 -06:00
}
2013-03-14 09:35:05 -05:00
return sel_objects ;
2013-03-03 10:41:46 -06:00
}
2015-02-18 00:18:34 -06:00
static void select_op_expand ( RTLIL : : Design * design , std : : string arg , char mode , bool eval_only )
2013-03-14 09:57:47 -05:00
{
2015-02-18 00:18:34 -06:00
int pos = ( mode = = ' x ' ? 2 : 3 ) + ( eval_only ? 1 : 0 ) ;
int levels = 1 , rem_objects = - 1 ;
2013-03-14 09:57:47 -05:00
std : : vector < expand_rule_t > rules ;
std : : set < RTLIL : : IdString > limits ;
CellTypes ct ;
if ( mode ! = ' x ' )
ct . setup ( design ) ;
if ( pos < int ( arg . size ( ) ) & & arg [ pos ] = = ' * ' ) {
levels = 1000000 ;
pos + + ;
} else
if ( pos < int ( arg . size ( ) ) & & ' 0 ' < = arg [ pos ] & & arg [ pos ] < = ' 9 ' ) {
size_t endpos = arg . find_first_not_of ( " 0123456789 " , pos ) ;
if ( endpos = = std : : string : : npos )
endpos = arg . size ( ) ;
2019-08-07 13:09:17 -05:00
levels = atoi ( arg . substr ( pos , endpos - pos ) . c_str ( ) ) ;
2013-03-14 09:57:47 -05:00
pos = endpos ;
}
if ( pos < int ( arg . size ( ) ) & & arg [ pos ] = = ' . ' ) {
size_t endpos = arg . find_first_not_of ( " 0123456789 " , + + pos ) ;
if ( endpos = = std : : string : : npos )
endpos = arg . size ( ) ;
if ( int ( endpos ) > pos )
2019-08-07 13:09:17 -05:00
rem_objects = atoi ( arg . substr ( pos , endpos - pos ) . c_str ( ) ) ;
2013-03-14 09:57:47 -05:00
pos = endpos ;
}
while ( pos < int ( arg . size ( ) ) ) {
if ( arg [ pos ] ! = ' : ' | | pos + 1 = = int ( arg . size ( ) ) )
log_cmd_error ( " Syntax error in expand operator '%s'. \n " , arg . c_str ( ) ) ;
pos + + ;
if ( arg [ pos ] = = ' + ' | | arg [ pos ] = = ' - ' ) {
expand_rule_t rule ;
rule . mode = arg [ pos + + ] ;
pos = parse_comma_list ( rule . cell_types , arg , pos , " [: " ) ;
if ( pos < int ( arg . size ( ) ) & & arg [ pos ] = = ' [ ' ) {
pos = parse_comma_list ( rule . port_names , arg , pos + 1 , " ]: " ) ;
if ( pos < int ( arg . size ( ) ) & & arg [ pos ] = = ' ] ' )
pos + + ;
}
rules . push_back ( rule ) ;
} else {
size_t endpos = arg . find ( ' : ' , pos ) ;
if ( endpos = = std : : string : : npos )
endpos = arg . size ( ) ;
2013-04-01 07:58:11 -05:00
if ( int ( endpos ) > pos ) {
std : : string str = arg . substr ( pos , endpos - pos ) ;
if ( str [ 0 ] = = ' @ ' ) {
str = RTLIL : : escape_id ( str . substr ( 1 ) ) ;
if ( design - > selection_vars . count ( str ) > 0 ) {
for ( auto i1 : design - > selection_vars . at ( str ) . selected_members )
for ( auto i2 : i1 . second )
limits . insert ( i2 ) ;
2014-02-04 16:31:06 -06:00
} else
2014-08-02 09:03:18 -05:00
log_cmd_error ( " Selection %s is not defined! \n " , RTLIL : : unescape_id ( str ) . c_str ( ) ) ;
2013-04-01 07:58:11 -05:00
} else
limits . insert ( RTLIL : : escape_id ( str ) ) ;
}
2013-03-14 09:57:47 -05:00
pos = endpos ;
}
}
#if 0
log ( " expand by %d levels (max. %d objects): \n " , levels , rem_objects ) ;
for ( auto & rule : rules ) {
log ( " rule (%c): \n " , rule . mode ) ;
if ( rule . cell_types . size ( ) > 0 ) {
log ( " cell types: " ) ;
for ( auto & it : rule . cell_types )
log ( " %s " , it . c_str ( ) ) ;
log ( " \n " ) ;
}
if ( rule . port_names . size ( ) > 0 ) {
log ( " port names: " ) ;
for ( auto & it : rule . port_names )
log ( " %s " , it . c_str ( ) ) ;
log ( " \n " ) ;
}
}
if ( limits . size ( ) > 0 ) {
log ( " limits: " ) ;
for ( auto & it : limits )
log ( " %s " , it . c_str ( ) ) ;
log ( " \n " ) ;
}
# endif
while ( levels - - > 0 & & rem_objects ! = 0 ) {
2015-02-18 00:18:34 -06:00
int num_objects = select_op_expand ( design , work_stack . back ( ) , rules , limits , rem_objects , mode , ct , eval_only ) ;
2013-03-14 09:57:47 -05:00
if ( num_objects = = 0 )
break ;
rem_objects - = num_objects ;
}
if ( rem_objects = = 0 )
2014-11-09 03:44:23 -06:00
log_warning ( " reached configured limit at `%s'. \n " , arg . c_str ( ) ) ;
2013-03-14 09:57:47 -05:00
}
2013-01-05 04:13:26 -06:00
static void select_filter_active_mod ( RTLIL : : Design * design , RTLIL : : Selection & sel )
{
if ( design - > selected_active_module . empty ( ) )
return ;
2015-07-02 04:14:30 -05:00
2013-01-05 04:13:26 -06:00
if ( sel . full_selection ) {
sel . full_selection = false ;
sel . selected_modules . clear ( ) ;
sel . selected_members . clear ( ) ;
sel . selected_modules . insert ( design - > selected_active_module ) ;
return ;
}
2014-08-01 17:45:25 -05:00
std : : vector < RTLIL : : IdString > del_list ;
2013-01-05 04:13:26 -06:00
for ( auto mod_name : sel . selected_modules )
if ( mod_name ! = design - > selected_active_module )
del_list . push_back ( mod_name ) ;
for ( auto & it : sel . selected_members )
if ( it . first ! = design - > selected_active_module )
del_list . push_back ( it . first ) ;
for ( auto mod_name : del_list ) {
sel . selected_modules . erase ( mod_name ) ;
sel . selected_members . erase ( mod_name ) ;
}
}
2020-03-23 01:31:41 -05:00
static void select_stmt ( RTLIL : : Design * design , std : : string arg , bool disable_empty_warning = false )
2013-01-05 04:13:26 -06:00
{
std : : string arg_mod , arg_memb ;
2020-03-12 12:00:21 -05:00
std : : unordered_map < std : : string , bool > arg_mod_found ;
std : : unordered_map < std : : string , bool > arg_memb_found ;
auto isalpha = [ ] ( const char & x ) { return ( ( x > = ' a ' & & x < = ' z ' ) | | ( x > = ' A ' & & x < = ' Z ' ) ) ; } ;
bool prefixed = GetSize ( arg ) > = 2 & & isalpha ( arg [ 0 ] ) & & arg [ 1 ] = = ' : ' ;
2013-01-05 04:13:26 -06:00
if ( arg . size ( ) = = 0 )
return ;
2013-03-14 10:15:24 -05:00
if ( arg [ 0 ] = = ' % ' ) {
if ( arg = = " % " ) {
2013-01-05 04:13:26 -06:00
if ( design - > selection_stack . size ( ) > 0 )
work_stack . push_back ( design - > selection_stack . back ( ) ) ;
} else
2013-03-14 10:15:24 -05:00
if ( arg = = " %% " ) {
2013-03-08 01:47:29 -06:00
while ( work_stack . size ( ) > 1 ) {
select_op_union ( design , work_stack . front ( ) , work_stack . back ( ) ) ;
work_stack . pop_back ( ) ;
}
} else
2013-03-14 10:15:24 -05:00
if ( arg = = " %n " ) {
2013-01-05 04:13:26 -06:00
if ( work_stack . size ( ) < 1 )
2013-03-14 10:15:24 -05:00
log_cmd_error ( " Must have at least one element on the stack for operator %%n. \n " ) ;
2013-01-05 04:13:26 -06:00
select_op_neg ( design , work_stack [ work_stack . size ( ) - 1 ] ) ;
} else
2013-03-14 10:15:24 -05:00
if ( arg = = " %u " ) {
2013-01-05 04:13:26 -06:00
if ( work_stack . size ( ) < 2 )
2013-03-14 10:15:24 -05:00
log_cmd_error ( " Must have at least two elements on the stack for operator %%u. \n " ) ;
2013-01-05 04:13:26 -06:00
select_op_union ( design , work_stack [ work_stack . size ( ) - 2 ] , work_stack [ work_stack . size ( ) - 1 ] ) ;
work_stack . pop_back ( ) ;
} else
2013-03-14 10:15:24 -05:00
if ( arg = = " %d " ) {
2013-01-05 04:13:26 -06:00
if ( work_stack . size ( ) < 2 )
2013-03-14 10:15:24 -05:00
log_cmd_error ( " Must have at least two elements on the stack for operator %%d. \n " ) ;
2013-01-05 04:13:26 -06:00
select_op_diff ( design , work_stack [ work_stack . size ( ) - 2 ] , work_stack [ work_stack . size ( ) - 1 ] ) ;
work_stack . pop_back ( ) ;
} else
2014-06-14 09:19:32 -05:00
if ( arg = = " %D " ) {
if ( work_stack . size ( ) < 2 )
2019-09-01 04:00:09 -05:00
log_cmd_error ( " Must have at least two elements on the stack for operator %%D. \n " ) ;
2014-06-14 09:19:32 -05:00
select_op_diff ( design , work_stack [ work_stack . size ( ) - 1 ] , work_stack [ work_stack . size ( ) - 2 ] ) ;
work_stack [ work_stack . size ( ) - 2 ] = work_stack [ work_stack . size ( ) - 1 ] ;
work_stack . pop_back ( ) ;
} else
2013-03-14 10:15:24 -05:00
if ( arg = = " %i " ) {
2013-01-05 04:13:26 -06:00
if ( work_stack . size ( ) < 2 )
2013-03-14 10:15:24 -05:00
log_cmd_error ( " Must have at least two elements on the stack for operator %%i. \n " ) ;
2013-01-05 04:13:26 -06:00
select_op_intersect ( design , work_stack [ work_stack . size ( ) - 2 ] , work_stack [ work_stack . size ( ) - 1 ] ) ;
work_stack . pop_back ( ) ;
2013-03-03 10:41:46 -06:00
} else
2015-12-20 06:35:58 -06:00
if ( arg . size ( ) > = 2 & & arg [ 0 ] = = ' % ' & & arg [ 1 ] = = ' R ' ) {
if ( work_stack . size ( ) < 1 )
log_cmd_error ( " Must have at least one element on the stack for operator %%R. \n " ) ;
int count = arg . size ( ) > 2 ? atoi ( arg . c_str ( ) + 2 ) : 1 ;
select_op_random ( design , work_stack [ work_stack . size ( ) - 1 ] , count ) ;
} else
2014-02-06 10:36:39 -06:00
if ( arg = = " %s " ) {
if ( work_stack . size ( ) < 1 )
log_cmd_error ( " Must have at least one element on the stack for operator %%s. \n " ) ;
select_op_submod ( design , work_stack [ work_stack . size ( ) - 1 ] ) ;
} else
2015-04-07 15:22:09 -05:00
if ( arg = = " %M " ) {
if ( work_stack . size ( ) < 1 )
log_cmd_error ( " Must have at least one element on the stack for operator %%M. \n " ) ;
select_op_cells_to_modules ( design , work_stack [ work_stack . size ( ) - 1 ] ) ;
} else
if ( arg = = " %C " ) {
if ( work_stack . size ( ) < 1 )
2019-09-01 04:00:09 -05:00
log_cmd_error ( " Must have at least one element on the stack for operator %%C. \n " ) ;
2015-04-07 15:22:09 -05:00
select_op_module_to_cells ( design , work_stack [ work_stack . size ( ) - 1 ] ) ;
} else
2014-06-14 09:19:32 -05:00
if ( arg = = " %c " ) {
if ( work_stack . size ( ) < 1 )
log_cmd_error ( " Must have at least one element on the stack for operator %%c. \n " ) ;
work_stack . push_back ( work_stack . back ( ) ) ;
} else
2014-02-06 12:30:08 -06:00
if ( arg = = " %m " ) {
if ( work_stack . size ( ) < 1 )
2014-06-14 09:19:32 -05:00
log_cmd_error ( " Must have at least one element on the stack for operator %%m. \n " ) ;
2014-02-06 12:30:08 -06:00
select_op_fullmod ( design , work_stack [ work_stack . size ( ) - 1 ] ) ;
} else
2014-02-08 09:31:38 -06:00
if ( arg = = " %a " ) {
if ( work_stack . size ( ) < 1 )
2014-06-14 09:19:32 -05:00
log_cmd_error ( " Must have at least one element on the stack for operator %%a. \n " ) ;
2014-02-08 09:31:38 -06:00
select_op_alias ( design , work_stack [ work_stack . size ( ) - 1 ] ) ;
} else
2019-08-07 14:20:08 -05:00
if ( arg = = " %x " | | ( arg . size ( ) > 2 & & arg . compare ( 0 , 2 , " %x " ) = = 0 & & ( arg [ 2 ] = = ' : ' | | arg [ 2 ] = = ' * ' | | arg [ 2 ] = = ' . ' | | ( ' 0 ' < = arg [ 2 ] & & arg [ 2 ] < = ' 9 ' ) ) ) ) {
2013-03-03 10:41:46 -06:00
if ( work_stack . size ( ) < 1 )
2013-03-14 10:15:24 -05:00
log_cmd_error ( " Must have at least one element on the stack for operator %%x. \n " ) ;
2015-02-18 00:18:34 -06:00
select_op_expand ( design , arg , ' x ' , false ) ;
2013-03-14 09:57:47 -05:00
} else
2019-08-07 14:20:08 -05:00
if ( arg = = " %ci " | | ( arg . size ( ) > 3 & & arg . compare ( 0 , 3 , " %ci " ) = = 0 & & ( arg [ 3 ] = = ' : ' | | arg [ 3 ] = = ' * ' | | arg [ 3 ] = = ' . ' | | ( ' 0 ' < = arg [ 3 ] & & arg [ 3 ] < = ' 9 ' ) ) ) ) {
2013-03-14 09:57:47 -05:00
if ( work_stack . size ( ) < 1 )
2013-03-14 10:15:24 -05:00
log_cmd_error ( " Must have at least one element on the stack for operator %%ci. \n " ) ;
2015-02-18 00:18:34 -06:00
select_op_expand ( design , arg , ' i ' , false ) ;
2013-03-14 09:57:47 -05:00
} else
2019-08-07 14:20:08 -05:00
if ( arg = = " %co " | | ( arg . size ( ) > 3 & & arg . compare ( 0 , 3 , " %co " ) = = 0 & & ( arg [ 3 ] = = ' : ' | | arg [ 3 ] = = ' * ' | | arg [ 3 ] = = ' . ' | | ( ' 0 ' < = arg [ 3 ] & & arg [ 3 ] < = ' 9 ' ) ) ) ) {
2013-03-14 09:57:47 -05:00
if ( work_stack . size ( ) < 1 )
2013-03-14 10:15:24 -05:00
log_cmd_error ( " Must have at least one element on the stack for operator %%co. \n " ) ;
2015-02-18 00:18:34 -06:00
select_op_expand ( design , arg , ' o ' , false ) ;
} else
2019-08-07 14:20:08 -05:00
if ( arg = = " %xe " | | ( arg . size ( ) > 3 & & arg . compare ( 0 , 3 , " %xe " ) = = 0 & & ( arg [ 3 ] = = ' : ' | | arg [ 3 ] = = ' * ' | | arg [ 3 ] = = ' . ' | | ( ' 0 ' < = arg [ 3 ] & & arg [ 3 ] < = ' 9 ' ) ) ) ) {
2015-02-18 00:18:34 -06:00
if ( work_stack . size ( ) < 1 )
log_cmd_error ( " Must have at least one element on the stack for operator %%xe. \n " ) ;
select_op_expand ( design , arg , ' x ' , true ) ;
} else
2019-08-07 14:20:08 -05:00
if ( arg = = " %cie " | | ( arg . size ( ) > 4 & & arg . compare ( 0 , 4 , " %cie " ) = = 0 & & ( arg [ 4 ] = = ' : ' | | arg [ 4 ] = = ' * ' | | arg [ 4 ] = = ' . ' | | ( ' 0 ' < = arg [ 4 ] & & arg [ 4 ] < = ' 9 ' ) ) ) ) {
2015-02-18 00:18:34 -06:00
if ( work_stack . size ( ) < 1 )
log_cmd_error ( " Must have at least one element on the stack for operator %%cie. \n " ) ;
select_op_expand ( design , arg , ' i ' , true ) ;
} else
2019-08-07 14:20:08 -05:00
if ( arg = = " %coe " | | ( arg . size ( ) > 4 & & arg . compare ( 0 , 4 , " %coe " ) = = 0 & & ( arg [ 4 ] = = ' : ' | | arg [ 4 ] = = ' * ' | | arg [ 4 ] = = ' . ' | | ( ' 0 ' < = arg [ 4 ] & & arg [ 4 ] < = ' 9 ' ) ) ) ) {
2015-02-18 00:18:34 -06:00
if ( work_stack . size ( ) < 1 )
log_cmd_error ( " Must have at least one element on the stack for operator %%coe. \n " ) ;
select_op_expand ( design , arg , ' o ' , true ) ;
2013-01-05 04:13:26 -06:00
} else
log_cmd_error ( " Unknown selection operator '%s'. \n " , arg . c_str ( ) ) ;
2013-03-31 11:06:27 -05:00
if ( work_stack . size ( ) > = 1 )
select_filter_active_mod ( design , work_stack . back ( ) ) ;
2013-01-05 04:13:26 -06:00
return ;
}
2013-02-28 05:51:30 -06:00
if ( arg [ 0 ] = = ' @ ' ) {
std : : string set_name = RTLIL : : escape_id ( arg . substr ( 1 ) ) ;
if ( design - > selection_vars . count ( set_name ) > 0 )
work_stack . push_back ( design - > selection_vars [ set_name ] ) ;
else
2014-08-02 09:03:18 -05:00
log_cmd_error ( " Selection @%s is not defined! \n " , RTLIL : : unescape_id ( set_name ) . c_str ( ) ) ;
2013-02-28 05:51:30 -06:00
select_filter_active_mod ( design , work_stack . back ( ) ) ;
return ;
}
2013-01-05 04:13:26 -06:00
if ( ! design - > selected_active_module . empty ( ) ) {
arg_mod = design - > selected_active_module ;
arg_memb = arg ;
2020-03-12 12:00:21 -05:00
if ( ! prefixed ) arg_memb_found [ arg_memb ] = false ;
2018-02-13 07:55:24 -06:00
} else
2020-03-12 12:00:21 -05:00
if ( prefixed & & arg [ 0 ] > = ' a ' & & arg [ 0 ] < = ' z ' ) {
2018-02-13 07:55:24 -06:00
arg_mod = " * " , arg_memb = arg ;
2013-01-05 04:13:26 -06:00
} else {
size_t pos = arg . find ( ' / ' ) ;
if ( pos = = std : : string : : npos ) {
2020-03-17 12:44:06 -05:00
arg_mod = arg ;
2020-03-12 12:00:21 -05:00
if ( ! prefixed ) arg_mod_found [ arg_mod ] = false ;
2013-01-05 04:13:26 -06:00
} else {
arg_mod = arg . substr ( 0 , pos ) ;
2020-03-12 12:00:21 -05:00
if ( ! prefixed ) arg_mod_found [ arg_mod ] = false ;
2013-01-05 04:13:26 -06:00
arg_memb = arg . substr ( pos + 1 ) ;
2020-03-23 12:50:11 -05:00
bool arg_memb_prefixed = GetSize ( arg_memb ) > = 2 & & isalpha ( arg_memb [ 0 ] ) & & arg_memb [ 1 ] = = ' : ' ;
if ( ! arg_memb_prefixed ) arg_memb_found [ arg_memb ] = false ;
2013-01-05 04:13:26 -06:00
}
}
work_stack . push_back ( RTLIL : : Selection ( ) ) ;
RTLIL : : Selection & sel = work_stack . back ( ) ;
if ( arg = = " * " & & arg_mod = = " * " ) {
select_filter_active_mod ( design , work_stack . back ( ) ) ;
return ;
}
2015-07-02 04:14:30 -05:00
2013-01-05 04:13:26 -06:00
sel . full_selection = false ;
2020-03-13 23:40:14 -05:00
for ( auto mod : design - > modules ( ) )
2013-01-05 04:13:26 -06:00
{
2019-08-07 14:20:08 -05:00
if ( arg_mod . compare ( 0 , 2 , " A: " ) = = 0 ) {
2020-03-13 23:40:14 -05:00
if ( ! match_attr ( mod - > attributes , arg_mod . substr ( 2 ) ) )
2014-02-02 09:47:17 -06:00
continue ;
} else
2020-03-17 12:44:06 -05:00
if ( arg_mod . compare ( 0 , 2 , " N: " ) = = 0 ) {
if ( ! match_ids ( mod - > name , arg_mod . substr ( 2 ) ) )
continue ;
} else
2020-03-13 23:40:14 -05:00
if ( ! match_ids ( mod - > name , arg_mod ) )
2013-01-05 04:13:26 -06:00
continue ;
2020-03-12 12:00:21 -05:00
else
arg_mod_found [ arg_mod ] = true ;
2013-01-05 04:13:26 -06:00
if ( arg_memb = = " " ) {
2020-03-13 23:40:14 -05:00
sel . selected_modules . insert ( mod - > name ) ;
2013-01-05 04:13:26 -06:00
continue ;
}
2019-08-07 14:20:08 -05:00
if ( arg_memb . compare ( 0 , 2 , " w: " ) = = 0 ) {
2020-03-13 23:40:14 -05:00
for ( auto wire : mod - > wires ( ) )
if ( match_ids ( wire - > name , arg_memb . substr ( 2 ) ) )
sel . selected_members [ mod - > name ] . insert ( wire - > name ) ;
2013-01-05 04:13:26 -06:00
} else
2019-08-07 14:20:08 -05:00
if ( arg_memb . compare ( 0 , 2 , " i: " ) = = 0 ) {
2020-03-13 23:40:14 -05:00
for ( auto wire : mod - > wires ( ) )
if ( wire - > port_input & & match_ids ( wire - > name , arg_memb . substr ( 2 ) ) )
sel . selected_members [ mod - > name ] . insert ( wire - > name ) ;
2014-02-06 12:35:33 -06:00
} else
2019-08-07 14:20:08 -05:00
if ( arg_memb . compare ( 0 , 2 , " o: " ) = = 0 ) {
2020-03-13 23:40:14 -05:00
for ( auto wire : mod - > wires ( ) )
if ( wire - > port_output & & match_ids ( wire - > name , arg_memb . substr ( 2 ) ) )
sel . selected_members [ mod - > name ] . insert ( wire - > name ) ;
2014-02-06 12:35:33 -06:00
} else
2019-08-07 14:20:08 -05:00
if ( arg_memb . compare ( 0 , 2 , " x: " ) = = 0 ) {
2020-03-13 23:40:14 -05:00
for ( auto wire : mod - > wires ( ) )
if ( ( wire - > port_input | | wire - > port_output ) & & match_ids ( wire - > name , arg_memb . substr ( 2 ) ) )
sel . selected_members [ mod - > name ] . insert ( wire - > name ) ;
2014-02-06 12:35:33 -06:00
} else
2019-08-07 14:20:08 -05:00
if ( arg_memb . compare ( 0 , 2 , " s: " ) = = 0 ) {
2014-02-06 12:45:03 -06:00
size_t delim = arg_memb . substr ( 2 ) . find ( ' : ' ) ;
if ( delim = = std : : string : : npos ) {
2019-08-07 13:09:17 -05:00
int width = atoi ( arg_memb . substr ( 2 ) . c_str ( ) ) ;
2020-03-13 23:40:14 -05:00
for ( auto wire : mod - > wires ( ) )
if ( wire - > width = = width )
sel . selected_members [ mod - > name ] . insert ( wire - > name ) ;
2014-02-06 12:45:03 -06:00
} else {
std : : string min_str = arg_memb . substr ( 2 , delim ) ;
std : : string max_str = arg_memb . substr ( 2 + delim + 1 ) ;
2019-08-07 13:09:17 -05:00
int min_width = min_str . empty ( ) ? 0 : atoi ( min_str . c_str ( ) ) ;
int max_width = max_str . empty ( ) ? - 1 : atoi ( max_str . c_str ( ) ) ;
2020-03-13 23:40:14 -05:00
for ( auto wire : mod - > wires ( ) )
if ( min_width < = wire - > width & & ( wire - > width < = max_width | | max_width = = - 1 ) )
sel . selected_members [ mod - > name ] . insert ( wire - > name ) ;
2014-02-06 12:45:03 -06:00
}
} else
2019-08-07 14:20:08 -05:00
if ( arg_memb . compare ( 0 , 2 , " m: " ) = = 0 ) {
2013-01-05 04:13:26 -06:00
for ( auto & it : mod - > memories )
if ( match_ids ( it . first , arg_memb . substr ( 2 ) ) )
sel . selected_members [ mod - > name ] . insert ( it . first ) ;
} else
2020-03-12 12:00:21 -05:00
if ( arg_memb . compare ( 0 , 2 , " c: " ) = = 0 ) {
2020-03-13 23:40:14 -05:00
for ( auto cell : mod - > cells ( ) )
if ( match_ids ( cell - > name , arg_memb . substr ( 2 ) ) )
sel . selected_members [ mod - > name ] . insert ( cell - > name ) ;
2013-01-05 04:13:26 -06:00
} else
2019-08-07 14:20:08 -05:00
if ( arg_memb . compare ( 0 , 2 , " t: " ) = = 0 ) {
2020-03-13 23:40:14 -05:00
for ( auto cell : mod - > cells ( ) )
if ( match_ids ( cell - > type , arg_memb . substr ( 2 ) ) )
sel . selected_members [ mod - > name ] . insert ( cell - > name ) ;
2013-01-05 04:13:26 -06:00
} else
2019-08-07 14:20:08 -05:00
if ( arg_memb . compare ( 0 , 2 , " p: " ) = = 0 ) {
2013-01-05 04:13:26 -06:00
for ( auto & it : mod - > processes )
if ( match_ids ( it . first , arg_memb . substr ( 2 ) ) )
sel . selected_members [ mod - > name ] . insert ( it . first ) ;
2013-01-05 05:27:59 -06:00
} else
2019-08-07 14:20:08 -05:00
if ( arg_memb . compare ( 0 , 2 , " a: " ) = = 0 ) {
2020-03-13 23:40:14 -05:00
for ( auto wire : mod - > wires ( ) )
if ( match_attr ( wire - > attributes , arg_memb . substr ( 2 ) ) )
sel . selected_members [ mod - > name ] . insert ( wire - > name ) ;
2013-01-05 05:27:59 -06:00
for ( auto & it : mod - > memories )
2014-02-05 11:24:45 -06:00
if ( match_attr ( it . second - > attributes , arg_memb . substr ( 2 ) ) )
2013-01-05 05:27:59 -06:00
sel . selected_members [ mod - > name ] . insert ( it . first ) ;
2020-03-13 23:40:14 -05:00
for ( auto cell : mod - > cells ( ) )
if ( match_attr ( cell - > attributes , arg_memb . substr ( 2 ) ) )
sel . selected_members [ mod - > name ] . insert ( cell - > name ) ;
2013-01-05 05:27:59 -06:00
for ( auto & it : mod - > processes )
2014-02-05 11:24:45 -06:00
if ( match_attr ( it . second - > attributes , arg_memb . substr ( 2 ) ) )
sel . selected_members [ mod - > name ] . insert ( it . first ) ;
} else
2019-08-07 14:20:08 -05:00
if ( arg_memb . compare ( 0 , 2 , " r: " ) = = 0 ) {
2020-03-13 23:40:14 -05:00
for ( auto cell : mod - > cells ( ) )
if ( match_attr ( cell - > parameters , arg_memb . substr ( 2 ) ) )
sel . selected_members [ mod - > name ] . insert ( cell - > name ) ;
2013-01-05 04:13:26 -06:00
} else {
2020-03-12 12:00:21 -05:00
std : : string orig_arg_memb = arg_memb ;
2019-08-07 14:20:08 -05:00
if ( arg_memb . compare ( 0 , 2 , " n: " ) = = 0 )
2013-01-05 04:13:26 -06:00
arg_memb = arg_memb . substr ( 2 ) ;
2020-03-13 23:40:14 -05:00
for ( auto wire : mod - > wires ( ) )
2020-03-12 12:00:21 -05:00
if ( match_ids ( wire - > name , arg_memb ) ) {
2020-03-13 23:40:14 -05:00
sel . selected_members [ mod - > name ] . insert ( wire - > name ) ;
2020-03-12 12:00:21 -05:00
arg_memb_found [ orig_arg_memb ] = true ;
}
2013-01-05 04:13:26 -06:00
for ( auto & it : mod - > memories )
2020-03-12 12:00:21 -05:00
if ( match_ids ( it . first , arg_memb ) ) {
2013-01-05 04:13:26 -06:00
sel . selected_members [ mod - > name ] . insert ( it . first ) ;
2020-03-12 12:00:21 -05:00
arg_memb_found [ orig_arg_memb ] = true ;
}
2020-03-13 23:40:14 -05:00
for ( auto cell : mod - > cells ( ) )
2020-03-12 12:00:21 -05:00
if ( match_ids ( cell - > name , arg_memb ) ) {
2020-03-13 23:40:14 -05:00
sel . selected_members [ mod - > name ] . insert ( cell - > name ) ;
2020-03-12 12:00:21 -05:00
arg_memb_found [ orig_arg_memb ] = true ;
}
2013-01-05 04:13:26 -06:00
for ( auto & it : mod - > processes )
2020-03-12 12:00:21 -05:00
if ( match_ids ( it . first , arg_memb ) ) {
2013-01-05 04:13:26 -06:00
sel . selected_members [ mod - > name ] . insert ( it . first ) ;
2020-03-12 12:00:21 -05:00
arg_memb_found [ orig_arg_memb ] = true ;
}
2013-01-05 04:13:26 -06:00
}
}
select_filter_active_mod ( design , work_stack . back ( ) ) ;
2020-03-12 12:00:21 -05:00
for ( auto & it : arg_mod_found ) {
2020-03-23 01:31:41 -05:00
if ( it . second = = false & & ! disable_empty_warning ) {
2020-03-12 12:00:21 -05:00
log_warning ( " Selection \" %s \" did not match any module. \n " , it . first . c_str ( ) ) ;
}
}
for ( auto & it : arg_memb_found ) {
2020-03-23 01:31:41 -05:00
if ( it . second = = false & & ! disable_empty_warning ) {
2020-03-12 12:00:21 -05:00
log_warning ( " Selection \" %s \" did not match any object. \n " , it . first . c_str ( ) ) ;
}
}
2013-01-05 04:13:26 -06:00
}
2018-12-12 22:31:58 -06:00
static std : : string describe_selection_for_assert ( RTLIL : : Design * design , RTLIL : : Selection * sel )
{
std : : string desc = " Selection contains: \n " ;
2020-03-13 23:40:14 -05:00
for ( auto mod : design - > modules ( ) )
2018-12-12 22:31:58 -06:00
{
2020-03-13 23:40:14 -05:00
if ( sel - > selected_module ( mod - > name ) ) {
for ( auto wire : mod - > wires ( ) )
if ( sel - > selected_member ( mod - > name , wire - > name ) )
desc + = stringf ( " %s/%s \n " , id2cstr ( mod - > name ) , id2cstr ( wire - > name ) ) ;
for ( auto & it : mod - > memories )
if ( sel - > selected_member ( mod - > name , it . first ) )
desc + = stringf ( " %s/%s \n " , id2cstr ( mod - > name ) , id2cstr ( it . first ) ) ;
for ( auto cell : mod - > cells ( ) )
if ( sel - > selected_member ( mod - > name , cell - > name ) )
desc + = stringf ( " %s/%s \n " , id2cstr ( mod - > name ) , id2cstr ( cell - > name ) ) ;
for ( auto & it : mod - > processes )
if ( sel - > selected_member ( mod - > name , it . first ) )
desc + = stringf ( " %s/%s \n " , id2cstr ( mod - > name ) , id2cstr ( it . first ) ) ;
2018-12-12 22:31:58 -06:00
}
}
return desc ;
}
2014-09-27 09:17:53 -05:00
PRIVATE_NAMESPACE_END
YOSYS_NAMESPACE_BEGIN
2013-04-01 07:12:17 -05:00
// used in kernel/register.cc and maybe other locations, extern decl. in register.h
2015-02-08 11:56:06 -06:00
void handle_extra_select_args ( Pass * pass , vector < string > args , size_t argidx , size_t args_size , RTLIL : : Design * design )
2013-03-03 03:05:37 -06:00
{
work_stack . clear ( ) ;
2013-04-01 07:12:17 -05:00
for ( ; argidx < args_size ; argidx + + ) {
2019-08-07 14:20:08 -05:00
if ( args [ argidx ] . compare ( 0 , 1 , " - " ) = = 0 ) {
2020-03-13 23:40:14 -05:00
if ( pass ! = nullptr )
2013-04-01 07:12:17 -05:00
pass - > cmd_error ( args , argidx , " Unexpected option in selection arguments. " ) ;
else
log_cmd_error ( " Unexpected option in selection arguments. " ) ;
}
2013-03-03 03:05:37 -06:00
select_stmt ( design , args [ argidx ] ) ;
}
while ( work_stack . size ( ) > 1 ) {
select_op_union ( design , work_stack . front ( ) , work_stack . back ( ) ) ;
work_stack . pop_back ( ) ;
}
2015-02-08 11:56:06 -06:00
if ( work_stack . empty ( ) )
2013-04-01 07:12:17 -05:00
design - > selection_stack . push_back ( RTLIL : : Selection ( false ) ) ;
2015-02-08 11:56:06 -06:00
else
design - > selection_stack . push_back ( work_stack . back ( ) ) ;
}
// extern decl. in register.h
RTLIL : : Selection eval_select_args ( const vector < string > & args , RTLIL : : Design * design )
{
work_stack . clear ( ) ;
for ( auto & arg : args )
select_stmt ( design , arg ) ;
while ( work_stack . size ( ) > 1 ) {
select_op_union ( design , work_stack . front ( ) , work_stack . back ( ) ) ;
work_stack . pop_back ( ) ;
}
if ( work_stack . empty ( ) )
return RTLIL : : Selection ( false ) ;
return work_stack . back ( ) ;
}
// extern decl. in register.h
2015-02-08 12:06:16 -06:00
void eval_select_op ( vector < RTLIL : : Selection > & work , const string & op , RTLIL : : Design * design )
2015-02-08 11:56:06 -06:00
{
work_stack . swap ( work ) ;
select_stmt ( design , op ) ;
work_stack . swap ( work ) ;
2013-03-03 03:05:37 -06:00
}
2014-09-27 09:17:53 -05:00
YOSYS_NAMESPACE_END
PRIVATE_NAMESPACE_BEGIN
2013-01-05 04:13:26 -06:00
struct SelectPass : public Pass {
2013-02-28 05:51:30 -06:00
SelectPass ( ) : Pass ( " select " , " modify and view the list of selected objects " ) { }
2018-07-21 01:41:18 -05:00
void help ( ) YS_OVERRIDE
2013-02-28 05:51:30 -06:00
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log ( " \n " ) ;
2015-02-06 03:01:22 -06:00
log ( " select [ -add | -del | -set <name> ] {-read <filename> | <selection>} \n " ) ;
2020-04-14 12:58:42 -05:00
log ( " select [ -unset <name> ] \n " ) ;
2016-07-01 05:24:13 -05:00
log ( " select [ <assert_option> ] {-read <filename> | <selection>} \n " ) ;
2013-03-14 07:02:10 -05:00
log ( " select [ -list | -write <filename> | -count | -clear ] \n " ) ;
2013-02-28 05:51:30 -06:00
log ( " select -module <modname> \n " ) ;
log ( " \n " ) ;
log ( " Most commands use the list of currently selected objects to determine which part \n " ) ;
log ( " of the design to operate on. This command can be used to modify and view this \n " ) ;
log ( " list of selected objects. \n " ) ;
log ( " \n " ) ;
log ( " Note that many commands support an optional [selection] argument that can be \n " ) ;
2018-12-07 13:14:07 -06:00
log ( " used to override the global selection for the command. The syntax of this \n " ) ;
2013-02-28 05:51:30 -06:00
log ( " optional argument is identical to the syntax of the <selection> argument \n " ) ;
log ( " described here. \n " ) ;
log ( " \n " ) ;
log ( " -add, -del \n " ) ;
log ( " add or remove the given objects to the current selection. \n " ) ;
log ( " without this options the current selection is replaced. \n " ) ;
log ( " \n " ) ;
log ( " -set <name> \n " ) ;
log ( " do not modify the current selection. instead save the new selection \n " ) ;
2014-02-05 08:53:02 -06:00
log ( " under the given name (see @<name> below). to save the current selection, \n " ) ;
log ( " use \" select -set <name> %% \" \n " ) ;
2013-02-28 05:51:30 -06:00
log ( " \n " ) ;
2020-04-14 12:58:42 -05:00
log ( " -unset <name> \n " ) ;
log ( " do not modify the current selection. instead remove a previously saved \n " ) ;
log ( " selection under the given name (see @<name> below). " ) ;
log ( " \n " ) ;
2014-01-17 09:34:50 -06:00
log ( " -assert-none \n " ) ;
2014-02-05 08:53:02 -06:00
log ( " do not modify the current selection. instead assert that the given \n " ) ;
log ( " selection is empty. i.e. produce an error if any object matching the \n " ) ;
log ( " selection is found. \n " ) ;
2014-01-17 09:34:50 -06:00
log ( " \n " ) ;
log ( " -assert-any \n " ) ;
2014-02-05 08:53:02 -06:00
log ( " do not modify the current selection. instead assert that the given \n " ) ;
log ( " selection is non-empty. i.e. produce an error if no object matching \n " ) ;
log ( " the selection is found. \n " ) ;
2014-01-17 09:34:50 -06:00
log ( " \n " ) ;
2014-07-20 13:15:49 -05:00
log ( " -assert-count N \n " ) ;
log ( " do not modify the current selection. instead assert that the given \n " ) ;
log ( " selection contains exactly N objects. \n " ) ;
log ( " \n " ) ;
2016-07-01 05:24:13 -05:00
log ( " -assert-max N \n " ) ;
2016-07-01 01:24:22 -05:00
log ( " do not modify the current selection. instead assert that the given \n " ) ;
2016-07-01 05:24:13 -05:00
log ( " selection contains less than or exactly N objects. \n " ) ;
log ( " \n " ) ;
log ( " -assert-min N \n " ) ;
log ( " do not modify the current selection. instead assert that the given \n " ) ;
log ( " selection contains at least N objects. \n " ) ;
2016-07-01 01:24:22 -05:00
log ( " \n " ) ;
2013-02-28 05:51:30 -06:00
log ( " -list \n " ) ;
log ( " list all objects in the current selection \n " ) ;
log ( " \n " ) ;
2013-03-14 07:02:10 -05:00
log ( " -write <filename> \n " ) ;
log ( " like -list but write the output to the specified file \n " ) ;
log ( " \n " ) ;
2015-02-06 03:01:22 -06:00
log ( " -read <filename> \n " ) ;
log ( " read the specified file (written by -write) \n " ) ;
log ( " \n " ) ;
2013-03-08 01:31:12 -06:00
log ( " -count \n " ) ;
log ( " count all objects in the current selection \n " ) ;
log ( " \n " ) ;
2013-02-28 05:51:30 -06:00
log ( " -clear \n " ) ;
2014-02-04 16:23:44 -06:00
log ( " clear the current selection. this effectively selects the whole \n " ) ;
log ( " design. it also resets the selected module (see -module). use the \n " ) ;
log ( " command 'select *' to select everything but stay in the current module. \n " ) ;
log ( " \n " ) ;
log ( " -none \n " ) ;
log ( " create an empty selection. the current module is unchanged. \n " ) ;
2013-02-28 05:51:30 -06:00
log ( " \n " ) ;
log ( " -module <modname> \n " ) ;
2013-03-17 16:02:30 -05:00
log ( " limit the current scope to the specified module. \n " ) ;
2013-02-28 05:51:30 -06:00
log ( " the difference between this and simply selecting the module \n " ) ;
log ( " is that all object names are interpreted relative to this \n " ) ;
log ( " module after this command until the selection is cleared again. \n " ) ;
log ( " \n " ) ;
log ( " When this command is called without an argument, the current selection \n " ) ;
2013-03-17 16:02:30 -05:00
log ( " is displayed in a compact form (i.e. only the module name when a whole module \n " ) ;
2013-02-28 05:51:30 -06:00
log ( " is selected). \n " ) ;
log ( " \n " ) ;
log ( " The <selection> argument itself is a series of commands for a simple stack \n " ) ;
log ( " machine. Each element on the stack represents a set of selected objects. \n " ) ;
log ( " After this commands have been executed, the union of all remaining sets \n " ) ;
log ( " on the stack is computed and used as selection for the command. \n " ) ;
log ( " \n " ) ;
log ( " Pushing (selecting) object when not in -module mode: \n " ) ;
log ( " \n " ) ;
log ( " <mod_pattern> \n " ) ;
log ( " select the specified module(s) \n " ) ;
log ( " \n " ) ;
log ( " <mod_pattern>/<obj_pattern> \n " ) ;
log ( " select the specified object(s) from the module(s) \n " ) ;
log ( " \n " ) ;
log ( " Pushing (selecting) object when in -module mode: \n " ) ;
log ( " \n " ) ;
log ( " <obj_pattern> \n " ) ;
log ( " select the specified object(s) from the current module \n " ) ;
log ( " \n " ) ;
2014-02-02 09:47:17 -06:00
log ( " A <mod_pattern> can be a module name, wildcard expression (*, ?, [..]) \n " ) ;
log ( " matching module names, or one of the following: \n " ) ;
log ( " \n " ) ;
log ( " A:<pattern>, A:<pattern>=<pattern> \n " ) ;
log ( " all modules with an attribute matching the given pattern \n " ) ;
2014-02-05 11:24:45 -06:00
log ( " in addition to = also <, <=, >=, and > are supported \n " ) ;
2013-02-28 05:51:30 -06:00
log ( " \n " ) ;
2020-03-17 12:44:06 -05:00
log ( " N:<pattern> \n " ) ;
log ( " all modules with a name matching the given pattern \n " ) ;
log ( " (i.e. 'N:' is optional as it is the default matching rule) \n " ) ;
log ( " \n " ) ;
2013-02-28 05:51:30 -06:00
log ( " An <obj_pattern> can be an object name, wildcard expression, or one of \n " ) ;
log ( " the following: \n " ) ;
log ( " \n " ) ;
log ( " w:<pattern> \n " ) ;
log ( " all wires with a name matching the given wildcard pattern \n " ) ;
log ( " \n " ) ;
2014-02-06 12:35:33 -06:00
log ( " i:<pattern>, o:<pattern>, x:<pattern> \n " ) ;
2014-02-06 12:45:03 -06:00
log ( " all inputs (i:), outputs (o:) or any ports (x:) with matching names \n " ) ;
log ( " \n " ) ;
log ( " s:<size>, s:<min>:<max> \n " ) ;
log ( " all wires with a matching width \n " ) ;
2014-02-06 12:35:33 -06:00
log ( " \n " ) ;
2013-02-28 05:51:30 -06:00
log ( " m:<pattern> \n " ) ;
log ( " all memories with a name matching the given pattern \n " ) ;
log ( " \n " ) ;
log ( " c:<pattern> \n " ) ;
log ( " all cells with a name matching the given pattern \n " ) ;
log ( " \n " ) ;
log ( " t:<pattern> \n " ) ;
log ( " all cells with a type matching the given pattern \n " ) ;
log ( " \n " ) ;
log ( " p:<pattern> \n " ) ;
log ( " all processes with a name matching the given pattern \n " ) ;
log ( " \n " ) ;
log ( " a:<pattern> \n " ) ;
log ( " all objects with an attribute name matching the given pattern \n " ) ;
log ( " \n " ) ;
log ( " a:<pattern>=<pattern> \n " ) ;
2014-02-05 11:24:45 -06:00
log ( " all objects with a matching attribute name-value-pair. \n " ) ;
log ( " in addition to = also <, <=, >=, and > are supported \n " ) ;
log ( " \n " ) ;
log ( " r:<pattern>, r:<pattern>=<pattern> \n " ) ;
log ( " cells with matching parameters. also with <, <=, >= and >. \n " ) ;
2013-02-28 05:51:30 -06:00
log ( " \n " ) ;
log ( " n:<pattern> \n " ) ;
2013-03-17 16:02:30 -05:00
log ( " all objects with a name matching the given pattern \n " ) ;
log ( " (i.e. 'n:' is optional as it is the default matching rule) \n " ) ;
2013-02-28 05:51:30 -06:00
log ( " \n " ) ;
log ( " @<name> \n " ) ;
log ( " push the selection saved prior with 'select -set <name> ...' \n " ) ;
log ( " \n " ) ;
log ( " The following actions can be performed on the top sets on the stack: \n " ) ;
log ( " \n " ) ;
2013-03-14 10:15:24 -05:00
log ( " %% \n " ) ;
2013-02-28 05:51:30 -06:00
log ( " push a copy of the current selection to the stack \n " ) ;
log ( " \n " ) ;
2013-03-14 10:15:24 -05:00
log ( " %%%% \n " ) ;
2013-03-08 01:47:29 -06:00
log ( " replace the stack with a union of all elements on it \n " ) ;
log ( " \n " ) ;
2013-03-14 10:15:24 -05:00
log ( " %%n \n " ) ;
2013-02-28 05:51:30 -06:00
log ( " replace top set with its invert \n " ) ;
log ( " \n " ) ;
2013-03-14 10:15:24 -05:00
log ( " %%u \n " ) ;
2013-02-28 05:51:30 -06:00
log ( " replace the two top sets on the stack with their union \n " ) ;
log ( " \n " ) ;
2013-03-14 10:15:24 -05:00
log ( " %%i \n " ) ;
2013-02-28 05:51:30 -06:00
log ( " replace the two top sets on the stack with their intersection \n " ) ;
log ( " \n " ) ;
2013-03-14 10:15:24 -05:00
log ( " %%d \n " ) ;
2013-02-28 05:51:30 -06:00
log ( " pop the top set from the stack and subtract it from the new top \n " ) ;
log ( " \n " ) ;
2014-06-14 09:19:32 -05:00
log ( " %%D \n " ) ;
log ( " like %%d but swap the roles of two top sets on the stack \n " ) ;
log ( " \n " ) ;
log ( " %%c \n " ) ;
2015-08-14 04:27:19 -05:00
log ( " create a copy of the top set from the stack and push it \n " ) ;
2014-06-14 09:19:32 -05:00
log ( " \n " ) ;
2013-03-14 10:15:24 -05:00
log ( " %%x[<num1>|*][.<num2>][:<rule>[:<rule>..]] \n " ) ;
2013-03-17 16:02:30 -05:00
log ( " expand top set <num1> num times according to the specified rules. \n " ) ;
2013-03-05 05:53:40 -06:00
log ( " (i.e. select all cells connected to selected wires and select all \n " ) ;
log ( " wires connected to selected cells) The rules specify which cell \n " ) ;
log ( " ports to use for this. the syntax for a rule is a '-' for exclusion \n " ) ;
2014-09-06 01:47:06 -05:00
log ( " and a '+' for inclusion, followed by an optional comma separated \n " ) ;
2013-03-17 16:02:30 -05:00
log ( " list of cell types followed by an optional comma separated list of \n " ) ;
2013-03-08 03:15:15 -06:00
log ( " cell ports in square brackets. a rule can also be just a cell or wire \n " ) ;
log ( " name that limits the expansion (is included but does not go beyond). \n " ) ;
2013-03-14 09:35:05 -05:00
log ( " select at most <num2> objects. a warning message is printed when this \n " ) ;
log ( " limit is reached. When '*' is used instead of <num1> then the process \n " ) ;
log ( " is repeated until no further object are selected. \n " ) ;
2013-03-05 05:53:40 -06:00
log ( " \n " ) ;
2013-03-14 10:15:24 -05:00
log ( " %%ci[<num1>|*][.<num2>][:<rule>[:<rule>..]] \n " ) ;
log ( " %%co[<num1>|*][.<num2>][:<rule>[:<rule>..]] \n " ) ;
2015-08-14 03:56:05 -05:00
log ( " similar to %%x, but only select input (%%ci) or output cones (%%co) \n " ) ;
2013-03-14 09:57:47 -05:00
log ( " \n " ) ;
2015-02-18 00:18:34 -06:00
log ( " %%xe[...] %%cie[...] %%coe \n " ) ;
log ( " like %%x, %%ci, and %%co but only consider combinatorial cells \n " ) ;
log ( " \n " ) ;
2014-02-08 09:31:38 -06:00
log ( " %%a \n " ) ;
log ( " expand top set by selecting all wires that are (at least in part) \n " ) ;
log ( " aliases for selected wires. \n " ) ;
log ( " \n " ) ;
2014-02-06 10:36:39 -06:00
log ( " %%s \n " ) ;
2015-04-07 15:22:09 -05:00
log ( " expand top set by adding all modules that implement cells in selected \n " ) ;
2014-02-06 10:36:39 -06:00
log ( " modules \n " ) ;
log ( " \n " ) ;
2014-02-06 12:30:08 -06:00
log ( " %%m \n " ) ;
log ( " expand top set by selecting all modules that contain selected objects \n " ) ;
log ( " \n " ) ;
2015-04-07 15:22:09 -05:00
log ( " %%M \n " ) ;
log ( " select modules that implement selected cells \n " ) ;
log ( " \n " ) ;
log ( " %%C \n " ) ;
log ( " select cells that implement selected modules \n " ) ;
log ( " \n " ) ;
2015-12-20 06:35:58 -06:00
log ( " %%R[<num>] \n " ) ;
log ( " select <num> random objects from top selection (default 1) \n " ) ;
log ( " \n " ) ;
2013-03-05 05:53:40 -06:00
log ( " Example: the following command selects all wires that are connected to a \n " ) ;
log ( " 'GATE' input of a 'SWITCH' cell: \n " ) ;
log ( " \n " ) ;
2013-03-14 10:15:24 -05:00
log ( " select */t:SWITCH %%x:+[GATE] */t:SWITCH %%d \n " ) ;
2013-03-03 10:41:46 -06:00
log ( " \n " ) ;
2013-02-28 05:51:30 -06:00
}
2018-07-21 01:41:18 -05:00
void execute ( std : : vector < std : : string > args , RTLIL : : Design * design ) YS_OVERRIDE
2013-01-05 04:13:26 -06:00
{
bool add_mode = false ;
bool del_mode = false ;
bool clear_mode = false ;
2014-02-04 16:23:44 -06:00
bool none_mode = false ;
2013-01-05 04:13:26 -06:00
bool list_mode = false ;
2013-03-08 01:31:12 -06:00
bool count_mode = false ;
2013-01-05 04:13:26 -06:00
bool got_module = false ;
2014-01-17 09:34:50 -06:00
bool assert_none = false ;
bool assert_any = false ;
2014-07-20 13:15:49 -05:00
int assert_count = - 1 ;
2016-07-01 05:24:13 -05:00
int assert_max = - 1 ;
int assert_min = - 1 ;
2015-02-06 03:01:22 -06:00
std : : string write_file , read_file ;
2020-04-14 12:58:42 -05:00
std : : string set_name , unset_name , sel_str ;
2013-01-05 04:13:26 -06:00
work_stack . clear ( ) ;
size_t argidx ;
for ( argidx = 1 ; argidx < args . size ( ) ; argidx + + )
{
std : : string arg = args [ argidx ] ;
if ( arg = = " -add " ) {
add_mode = true ;
continue ;
}
if ( arg = = " -del " ) {
del_mode = true ;
continue ;
}
2014-01-17 09:34:50 -06:00
if ( arg = = " -assert-none " ) {
assert_none = true ;
continue ;
}
if ( arg = = " -assert-any " ) {
assert_any = true ;
continue ;
}
2014-07-20 13:15:49 -05:00
if ( arg = = " -assert-count " & & argidx + 1 < args . size ( ) ) {
2019-08-07 13:09:17 -05:00
assert_count = atoi ( args [ + + argidx ] . c_str ( ) ) ;
2014-07-20 13:15:49 -05:00
continue ;
}
2016-07-01 05:24:13 -05:00
if ( arg = = " -assert-max " & & argidx + 1 < args . size ( ) ) {
2019-08-07 13:09:17 -05:00
assert_max = atoi ( args [ + + argidx ] . c_str ( ) ) ;
2016-07-01 05:24:13 -05:00
continue ;
}
if ( arg = = " -assert-min " & & argidx + 1 < args . size ( ) ) {
2019-08-07 13:09:17 -05:00
assert_min = atoi ( args [ + + argidx ] . c_str ( ) ) ;
2016-07-01 01:24:22 -05:00
continue ;
}
2013-01-05 04:13:26 -06:00
if ( arg = = " -clear " ) {
clear_mode = true ;
continue ;
}
2014-02-04 16:23:44 -06:00
if ( arg = = " -none " ) {
none_mode = true ;
continue ;
}
2013-01-05 04:13:26 -06:00
if ( arg = = " -list " ) {
list_mode = true ;
continue ;
}
2013-03-14 07:02:10 -05:00
if ( arg = = " -write " & & argidx + 1 < args . size ( ) ) {
write_file = args [ + + argidx ] ;
continue ;
}
2015-02-06 03:01:22 -06:00
if ( arg = = " -read " & & argidx + 1 < args . size ( ) ) {
read_file = args [ + + argidx ] ;
continue ;
}
2013-03-08 01:31:12 -06:00
if ( arg = = " -count " ) {
count_mode = true ;
continue ;
}
2013-01-05 04:13:26 -06:00
if ( arg = = " -module " & & argidx + 1 < args . size ( ) ) {
RTLIL : : IdString mod_name = RTLIL : : escape_id ( args [ + + argidx ] ) ;
2020-03-16 15:32:46 -05:00
if ( design - > module ( mod_name ) = = nullptr )
2013-03-01 01:57:58 -06:00
log_cmd_error ( " No such module: %s \n " , id2cstr ( mod_name ) ) ;
2014-08-02 11:58:40 -05:00
design - > selected_active_module = mod_name . str ( ) ;
2013-01-05 04:13:26 -06:00
got_module = true ;
continue ;
}
2013-02-28 05:51:30 -06:00
if ( arg = = " -set " & & argidx + 1 < args . size ( ) ) {
set_name = RTLIL : : escape_id ( args [ + + argidx ] ) ;
continue ;
}
2020-04-14 12:58:42 -05:00
if ( arg = = " -unset " & & argidx + 1 < args . size ( ) ) {
unset_name = RTLIL : : escape_id ( args [ + + argidx ] ) ;
continue ;
}
2013-01-05 04:13:26 -06:00
if ( arg . size ( ) > 0 & & arg [ 0 ] = = ' - ' )
2014-09-06 01:47:06 -05:00
log_cmd_error ( " Unknown option %s. \n " , arg . c_str ( ) ) ;
2020-03-23 01:31:41 -05:00
bool disable_empty_warning = count_mode | | assert_none | | assert_any | | ( assert_count ! = - 1 ) | | ( assert_max ! = - 1 ) | | ( assert_min ! = - 1 ) ;
select_stmt ( design , arg , disable_empty_warning ) ;
2014-02-05 11:52:55 -06:00
sel_str + = " " + arg ;
2013-01-05 04:13:26 -06:00
}
2015-02-06 03:01:22 -06:00
if ( ! read_file . empty ( ) )
{
if ( ! sel_str . empty ( ) )
log_cmd_error ( " Option -read can not be combined with a selection expression. \n " ) ;
std : : ifstream f ( read_file ) ;
2018-01-07 09:36:13 -06:00
yosys_input_files . insert ( read_file ) ;
2015-02-06 03:01:22 -06:00
if ( f . fail ( ) )
log_error ( " Can't open '%s' for reading: %s \n " , read_file . c_str ( ) , strerror ( errno ) ) ;
RTLIL : : Selection sel ( false ) ;
string line ;
while ( std : : getline ( f , line ) ) {
size_t slash_pos = line . find ( ' / ' ) ;
if ( slash_pos = = string : : npos ) {
log_warning ( " Ignoring line without slash in 'select -read': %s \n " , line . c_str ( ) ) ;
continue ;
}
IdString mod_name = RTLIL : : escape_id ( line . substr ( 0 , slash_pos ) ) ;
IdString obj_name = RTLIL : : escape_id ( line . substr ( slash_pos + 1 ) ) ;
sel . selected_members [ mod_name ] . insert ( obj_name ) ;
}
select_filter_active_mod ( design , sel ) ;
sel . optimize ( design ) ;
work_stack . push_back ( sel ) ;
}
2013-01-05 04:13:26 -06:00
if ( clear_mode & & args . size ( ) ! = 2 )
2014-01-17 09:34:50 -06:00
log_cmd_error ( " Option -clear can not be combined with any other options. \n " ) ;
2013-01-05 04:13:26 -06:00
2014-02-04 16:23:44 -06:00
if ( none_mode & & args . size ( ) ! = 2 )
log_cmd_error ( " Option -none can not be combined with any other options. \n " ) ;
2016-07-01 05:24:13 -05:00
if ( add_mode + del_mode + assert_none + assert_any + ( assert_count > = 0 ) + ( assert_max > = 0 ) + ( assert_min > = 0 ) > 1 )
log_cmd_error ( " Options -add, -del, -assert-none, -assert-any, assert-count, -assert-max or -assert-min can not be combined. \n " ) ;
2013-01-05 04:13:26 -06:00
2016-07-01 05:24:13 -05:00
if ( ( list_mode | | ! write_file . empty ( ) | | count_mode ) & & ( add_mode | | del_mode | | assert_none | | assert_any | | assert_count > = 0 | | assert_max > = 0 | | assert_min > = 0 ) )
log_cmd_error ( " Options -list, -write and -count can not be combined with -add, -del, -assert-none, -assert-any, assert-count, -assert-max, or -assert-min. \n " ) ;
2013-01-05 04:13:26 -06:00
2020-04-14 12:58:42 -05:00
if ( ! set_name . empty ( ) & & ( list_mode | | ! write_file . empty ( ) | | count_mode | | add_mode | | ! unset_name . empty ( ) | | del_mode | | assert_none | | assert_any | | assert_count > = 0 | | assert_max > = 0 | | assert_min > = 0 ) )
log_cmd_error ( " Option -set can not be combined with -list, -write, -count, -add, -del, -unset, -assert-none, -assert-any, -assert-count, -assert-max, or -assert-min. \n " ) ;
if ( ! unset_name . empty ( ) & & ( list_mode | | ! write_file . empty ( ) | | count_mode | | add_mode | | ! set_name . empty ( ) | | del_mode | | assert_none | | assert_any | | assert_count > = 0 | | assert_max > = 0 | | assert_min > = 0 ) )
log_cmd_error ( " Option -unset can not be combined with -list, -write, -count, -add, -del, -set, -assert-none, -assert-any, -assert-count, -assert-max, or -assert-min. \n " ) ;
2013-02-28 05:51:30 -06:00
2013-01-05 04:13:26 -06:00
if ( work_stack . size ( ) = = 0 & & got_module ) {
RTLIL : : Selection sel ;
select_filter_active_mod ( design , sel ) ;
work_stack . push_back ( sel ) ;
}
while ( work_stack . size ( ) > 1 ) {
select_op_union ( design , work_stack . front ( ) , work_stack . back ( ) ) ;
work_stack . pop_back ( ) ;
}
2014-07-28 04:08:55 -05:00
log_assert ( design - > selection_stack . size ( ) > 0 ) ;
2013-01-05 04:13:26 -06:00
2014-02-04 16:23:44 -06:00
if ( clear_mode ) {
2013-01-05 04:13:26 -06:00
design - > selection_stack . back ( ) = RTLIL : : Selection ( true ) ;
design - > selected_active_module = std : : string ( ) ;
return ;
}
2014-02-04 16:23:44 -06:00
if ( none_mode ) {
design - > selection_stack . back ( ) = RTLIL : : Selection ( false ) ;
return ;
}
2013-03-14 07:02:10 -05:00
if ( list_mode | | count_mode | | ! write_file . empty ( ) )
2013-01-05 04:13:26 -06:00
{
2020-03-13 23:40:14 -05:00
# define LOG_OBJECT(...) { if (list_mode) log(__VA_ARGS__); if (f != nullptr) fprintf(f, __VA_ARGS__); total_count++; }
2013-03-08 01:31:12 -06:00
int total_count = 0 ;
2020-03-13 23:40:14 -05:00
FILE * f = nullptr ;
2013-03-14 07:02:10 -05:00
if ( ! write_file . empty ( ) ) {
f = fopen ( write_file . c_str ( ) , " w " ) ;
2018-01-07 09:36:13 -06:00
yosys_output_files . insert ( write_file ) ;
2020-03-13 23:40:14 -05:00
if ( f = = nullptr )
2013-03-14 07:02:10 -05:00
log_error ( " Can't open '%s' for writing: %s \n " , write_file . c_str ( ) , strerror ( errno ) ) ;
}
2013-01-05 04:13:26 -06:00
RTLIL : : Selection * sel = & design - > selection_stack . back ( ) ;
if ( work_stack . size ( ) > 0 )
sel = & work_stack . back ( ) ;
sel - > optimize ( design ) ;
2020-03-13 23:40:14 -05:00
for ( auto mod : design - > modules ( ) )
2013-01-05 04:13:26 -06:00
{
2020-03-13 23:40:14 -05:00
if ( sel - > selected_whole_module ( mod - > name ) & & list_mode )
log ( " %s \n " , id2cstr ( mod - > name ) ) ;
if ( sel - > selected_module ( mod - > name ) ) {
for ( auto wire : mod - > wires ( ) )
if ( sel - > selected_member ( mod - > name , wire - > name ) )
LOG_OBJECT ( " %s/%s \n " , id2cstr ( mod - > name ) , id2cstr ( wire - > name ) )
for ( auto & it : mod - > memories )
if ( sel - > selected_member ( mod - > name , it . first ) )
LOG_OBJECT ( " %s/%s \n " , id2cstr ( mod - > name ) , id2cstr ( it . first ) )
for ( auto cell : mod - > cells ( ) )
if ( sel - > selected_member ( mod - > name , cell - > name ) )
LOG_OBJECT ( " %s/%s \n " , id2cstr ( mod - > name ) , id2cstr ( cell - > name ) )
for ( auto & it : mod - > processes )
if ( sel - > selected_member ( mod - > name , it . first ) )
LOG_OBJECT ( " %s/%s \n " , id2cstr ( mod - > name ) , id2cstr ( it . first ) )
2013-01-05 04:13:26 -06:00
}
}
2013-03-08 01:31:12 -06:00
if ( count_mode )
log ( " %d objects. \n " , total_count ) ;
2020-03-13 23:40:14 -05:00
if ( f ! = nullptr )
2013-03-14 07:02:10 -05:00
fclose ( f ) ;
2013-03-08 01:31:12 -06:00
# undef LOG_OBJECT
2013-01-05 04:13:26 -06:00
return ;
}
if ( add_mode )
{
if ( work_stack . size ( ) = = 0 )
log_cmd_error ( " Nothing to add to selection. \n " ) ;
select_op_union ( design , design - > selection_stack . back ( ) , work_stack . back ( ) ) ;
design - > selection_stack . back ( ) . optimize ( design ) ;
return ;
}
if ( del_mode )
{
if ( work_stack . size ( ) = = 0 )
log_cmd_error ( " Nothing to delete from selection. \n " ) ;
select_op_diff ( design , design - > selection_stack . back ( ) , work_stack . back ( ) ) ;
design - > selection_stack . back ( ) . optimize ( design ) ;
return ;
}
2014-01-17 09:34:50 -06:00
if ( assert_none )
{
if ( work_stack . size ( ) = = 0 )
log_cmd_error ( " No selection to check. \n " ) ;
2015-07-16 15:10:26 -05:00
work_stack . back ( ) . optimize ( design ) ;
2014-01-17 09:34:50 -06:00
if ( ! work_stack . back ( ) . empty ( ) )
2018-12-12 22:31:58 -06:00
{
RTLIL : : Selection * sel = & work_stack . back ( ) ;
sel - > optimize ( design ) ;
std : : string desc = describe_selection_for_assert ( design , sel ) ;
log_error ( " Assertion failed: selection is not empty:%s \n %s " , sel_str . c_str ( ) , desc . c_str ( ) ) ;
}
2014-01-17 09:34:50 -06:00
return ;
}
if ( assert_any )
{
if ( work_stack . size ( ) = = 0 )
log_cmd_error ( " No selection to check. \n " ) ;
2015-07-16 15:10:26 -05:00
work_stack . back ( ) . optimize ( design ) ;
2014-01-17 09:34:50 -06:00
if ( work_stack . back ( ) . empty ( ) )
2018-12-12 22:31:58 -06:00
{
RTLIL : : Selection * sel = & work_stack . back ( ) ;
sel - > optimize ( design ) ;
std : : string desc = describe_selection_for_assert ( design , sel ) ;
log_error ( " Assertion failed: selection is empty:%s \n %s " , sel_str . c_str ( ) , desc . c_str ( ) ) ;
}
2014-01-17 09:34:50 -06:00
return ;
}
2016-07-01 05:24:13 -05:00
if ( assert_count > = 0 | | assert_max > = 0 | | assert_min > = 0 )
2014-07-20 13:15:49 -05:00
{
int total_count = 0 ;
if ( work_stack . size ( ) = = 0 )
log_cmd_error ( " No selection to check. \n " ) ;
RTLIL : : Selection * sel = & work_stack . back ( ) ;
sel - > optimize ( design ) ;
2020-03-13 23:40:14 -05:00
for ( auto mod : design - > modules ( ) )
if ( sel - > selected_module ( mod - > name ) ) {
for ( auto wire : mod - > wires ( ) )
if ( sel - > selected_member ( mod - > name , wire - > name ) )
2014-07-20 13:15:49 -05:00
total_count + + ;
2020-03-13 23:40:14 -05:00
for ( auto & it : mod - > memories )
if ( sel - > selected_member ( mod - > name , it . first ) )
2014-07-20 13:15:49 -05:00
total_count + + ;
2020-03-13 23:40:14 -05:00
for ( auto cell : mod - > cells ( ) )
if ( sel - > selected_member ( mod - > name , cell - > name ) )
2014-07-20 13:15:49 -05:00
total_count + + ;
2020-03-13 23:40:14 -05:00
for ( auto & it : mod - > processes )
if ( sel - > selected_member ( mod - > name , it . first ) )
2014-07-20 13:15:49 -05:00
total_count + + ;
}
2016-07-01 05:24:13 -05:00
if ( assert_count > = 0 & & assert_count ! = total_count )
2018-12-12 22:31:58 -06:00
{
std : : string desc = describe_selection_for_assert ( design , sel ) ;
log_error ( " Assertion failed: selection contains %d elements instead of the asserted %d:%s \n %s " ,
total_count , assert_count , sel_str . c_str ( ) , desc . c_str ( ) ) ;
}
2016-07-01 05:24:13 -05:00
if ( assert_max > = 0 & & assert_max < total_count )
2018-12-12 22:31:58 -06:00
{
std : : string desc = describe_selection_for_assert ( design , sel ) ;
log_error ( " Assertion failed: selection contains %d elements, more than the maximum number %d:%s \n %s " ,
total_count , assert_max , sel_str . c_str ( ) , desc . c_str ( ) ) ;
}
2016-07-01 05:24:13 -05:00
if ( assert_min > = 0 & & assert_min > total_count )
2018-12-12 22:31:58 -06:00
{
std : : string desc = describe_selection_for_assert ( design , sel ) ;
log_error ( " Assertion failed: selection contains %d elements, less than the minimum number %d:%s \n %s " ,
total_count , assert_min , sel_str . c_str ( ) , desc . c_str ( ) ) ;
}
2016-07-01 01:24:22 -05:00
return ;
}
2013-02-28 05:51:30 -06:00
if ( ! set_name . empty ( ) )
{
if ( work_stack . size ( ) = = 0 )
2014-02-04 16:31:06 -06:00
design - > selection_vars [ set_name ] = RTLIL : : Selection ( false ) ;
2013-02-28 05:51:30 -06:00
else
design - > selection_vars [ set_name ] = work_stack . back ( ) ;
2020-04-14 12:58:42 -05:00
return ;
}
if ( ! unset_name . empty ( ) )
{
if ( ! design - > selection_vars . erase ( unset_name ) )
log_error ( " Selection '%s' does not exist! \n " , unset_name . c_str ( ) ) ;
2013-02-28 05:51:30 -06:00
return ;
}
2013-01-05 04:13:26 -06:00
if ( work_stack . size ( ) = = 0 ) {
RTLIL : : Selection & sel = design - > selection_stack . back ( ) ;
if ( sel . full_selection )
log ( " * \n " ) ;
for ( auto & it : sel . selected_modules )
2013-03-01 01:57:58 -06:00
log ( " %s \n " , id2cstr ( it ) ) ;
2013-01-05 04:13:26 -06:00
for ( auto & it : sel . selected_members )
for ( auto & it2 : it . second )
2013-03-01 01:57:58 -06:00
log ( " %s/%s \n " , id2cstr ( it . first ) , id2cstr ( it2 ) ) ;
2013-01-05 04:13:26 -06:00
return ;
}
design - > selection_stack . back ( ) = work_stack . back ( ) ;
design - > selection_stack . back ( ) . optimize ( design ) ;
}
} SelectPass ;
2015-07-02 04:14:30 -05:00
2013-06-08 07:45:28 -05:00
struct CdPass : public Pass {
CdPass ( ) : Pass ( " cd " , " a shortcut for 'select -module <name>' " ) { }
2018-07-21 01:41:18 -05:00
void help ( ) YS_OVERRIDE
2013-06-08 07:45:28 -05:00
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log ( " \n " ) ;
log ( " cd <modname> \n " ) ;
log ( " \n " ) ;
log ( " This is just a shortcut for 'select -module <modname>'. \n " ) ;
log ( " \n " ) ;
log ( " \n " ) ;
log ( " cd <cellname> \n " ) ;
log ( " \n " ) ;
log ( " When no module with the specified name is found, but there is a cell \n " ) ;
2015-08-14 03:56:05 -05:00
log ( " with the specified name in the current module, then this is equivalent \n " ) ;
2013-06-08 07:45:28 -05:00
log ( " to 'cd <celltype>'. \n " ) ;
log ( " \n " ) ;
log ( " cd .. \n " ) ;
log ( " \n " ) ;
2017-08-18 17:15:12 -05:00
log ( " Remove trailing substrings that start with '.' in current module name until \n " ) ;
log ( " the name of a module in the current design is generated, then switch to that \n " ) ;
log ( " module. Otherwise clear the current selection. \n " ) ;
log ( " \n " ) ;
log ( " cd \n " ) ;
log ( " \n " ) ;
2013-06-08 07:45:28 -05:00
log ( " This is just a shortcut for 'select -clear'. \n " ) ;
log ( " \n " ) ;
}
2018-07-21 01:41:18 -05:00
void execute ( std : : vector < std : : string > args , RTLIL : : Design * design ) YS_OVERRIDE
2013-06-08 07:45:28 -05:00
{
2017-08-18 17:15:12 -05:00
if ( args . size ( ) ! = 1 & & args . size ( ) ! = 2 )
2013-06-08 07:45:28 -05:00
log_cmd_error ( " Invalid number of arguments. \n " ) ;
2017-08-18 17:15:12 -05:00
if ( args . size ( ) = = 1 | | args [ 1 ] = = " / " ) {
design - > selection_stack . back ( ) = RTLIL : : Selection ( true ) ;
design - > selected_active_module = std : : string ( ) ;
return ;
}
if ( args [ 1 ] = = " .. " )
{
string modname = design - > selected_active_module ;
2013-06-08 07:45:28 -05:00
design - > selection_stack . back ( ) = RTLIL : : Selection ( true ) ;
design - > selected_active_module = std : : string ( ) ;
2017-08-18 17:15:12 -05:00
while ( 1 )
{
size_t pos = modname . rfind ( ' . ' ) ;
if ( pos = = string : : npos )
break ;
modname = modname . substr ( 0 , pos ) ;
Module * mod = design - > module ( modname ) ;
if ( mod = = nullptr )
continue ;
design - > selected_active_module = modname ;
design - > selection_stack . back ( ) = RTLIL : : Selection ( ) ;
select_filter_active_mod ( design , design - > selection_stack . back ( ) ) ;
design - > selection_stack . back ( ) . optimize ( design ) ;
return ;
}
2013-06-08 07:45:28 -05:00
return ;
}
std : : string modname = RTLIL : : escape_id ( args [ 1 ] ) ;
2020-03-16 15:32:46 -05:00
if ( design - > module ( modname ) = = nullptr & & ! design - > selected_active_module . empty ( ) ) {
RTLIL : : Module * module = design - > module ( design - > selected_active_module ) ;
if ( module ! = nullptr & & module - > cell ( modname ) ! = nullptr )
2020-03-13 23:40:14 -05:00
modname = module - > cell ( modname ) - > type . str ( ) ;
2013-06-08 07:45:28 -05:00
}
2020-03-16 15:32:46 -05:00
if ( design - > module ( modname ) ! = nullptr ) {
2013-06-08 07:45:28 -05:00
design - > selected_active_module = modname ;
design - > selection_stack . back ( ) = RTLIL : : Selection ( ) ;
select_filter_active_mod ( design , design - > selection_stack . back ( ) ) ;
design - > selection_stack . back ( ) . optimize ( design ) ;
return ;
}
2014-08-02 09:03:18 -05:00
log_cmd_error ( " No such module `%s' found! \n " , RTLIL : : unescape_id ( modname ) . c_str ( ) ) ;
2013-06-08 07:45:28 -05:00
}
} CdPass ;
2013-11-28 14:34:41 -06:00
template < typename T >
2015-01-31 17:13:19 -06:00
static void log_matches ( const char * title , Module * module , T list )
2013-11-28 14:34:41 -06:00
{
2015-01-31 17:13:19 -06:00
std : : vector < IdString > matches ;
2013-11-28 14:34:41 -06:00
for ( auto & it : list )
2015-01-31 17:13:19 -06:00
if ( module - > selected ( it . second ) )
2013-11-28 14:34:41 -06:00
matches . push_back ( it . first ) ;
2015-01-31 17:13:19 -06:00
if ( ! matches . empty ( ) ) {
log ( " \n %d %s: \n " , int ( matches . size ( ) ) , title ) ;
std : : sort ( matches . begin ( ) , matches . end ( ) , RTLIL : : sort_by_id_str ( ) ) ;
for ( auto id : matches )
log ( " %s \n " , RTLIL : : id2cstr ( id ) ) ;
}
2013-11-28 14:34:41 -06:00
}
2015-07-02 04:14:30 -05:00
2013-06-08 07:45:28 -05:00
struct LsPass : public Pass {
LsPass ( ) : Pass ( " ls " , " list modules or objects in modules " ) { }
2018-07-21 01:41:18 -05:00
void help ( ) YS_OVERRIDE
2013-06-08 07:45:28 -05:00
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log ( " \n " ) ;
2015-01-31 17:13:19 -06:00
log ( " ls [selection] \n " ) ;
2013-06-08 07:45:28 -05:00
log ( " \n " ) ;
2015-01-31 17:13:19 -06:00
log ( " When no active module is selected, this prints a list of modules. \n " ) ;
2013-06-08 07:45:28 -05:00
log ( " \n " ) ;
log ( " When an active module is selected, this prints a list of objects in the module. \n " ) ;
log ( " \n " ) ;
}
2018-07-21 01:41:18 -05:00
void execute ( std : : vector < std : : string > args , RTLIL : : Design * design ) YS_OVERRIDE
2013-06-08 07:45:28 -05:00
{
2015-01-31 17:13:19 -06:00
size_t argidx = 1 ;
extra_args ( args , argidx , design ) ;
2013-06-08 07:45:28 -05:00
if ( design - > selected_active_module . empty ( ) )
{
2015-01-31 17:13:19 -06:00
std : : vector < IdString > matches ;
for ( auto mod : design - > selected_modules ( ) )
matches . push_back ( mod - > name ) ;
if ( ! matches . empty ( ) ) {
log ( " \n %d %s: \n " , int ( matches . size ( ) ) , " modules " ) ;
std : : sort ( matches . begin ( ) , matches . end ( ) , RTLIL : : sort_by_id_str ( ) ) ;
for ( auto id : matches )
log ( " %s%s \n " , log_id ( id ) , design - > selected_whole_module ( design - > module ( id ) ) ? " " : " * " ) ;
}
2013-06-08 07:45:28 -05:00
}
else
2015-01-31 17:13:19 -06:00
if ( design - > module ( design - > selected_active_module ) ! = nullptr )
2013-06-08 07:45:28 -05:00
{
2015-01-31 17:13:19 -06:00
RTLIL : : Module * module = design - > module ( design - > selected_active_module ) ;
log_matches ( " wires " , module , module - > wires_ ) ;
log_matches ( " memories " , module , module - > memories ) ;
log_matches ( " cells " , module , module - > cells_ ) ;
log_matches ( " processes " , module , module - > processes ) ;
2013-06-08 07:45:28 -05:00
}
}
} LsPass ;
2015-07-02 04:14:30 -05:00
2014-09-27 09:17:53 -05:00
PRIVATE_NAMESPACE_END