2013-01-05 04:13:26 -06:00
/*
* yosys - - Yosys Open SYnthesis Suite
*
* Copyright ( C ) 2012 Clifford Wolf < clifford @ clifford . at >
2018-10-13 13:34:44 -05:00
* Copyright ( C ) 2018 Ruben Undheim < ruben . undheim @ gmail . com >
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"
2018-06-20 16:45:01 -05:00
# include "frontends/verific/verific.h"
2013-01-05 04:13:26 -06:00
# include <stdlib.h>
# include <stdio.h>
# include <set>
2014-10-16 11:06:54 -05:00
# ifndef _WIN32
# include <unistd.h>
# endif
2013-01-05 04:13:26 -06:00
2014-09-27 09:17:53 -05:00
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
struct generate_port_decl_t {
bool input , output ;
2015-01-04 04:45:39 -06:00
string portname ;
2014-09-27 09:17:53 -05:00
int index ;
} ;
2013-03-24 20:14:33 -05:00
2014-09-27 09:17:53 -05:00
void generate ( RTLIL : : Design * design , const std : : vector < std : : string > & celltypes , const std : : vector < generate_port_decl_t > & portdecls )
2013-03-24 20:14:33 -05:00
{
2014-08-02 06:11:01 -05:00
std : : set < RTLIL : : IdString > found_celltypes ;
2013-03-24 20:14:33 -05:00
2014-07-27 03:18:00 -05:00
for ( auto i1 : design - > modules_ )
2014-07-26 18:51:45 -05:00
for ( auto i2 : i1 . second - > cells_ )
2013-03-24 20:14:33 -05:00
{
RTLIL : : Cell * cell = i2 . second ;
2014-07-29 09:33:56 -05:00
if ( design - > has ( cell - > type ) )
continue ;
if ( cell - > type . substr ( 0 , 1 ) = = " $ " & & cell - > type . substr ( 0 , 3 ) ! = " $__ " )
2013-03-24 20:14:33 -05:00
continue ;
for ( auto & pattern : celltypes )
2014-10-10 11:02:17 -05:00
if ( patmatch ( pattern . c_str ( ) , RTLIL : : unescape_id ( cell - > type ) . c_str ( ) ) )
2013-03-24 20:14:33 -05:00
found_celltypes . insert ( cell - > type ) ;
}
for ( auto & celltype : found_celltypes )
{
2014-08-02 06:11:01 -05:00
std : : set < RTLIL : : IdString > portnames ;
std : : set < RTLIL : : IdString > parameters ;
std : : map < RTLIL : : IdString , int > portwidths ;
2013-03-24 20:14:33 -05:00
log ( " Generate module for cell type %s: \n " , celltype . c_str ( ) ) ;
2014-07-27 03:18:00 -05:00
for ( auto i1 : design - > modules_ )
2014-07-26 18:51:45 -05:00
for ( auto i2 : i1 . second - > cells_ )
2013-03-26 13:11:53 -05:00
if ( i2 . second - > type = = celltype ) {
2014-07-26 07:32:50 -05:00
for ( auto & conn : i2 . second - > connections ( ) ) {
2013-03-24 20:14:33 -05:00
if ( conn . first [ 0 ] ! = ' $ ' )
portnames . insert ( conn . first ) ;
2015-10-25 13:30:49 -05:00
portwidths [ conn . first ] = max ( portwidths [ conn . first ] , conn . second . size ( ) ) ;
2013-03-24 20:14:33 -05:00
}
2013-03-26 13:11:53 -05:00
for ( auto & para : i2 . second - > parameters )
parameters . insert ( para . first ) ;
}
2013-03-24 20:14:33 -05:00
for ( auto & decl : portdecls )
if ( decl . index > 0 )
portnames . insert ( decl . portname ) ;
std : : set < int > indices ;
for ( int i = 0 ; i < int ( portnames . size ( ) ) ; i + + )
indices . insert ( i + 1 ) ;
std : : vector < generate_port_decl_t > ports ( portnames . size ( ) ) ;
for ( auto & decl : portdecls )
if ( decl . index > 0 ) {
2015-10-25 13:30:49 -05:00
portwidths [ decl . portname ] = max ( portwidths [ decl . portname ] , 1 ) ;
portwidths [ decl . portname ] = max ( portwidths [ decl . portname ] , portwidths [ stringf ( " $%d " , decl . index ) ] ) ;
2013-03-24 20:14:33 -05:00
log ( " port %d: %s [%d:0] %s \n " , decl . index , decl . input ? decl . output ? " inout " : " input " : " output " , portwidths [ decl . portname ] - 1 , RTLIL : : id2cstr ( decl . portname ) ) ;
if ( indices . count ( decl . index ) > ports . size ( ) )
log_error ( " Port index (%d) exceeds number of found ports (%d). \n " , decl . index , int ( ports . size ( ) ) ) ;
if ( indices . count ( decl . index ) = = 0 )
log_error ( " Conflict on port index %d. \n " , decl . index ) ;
indices . erase ( decl . index ) ;
portnames . erase ( decl . portname ) ;
ports [ decl . index - 1 ] = decl ;
}
while ( portnames . size ( ) > 0 ) {
2014-08-02 06:11:01 -05:00
RTLIL : : IdString portname = * portnames . begin ( ) ;
2013-03-24 20:14:33 -05:00
for ( auto & decl : portdecls )
2014-10-10 11:02:17 -05:00
if ( decl . index = = 0 & & patmatch ( decl . portname . c_str ( ) , RTLIL : : unescape_id ( portname ) . c_str ( ) ) ) {
2013-03-24 20:14:33 -05:00
generate_port_decl_t d = decl ;
2015-01-04 04:45:39 -06:00
d . portname = portname . str ( ) ;
2013-03-24 20:14:33 -05:00
d . index = * indices . begin ( ) ;
2014-07-28 04:08:55 -05:00
log_assert ( ! indices . empty ( ) ) ;
2013-03-24 20:14:33 -05:00
indices . erase ( d . index ) ;
ports [ d . index - 1 ] = d ;
2015-10-25 13:30:49 -05:00
portwidths [ d . portname ] = max ( portwidths [ d . portname ] , 1 ) ;
2013-03-24 20:14:33 -05:00
log ( " port %d: %s [%d:0] %s \n " , d . index , d . input ? d . output ? " inout " : " input " : " output " , portwidths [ d . portname ] - 1 , RTLIL : : id2cstr ( d . portname ) ) ;
goto found_matching_decl ;
}
log_error ( " Can't match port %s. \n " , RTLIL : : id2cstr ( portname ) ) ;
found_matching_decl : ;
portnames . erase ( portname ) ;
}
2014-07-28 04:08:55 -05:00
log_assert ( indices . empty ( ) ) ;
2013-03-24 20:14:33 -05:00
RTLIL : : Module * mod = new RTLIL : : Module ;
mod - > name = celltype ;
2013-11-22 08:01:12 -06:00
mod - > attributes [ " \\ blackbox " ] = RTLIL : : Const ( 1 ) ;
2014-07-31 07:11:39 -05:00
design - > add ( mod ) ;
2013-03-24 20:14:33 -05:00
for ( auto & decl : ports ) {
2014-07-26 13:12:50 -05:00
RTLIL : : Wire * wire = mod - > addWire ( decl . portname , portwidths . at ( decl . portname ) ) ;
2013-03-24 20:14:33 -05:00
wire - > port_id = decl . index ;
wire - > port_input = decl . input ;
wire - > port_output = decl . output ;
}
2014-08-14 09:13:42 -05:00
mod - > fixup_ports ( ) ;
2013-03-26 13:11:53 -05:00
for ( auto & para : parameters )
log ( " ignoring parameter %s. \n " , RTLIL : : id2cstr ( para ) ) ;
2013-03-24 20:14:33 -05:00
log ( " module %s created. \n " , RTLIL : : id2cstr ( mod - > name ) ) ;
}
}
2019-02-15 13:31:37 -06:00
// Return the "basic" type for an array item.
std : : string basic_cell_type ( const std : : string celltype , int pos [ 3 ] = nullptr ) {
std : : string basicType = celltype ;
if ( celltype . substr ( 0 , 7 ) = = " $array: " ) {
int pos_idx = celltype . find_first_of ( ' : ' ) ;
int pos_num = celltype . find_first_of ( ' : ' , pos_idx + 1 ) ;
int pos_type = celltype . find_first_of ( ' : ' , pos_num + 1 ) ;
basicType = celltype . substr ( pos_type + 1 ) ;
if ( pos ! = nullptr ) {
pos [ 0 ] = pos_idx ;
pos [ 1 ] = pos_num ;
pos [ 2 ] = pos_type ;
}
}
return basicType ;
}
2018-05-12 06:59:13 -05:00
bool expand_module ( RTLIL : : Design * design , RTLIL : : Module * module , bool flag_check , bool flag_simcheck , std : : vector < std : : string > & libdirs )
2013-01-05 04:13:26 -06:00
{
bool did_something = false ;
2014-06-07 04:48:50 -05:00
std : : map < RTLIL : : Cell * , std : : pair < int , int > > array_cells ;
2014-01-14 12:28:20 -06:00
std : : string filename ;
2013-01-05 04:13:26 -06:00
2018-10-20 04:58:25 -05:00
bool has_interface_ports = false ;
// If any of the ports are actually interface ports, we will always need to
// reprocess the module:
if ( ! module - > get_bool_attribute ( " \\ interfaces_replaced_in_module " ) ) {
for ( auto & wire : module - > wires_ ) {
if ( ( wire . second - > port_input | | wire . second - > port_output ) & & wire . second - > get_bool_attribute ( " \\ is_interface " ) )
has_interface_ports = true ;
}
}
2018-10-13 13:34:44 -05:00
// Always keep track of all derived interfaces available in the current module in 'interfaces_in_module':
2018-10-11 16:33:31 -05:00
dict < RTLIL : : IdString , RTLIL : : Module * > interfaces_in_module ;
2014-07-26 18:51:45 -05:00
for ( auto & cell_it : module - > cells_ )
2014-01-14 12:28:20 -06:00
{
2013-01-05 04:13:26 -06:00
RTLIL : : Cell * cell = cell_it . second ;
2018-10-11 16:33:31 -05:00
if ( cell - > get_bool_attribute ( " \\ is_interface " ) ) {
RTLIL : : Module * intf_module = design - > modules_ [ cell - > type ] ;
interfaces_in_module [ cell - > name ] = intf_module ;
}
}
for ( auto & cell_it : module - > cells_ )
{
RTLIL : : Cell * cell = cell_it . second ;
bool has_interfaces_not_found = false ;
std : : vector < RTLIL : : IdString > connections_to_remove ;
std : : vector < RTLIL : : IdString > connections_to_add_name ;
std : : vector < RTLIL : : SigSpec > connections_to_add_signal ;
2014-01-14 12:28:20 -06:00
2014-06-07 04:48:50 -05:00
if ( cell - > type . substr ( 0 , 7 ) = = " $array: " ) {
2019-02-15 13:31:37 -06:00
int pos [ 3 ] ;
basic_cell_type ( cell - > type . str ( ) , pos ) ;
int pos_idx = pos [ 0 ] ;
int pos_num = pos [ 1 ] ;
int pos_type = pos [ 2 ] ;
2014-08-02 06:11:01 -05:00
int idx = atoi ( cell - > type . str ( ) . substr ( pos_idx + 1 , pos_num ) . c_str ( ) ) ;
int num = atoi ( cell - > type . str ( ) . substr ( pos_num + 1 , pos_type ) . c_str ( ) ) ;
2014-06-07 04:48:50 -05:00
array_cells [ cell ] = std : : pair < int , int > ( idx , num ) ;
2014-08-02 06:11:01 -05:00
cell - > type = cell - > type . str ( ) . substr ( pos_type + 1 ) ;
2014-06-07 04:48:50 -05:00
}
2018-10-11 16:33:31 -05:00
dict < RTLIL : : IdString , RTLIL : : Module * > interfaces_to_add_to_submodule ;
2018-10-12 13:58:37 -05:00
dict < RTLIL : : IdString , RTLIL : : IdString > modports_used_in_submodule ;
2014-06-07 04:48:50 -05:00
2014-07-27 03:18:00 -05:00
if ( design - > modules_ . count ( cell - > type ) = = 0 )
2014-01-14 12:28:20 -06:00
{
2014-08-02 06:11:01 -05:00
if ( design - > modules_ . count ( " $abstract " + cell - > type . str ( ) ) )
2014-02-13 06:59:13 -06:00
{
2014-08-02 06:11:01 -05:00
cell - > type = design - > modules_ . at ( " $abstract " + cell - > type . str ( ) ) - > derive ( design , cell - > parameters ) ;
2014-02-13 06:59:13 -06:00
cell - > parameters . clear ( ) ;
did_something = true ;
continue ;
}
2014-01-14 12:28:20 -06:00
if ( cell - > type [ 0 ] = = ' $ ' )
continue ;
for ( auto & dir : libdirs )
{
2018-03-27 07:12:57 -05:00
static const vector < pair < string , string > > extensions_list =
2018-03-27 02:35:20 -05:00
{
{ " .v " , " verilog " } ,
{ " .sv " , " verilog -sv " } ,
{ " .il " , " ilang " }
} ;
2018-03-27 07:12:57 -05:00
for ( auto & ext : extensions_list )
2018-03-27 02:35:20 -05:00
{
filename = dir + " / " + RTLIL : : unescape_id ( cell - > type ) + ext . first ;
if ( check_file_exists ( filename ) ) {
Frontend : : frontend_call ( design , NULL , filename , ext . second ) ;
goto loaded_module ;
}
2014-01-14 12:28:20 -06:00
}
}
2018-05-12 06:59:13 -05:00
if ( ( flag_check | | flag_simcheck ) & & cell - > type [ 0 ] ! = ' $ ' )
2013-01-05 04:13:26 -06:00
log_error ( " Module `%s' referenced in module `%s' in cell `%s' is not part of the design. \n " ,
cell - > type . c_str ( ) , module - > name . c_str ( ) , cell - > name . c_str ( ) ) ;
continue ;
2014-01-14 12:28:20 -06:00
loaded_module :
2014-07-27 03:18:00 -05:00
if ( design - > modules_ . count ( cell - > type ) = = 0 )
2014-01-14 12:28:20 -06:00
log_error ( " File `%s' from libdir does not declare module `%s'. \n " , filename . c_str ( ) , cell - > type . c_str ( ) ) ;
did_something = true ;
2018-10-11 16:33:31 -05:00
} else {
RTLIL : : Module * mod = design - > module ( cell - > type ) ;
// Go over all connections and see if any of them are SV interfaces. If they are, then add the replacements to
2018-10-13 13:34:44 -05:00
// some lists, so that the ports for sub-modules can be replaced further down:
2018-10-11 16:33:31 -05:00
for ( auto & conn : cell - > connections ( ) ) {
if ( mod - > wires_ . count ( conn . first ) ! = 0 & & mod - > wire ( conn . first ) - > get_bool_attribute ( " \\ is_interface " ) ) { // Check if the connection is present as an interface in the sub-module's port list
2018-10-12 13:58:37 -05:00
//const pool<string> &interface_type_pool = mod->wire(conn.first)->get_strpool_attribute("\\interface_type");
2018-10-13 13:34:44 -05:00
//for (auto &d : interface_type_pool) { // TODO: Compare interface type to type in parent module (not crucially important, but good for robustness)
2018-10-12 13:58:37 -05:00
//}
2018-10-13 13:34:44 -05:00
// Find if the sub-module has set a modport for the current interface connection:
2018-10-12 13:58:37 -05:00
const pool < string > & interface_modport_pool = mod - > wire ( conn . first ) - > get_strpool_attribute ( " \\ interface_modport " ) ;
std : : string interface_modport = " " ;
for ( auto & d : interface_modport_pool ) {
interface_modport = " \\ " + d ;
}
2018-10-13 13:34:44 -05:00
if ( conn . second . bits ( ) . size ( ) = = 1 & & conn . second . bits ( ) [ 0 ] . wire - > get_bool_attribute ( " \\ is_interface " ) ) { // Check if the connected wire is a potential interface in the parent module
2018-10-11 16:33:31 -05:00
std : : string interface_name_str = conn . second . bits ( ) [ 0 ] . wire - > name . str ( ) ;
2018-10-13 13:34:44 -05:00
interface_name_str . replace ( 0 , 23 , " " ) ; // Strip the prefix '$dummywireforinterface' from the dummy wire to get the name
2018-10-11 16:33:31 -05:00
interface_name_str = " \\ " + interface_name_str ;
RTLIL : : IdString interface_name = interface_name_str ;
2018-10-13 13:34:44 -05:00
bool not_found_interface = false ;
if ( module - > get_bool_attribute ( " \\ interfaces_replaced_in_module " ) ) { // If 'interfaces' in the cell have not be been handled yet, there is no need to derive the sub-module either
2018-10-20 05:45:51 -05:00
// Check if the interface instance is present in module:
// Interface instances may either have the plain name or the name appended with '_inst_from_top_dummy'.
// Check for both of them here
2018-10-20 04:58:25 -05:00
int nexactmatch = interfaces_in_module . count ( interface_name ) > 0 ;
std : : string interface_name_str2 = interface_name_str + " _inst_from_top_dummy " ;
RTLIL : : IdString interface_name2 = interface_name_str2 ;
int nmatch2 = interfaces_in_module . count ( interface_name2 ) > 0 ;
2018-10-20 05:45:51 -05:00
if ( nexactmatch > 0 | | nmatch2 > 0 ) {
if ( nexactmatch ! = 0 ) // Choose the one with the plain name if it exists
2018-10-20 04:58:25 -05:00
interface_name2 = interface_name ;
RTLIL : : Module * mod_replace_ports = interfaces_in_module . at ( interface_name2 ) ;
2018-10-13 13:34:44 -05:00
for ( auto & mod_wire : mod_replace_ports - > wires_ ) { // Go over all wires in interface, and add replacements to lists.
std : : string signal_name1 = conn . first . str ( ) + " . " + log_id ( mod_wire . first ) ;
std : : string signal_name2 = interface_name . str ( ) + " . " + log_id ( mod_wire . first ) ;
connections_to_add_name . push_back ( RTLIL : : IdString ( signal_name1 ) ) ;
if ( module - > wires_ . count ( signal_name2 ) = = 0 ) {
log_error ( " Could not find signal '%s' in '%s' \n " , signal_name2 . c_str ( ) , log_id ( module - > name ) ) ;
}
else {
RTLIL : : Wire * wire_in_parent = module - > wire ( signal_name2 ) ;
connections_to_add_signal . push_back ( wire_in_parent ) ;
}
2018-10-11 16:33:31 -05:00
}
2018-10-13 13:34:44 -05:00
connections_to_remove . push_back ( conn . first ) ;
2018-10-20 04:58:25 -05:00
interfaces_to_add_to_submodule [ conn . first ] = interfaces_in_module . at ( interface_name2 ) ;
2018-10-13 13:34:44 -05:00
// Add modports to a dict which will be passed to AstModule::derive
if ( interface_modport ! = " " ) {
modports_used_in_submodule [ conn . first ] = interface_modport ;
2018-10-11 16:33:31 -05:00
}
}
2018-10-13 13:34:44 -05:00
else not_found_interface = true ;
2018-10-11 16:33:31 -05:00
}
2018-10-13 13:34:44 -05:00
else not_found_interface = true ;
2018-10-11 16:33:31 -05:00
// If the interface instance has not already been derived in the module, we cannot complete at this stage. Set "has_interfaces_not_found"
// which will delay the expansion of this cell:
2018-10-13 13:34:44 -05:00
if ( not_found_interface ) {
2018-10-11 16:33:31 -05:00
// If we have already gone over all cells in this module, and the interface has still not been found - flag it as an error:
if ( ! ( module - > get_bool_attribute ( " \\ cells_not_processed " ) ) ) {
log_warning ( " Could not find interface instance for `%s' in `%s' \n " , log_id ( interface_name ) , log_id ( module ) ) ;
}
else {
// Only set has_interfaces_not_found if it would be possible to find them, since otherwiser we will end up in an infinite loop:
has_interfaces_not_found = true ;
}
}
}
}
}
//
2018-05-12 06:59:13 -05:00
if ( flag_check | | flag_simcheck )
2014-12-19 11:47:19 -06:00
{
2018-10-11 16:33:31 -05:00
for ( auto & conn : cell - > connections ( ) ) {
2014-12-19 11:47:19 -06:00
if ( conn . first [ 0 ] = = ' $ ' & & ' 0 ' < = conn . first [ 1 ] & & conn . first [ 1 ] < = ' 9 ' ) {
int id = atoi ( conn . first . c_str ( ) + 1 ) ;
2014-12-24 09:26:18 -06:00
if ( id < = 0 | | id > GetSize ( mod - > ports ) )
2014-12-19 11:47:19 -06:00
log_error ( " Module `%s' referenced in module `%s' in cell `%s' has only %d ports, requested port %d. \n " ,
2014-12-24 09:26:18 -06:00
log_id ( cell - > type ) , log_id ( module ) , log_id ( cell ) , GetSize ( mod - > ports ) , id ) ;
2014-12-19 11:47:19 -06:00
} else if ( mod - > wire ( conn . first ) = = nullptr | | mod - > wire ( conn . first ) - > port_id = = 0 )
log_error ( " Module `%s' referenced in module `%s' in cell `%s' does not have a port named '%s'. \n " ,
log_id ( cell - > type ) , log_id ( module ) , log_id ( cell ) , log_id ( conn . first ) ) ;
2018-10-11 16:33:31 -05:00
}
2016-10-22 04:05:49 -05:00
for ( auto & param : cell - > parameters )
2016-11-15 06:35:19 -06:00
if ( mod - > avail_parameters . count ( param . first ) = = 0 & & param . first [ 0 ] ! = ' $ ' & & strchr ( param . first . c_str ( ) , ' . ' ) = = NULL )
2016-10-22 04:05:49 -05:00
log_error ( " Module `%s' referenced in module `%s' in cell `%s' does not have a parameter named '%s'. \n " ,
log_id ( cell - > type ) , log_id ( module ) , log_id ( cell ) , log_id ( param . first ) ) ;
2018-10-11 16:33:31 -05:00
2013-01-05 04:13:26 -06:00
}
2018-10-11 16:33:31 -05:00
}
RTLIL : : Module * mod = design - > modules_ [ cell - > type ] ;
2014-01-14 12:28:20 -06:00
2019-04-18 10:42:12 -05:00
if ( design - > modules_ . at ( cell - > type ) - > get_blackbox_attribute ( ) ) {
2018-05-12 06:59:13 -05:00
if ( flag_simcheck )
2019-04-18 10:42:12 -05:00
log_error ( " Module `%s' referenced in module `%s' in cell `%s' is a blackbox/whitebox module. \n " ,
2018-05-12 06:59:13 -05:00
cell - > type . c_str ( ) , module - > name . c_str ( ) , cell - > name . c_str ( ) ) ;
2013-01-05 04:13:26 -06:00
continue ;
2018-05-12 06:59:13 -05:00
}
2014-01-14 12:28:20 -06:00
2018-10-11 16:33:31 -05:00
// If interface instances not yet found, skip cell for now, and say we did something, so that we will return back here:
if ( has_interfaces_not_found ) {
did_something = true ; // waiting for interfaces to be handled
2013-03-28 03:20:10 -05:00
continue ;
2018-10-11 16:33:31 -05:00
}
2014-01-14 12:28:20 -06:00
2018-10-11 16:33:31 -05:00
// Do the actual replacements of the SV interface port connection with the individual signal connections:
for ( unsigned int i = 0 ; i < connections_to_add_name . size ( ) ; i + + ) {
cell - > connections_ [ connections_to_add_name [ i ] ] = connections_to_add_signal [ i ] ;
}
// Remove the connection for the interface itself:
for ( unsigned int i = 0 ; i < connections_to_remove . size ( ) ; i + + ) {
cell - > connections_ . erase ( connections_to_remove [ i ] ) ;
}
// If there are no overridden parameters AND not interfaces, then we can use the existing module instance as the type
// for the cell:
if ( cell - > parameters . size ( ) = = 0 & & ( interfaces_to_add_to_submodule . size ( ) = = 0 | | ! ( cell - > get_bool_attribute ( " \\ module_not_derived " ) ) ) ) {
// If the cell being processed is an the interface instance itself, go down to "handle_interface_instance:",
// so that the signals of the interface are added to the parent module.
if ( mod - > get_bool_attribute ( " \\ is_interface " ) ) {
goto handle_interface_instance ;
}
continue ;
}
2018-10-12 13:58:37 -05:00
cell - > type = mod - > derive ( design , cell - > parameters , interfaces_to_add_to_submodule , modports_used_in_submodule ) ;
2013-01-05 04:13:26 -06:00
cell - > parameters . clear ( ) ;
2013-04-26 06:28:15 -05:00
did_something = true ;
2018-10-11 16:33:31 -05:00
handle_interface_instance :
// We add all the signals of the interface explicitly to the parent module. This is always needed when we encounter
// an interface instance:
if ( mod - > get_bool_attribute ( " \\ is_interface " ) & & cell - > get_bool_attribute ( " \\ module_not_derived " ) ) {
cell - > set_bool_attribute ( " \\ is_interface " ) ;
RTLIL : : Module * derived_module = design - > modules_ [ cell - > type ] ;
interfaces_in_module [ cell - > name ] = derived_module ;
did_something = true ;
}
2018-10-13 13:34:44 -05:00
// We clear 'module_not_derived' such that we will not rederive the cell again (needed when there are interfaces connected to the cell)
2018-10-11 16:33:31 -05:00
cell - > attributes . erase ( " \\ module_not_derived " ) ;
}
2018-10-13 13:34:44 -05:00
// Clear the attribute 'cells_not_processed' such that it can be known that we
// have been through all cells at least once, and that we can know whether
// to flag an error because of interface instances not found:
2018-10-11 16:33:31 -05:00
module - > attributes . erase ( " \\ cells_not_processed " ) ;
2018-10-13 13:34:44 -05:00
2018-10-20 04:58:25 -05:00
// If any interface instances or interface ports were found in the module, we need to rederive it completely:
if ( ( interfaces_in_module . size ( ) > 0 | | has_interface_ports ) & & ! module - > get_bool_attribute ( " \\ interfaces_replaced_in_module " ) ) {
2018-10-11 16:33:31 -05:00
module - > reprocess_module ( design , interfaces_in_module ) ;
return did_something ;
2013-01-05 04:13:26 -06:00
}
2018-10-11 16:33:31 -05:00
2014-06-07 04:48:50 -05:00
for ( auto & it : array_cells )
{
RTLIL : : Cell * cell = it . first ;
int idx = it . second . first , num = it . second . second ;
2014-07-27 03:18:00 -05:00
if ( design - > modules_ . count ( cell - > type ) = = 0 )
2014-09-06 01:47:06 -05:00
log_error ( " Array cell `%s.%s' of unknown type `%s'. \n " , RTLIL : : id2cstr ( module - > name ) , RTLIL : : id2cstr ( cell - > name ) , RTLIL : : id2cstr ( cell - > type ) ) ;
2014-06-07 04:48:50 -05:00
2014-07-27 03:18:00 -05:00
RTLIL : : Module * mod = design - > modules_ [ cell - > type ] ;
2014-06-07 04:48:50 -05:00
2014-07-26 08:57:57 -05:00
for ( auto & conn : cell - > connections_ ) {
2014-07-22 13:15:14 -05:00
int conn_size = conn . second . size ( ) ;
2014-08-02 06:11:01 -05:00
RTLIL : : IdString portname = conn . first ;
2014-06-07 05:17:06 -05:00
if ( portname . substr ( 0 , 1 ) = = " $ " ) {
int port_id = atoi ( portname . substr ( 1 ) . c_str ( ) ) ;
2014-07-26 18:49:51 -05:00
for ( auto & wire_it : mod - > wires_ )
2014-06-07 05:17:06 -05:00
if ( wire_it . second - > port_id = = port_id ) {
portname = wire_it . first ;
break ;
}
}
2014-07-26 18:49:51 -05:00
if ( mod - > wires_ . count ( portname ) = = 0 )
2014-09-06 01:47:06 -05:00
log_error ( " Array cell `%s.%s' connects to unknown port `%s'. \n " , RTLIL : : id2cstr ( module - > name ) , RTLIL : : id2cstr ( cell - > name ) , RTLIL : : id2cstr ( conn . first ) ) ;
2014-07-26 18:49:51 -05:00
int port_size = mod - > wires_ . at ( portname ) - > width ;
2018-05-31 11:09:31 -05:00
if ( conn_size = = port_size | | conn_size = = 0 )
2014-06-07 04:48:50 -05:00
continue ;
if ( conn_size ! = port_size * num )
log_error ( " Array cell `%s.%s' has invalid port vs. signal size for port `%s'. \n " , RTLIL : : id2cstr ( module - > name ) , RTLIL : : id2cstr ( cell - > name ) , RTLIL : : id2cstr ( conn . first ) ) ;
conn . second = conn . second . extract ( port_size * idx , port_size ) ;
}
}
2013-01-05 04:13:26 -06:00
return did_something ;
}
2016-05-22 09:37:47 -05:00
void hierarchy_worker ( RTLIL : : Design * design , std : : set < RTLIL : : Module * , IdString : : compare_ptr_by_name < Module > > & used , RTLIL : : Module * mod , int indent )
2013-01-05 04:13:26 -06:00
{
if ( used . count ( mod ) > 0 )
return ;
2013-05-26 05:20:51 -05:00
if ( indent = = 0 )
log ( " Top module: %s \n " , mod - > name . c_str ( ) ) ;
2019-04-18 10:42:12 -05:00
else if ( ! mod - > get_blackbox_attribute ( ) )
2013-05-26 05:20:51 -05:00
log ( " Used module: %*s%s \n " , indent , " " , mod - > name . c_str ( ) ) ;
2013-01-05 04:13:26 -06:00
used . insert ( mod ) ;
2014-11-27 05:47:33 -06:00
for ( auto cell : mod - > cells ( ) ) {
std : : string celltype = cell - > type . str ( ) ;
if ( celltype . substr ( 0 , 7 ) = = " $array: " ) {
2019-02-15 13:31:37 -06:00
celltype = basic_cell_type ( celltype ) ;
2014-11-27 05:47:33 -06:00
}
if ( design - > module ( celltype ) )
hierarchy_worker ( design , used , design - > module ( celltype ) , indent + 4 ) ;
2013-01-05 04:13:26 -06:00
}
}
2015-03-04 08:52:34 -06:00
void hierarchy_clean ( RTLIL : : Design * design , RTLIL : : Module * top , bool purge_lib )
2013-01-05 04:13:26 -06:00
{
2016-05-22 09:37:47 -05:00
std : : set < RTLIL : : Module * , IdString : : compare_ptr_by_name < Module > > used ;
2013-05-26 05:20:51 -05:00
hierarchy_worker ( design , used , top , 0 ) ;
2013-01-05 04:13:26 -06:00
std : : vector < RTLIL : : Module * > del_modules ;
2014-07-27 03:18:00 -05:00
for ( auto & it : design - > modules_ )
2013-01-05 04:13:26 -06:00
if ( used . count ( it . second ) = = 0 )
del_modules . push_back ( it . second ) ;
2018-10-20 04:58:25 -05:00
else {
// Now all interface ports must have been exploded, and it is hence
// safe to delete all of the remaining dummy interface ports:
pool < RTLIL : : Wire * > del_wires ;
for ( auto & wire : it . second - > wires_ ) {
if ( ( wire . second - > port_input | | wire . second - > port_output ) & & wire . second - > get_bool_attribute ( " \\ is_interface " ) ) {
del_wires . insert ( wire . second ) ;
}
}
if ( del_wires . size ( ) > 0 ) {
it . second - > remove ( del_wires ) ;
it . second - > fixup_ports ( ) ;
}
}
2013-01-05 04:13:26 -06:00
2015-02-15 05:57:41 -06:00
int del_counter = 0 ;
2013-01-05 04:13:26 -06:00
for ( auto mod : del_modules ) {
2019-04-18 10:42:12 -05:00
if ( ! purge_lib & & mod - > get_blackbox_attribute ( ) )
2014-02-04 09:50:13 -06:00
continue ;
2013-01-05 04:13:26 -06:00
log ( " Removing unused module `%s'. \n " , mod - > name . c_str ( ) ) ;
2014-07-27 03:18:00 -05:00
design - > modules_ . erase ( mod - > name ) ;
2015-02-15 05:57:41 -06:00
del_counter + + ;
2013-01-05 04:13:26 -06:00
delete mod ;
}
2015-02-15 05:57:41 -06:00
log ( " Removed %d unused modules. \n " , del_counter ) ;
2013-01-05 04:13:26 -06:00
}
2014-09-30 12:16:40 -05:00
bool set_keep_assert ( std : : map < RTLIL : : Module * , bool > & cache , RTLIL : : Module * mod )
{
if ( cache . count ( mod ) = = 0 )
for ( auto c : mod - > cells ( ) ) {
RTLIL : : Module * m = mod - > design - > module ( c - > type ) ;
2017-02-25 03:36:39 -06:00
if ( ( m ! = nullptr & & set_keep_assert ( cache , m ) ) | | c - > type . in ( " $assert " , " $assume " , " $live " , " $fair " , " $cover " ) )
2014-09-30 12:16:40 -05:00
return cache [ mod ] = true ;
}
return cache [ mod ] ;
}
2015-03-18 02:33:40 -05:00
int find_top_mod_score ( Design * design , Module * module , dict < Module * , int > & db )
{
if ( db . count ( module ) = = 0 ) {
2016-08-16 02:07:13 -05:00
int score = 0 ;
2015-03-18 02:33:40 -05:00
db [ module ] = 0 ;
2019-02-15 13:31:37 -06:00
for ( auto cell : module - > cells ( ) ) {
std : : string celltype = cell - > type . str ( ) ;
// Is this an array instance
if ( celltype . substr ( 0 , 7 ) = = " $array: " ) {
celltype = basic_cell_type ( celltype ) ;
2019-02-19 16:35:15 -06:00
}
// Is this cell a module instance?
2019-02-22 18:06:10 -06:00
auto instModule = design - > module ( celltype ) ;
// If there is no instance for this, issue a warning.
2019-02-24 13:41:36 -06:00
if ( instModule ! = nullptr ) {
2019-02-22 18:06:10 -06:00
score = max ( score , find_top_mod_score ( design , instModule , db ) + 1 ) ;
2019-02-15 13:31:37 -06:00
}
}
2016-08-16 02:07:13 -05:00
db [ module ] = score ;
2015-03-18 02:33:40 -05:00
}
return db . at ( module ) ;
}
2018-10-11 16:33:31 -05:00
RTLIL : : Module * check_if_top_has_changed ( Design * design , Module * top_mod )
{
if ( top_mod ! = NULL & & top_mod - > get_bool_attribute ( " \\ initial_top " ) )
return top_mod ;
else {
for ( auto mod : design - > modules ( ) ) {
if ( mod - > get_bool_attribute ( " \\ top " ) ) {
return mod ;
}
}
}
return NULL ;
}
2013-01-05 04:13:26 -06:00
struct HierarchyPass : public Pass {
2013-02-28 06:59:49 -06:00
HierarchyPass ( ) : Pass ( " hierarchy " , " check, expand and clean up design hierarchy " ) { }
2018-07-21 01:41:18 -05:00
void help ( ) YS_OVERRIDE
2013-02-28 06:59:49 -06:00
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log ( " \n " ) ;
log ( " hierarchy [-check] [-top <module>] \n " ) ;
2013-03-24 20:14:33 -05:00
log ( " hierarchy -generate <cell-types> <port-decls> \n " ) ;
2013-02-28 06:59:49 -06:00
log ( " \n " ) ;
2014-09-06 01:47:06 -05:00
log ( " In parametric designs, a module might exists in several variations with \n " ) ;
2013-02-28 06:59:49 -06:00
log ( " different parameter values. This pass looks at all modules in the current \n " ) ;
log ( " design an re-runs the language frontends for the parametric modules as \n " ) ;
2019-05-28 09:43:25 -05:00
log ( " needed. It also resolves assignments to wired logic data types (wand/wor), \n " ) ;
log ( " resolves positional module parameters, unroll array instances, and more. \n " ) ;
2013-02-28 06:59:49 -06:00
log ( " \n " ) ;
log ( " -check \n " ) ;
log ( " also check the design hierarchy. this generates an error when \n " ) ;
log ( " an unknown module is used as cell type. \n " ) ;
log ( " \n " ) ;
2018-05-12 06:59:13 -05:00
log ( " -simcheck \n " ) ;
2018-12-07 13:14:07 -06:00
log ( " like -check, but also throw an error if blackbox modules are \n " ) ;
2019-03-13 14:42:18 -05:00
log ( " instantiated, and throw an error if the design has no top module. \n " ) ;
2018-05-12 06:59:13 -05:00
log ( " \n " ) ;
2014-02-04 09:50:13 -06:00
log ( " -purge_lib \n " ) ;
log ( " by default the hierarchy command will not remove library (blackbox) \n " ) ;
2015-03-29 13:22:08 -05:00
log ( " modules. use this option to also remove unused blackbox modules. \n " ) ;
2014-02-04 09:50:13 -06:00
log ( " \n " ) ;
2014-01-14 12:28:20 -06:00
log ( " -libdir <directory> \n " ) ;
log ( " search for files named <module_name>.v in the specified directory \n " ) ;
2014-09-06 01:47:06 -05:00
log ( " for unknown modules and automatically run read_verilog for each \n " ) ;
2014-01-14 12:28:20 -06:00
log ( " unknown module. \n " ) ;
log ( " \n " ) ;
2013-11-03 02:42:51 -06:00
log ( " -keep_positionals \n " ) ;
log ( " per default this pass also converts positional arguments in cells \n " ) ;
2019-03-13 14:42:18 -05:00
log ( " to arguments using port names. This option disables this behavior. \n " ) ;
2013-11-03 02:42:51 -06:00
log ( " \n " ) ;
2017-01-01 15:52:52 -06:00
log ( " -keep_portwidths \n " ) ;
log ( " per default this pass adjusts the port width on cells that are \n " ) ;
2019-03-13 14:42:18 -05:00
log ( " module instances when the width does not match the module port. This \n " ) ;
2017-01-01 15:52:52 -06:00
log ( " option disables this behavior. \n " ) ;
log ( " \n " ) ;
2014-09-30 12:16:40 -05:00
log ( " -nokeep_asserts \n " ) ;
log ( " per default this pass sets the \" keep \" attribute on all modules \n " ) ;
2019-05-03 15:03:43 -05:00
log ( " that directly or indirectly contain one or more formal properties. \n " ) ;
log ( " This option disables this behavior. \n " ) ;
2014-09-30 12:16:40 -05:00
log ( " \n " ) ;
2013-02-28 06:59:49 -06:00
log ( " -top <module> \n " ) ;
2019-03-13 14:42:18 -05:00
log ( " use the specified top module to build the design hierarchy. Modules \n " ) ;
2013-02-28 06:59:49 -06:00
log ( " outside this tree (unused modules) are removed. \n " ) ;
log ( " \n " ) ;
2013-11-23 22:03:43 -06:00
log ( " when the -top option is used, the 'top' attribute will be set on the \n " ) ;
log ( " specified top module. otherwise a module with the 'top' attribute set \n " ) ;
log ( " will implicitly be used as top module, if such a module exists. \n " ) ;
log ( " \n " ) ;
2015-03-18 02:33:40 -05:00
log ( " -auto-top \n " ) ;
log ( " automatically determine the top of the design hierarchy and mark it. \n " ) ;
log ( " \n " ) ;
2019-03-13 14:42:18 -05:00
log ( " -chparam name value \n " ) ;
log ( " elaborate the top module using this parameter value. Modules on which \n " ) ;
log ( " this parameter does not exist may cause a warning message to be output. \n " ) ;
log ( " This option can be specified multiple times to override multiple \n " ) ;
log ( " parameters. String values must be passed in double quotes ( \" ). \n " ) ;
log ( " \n " ) ;
2013-11-22 08:01:12 -06:00
log ( " In -generate mode this pass generates blackbox modules for the given cell \n " ) ;
2013-03-24 20:14:33 -05:00
log ( " types (wildcards supported). For this the design is searched for cells that \n " ) ;
log ( " match the given types and then the given port declarations are used to \n " ) ;
log ( " determine the direction of the ports. The syntax for a port declaration is: \n " ) ;
log ( " \n " ) ;
log ( " {i|o|io}[@<num>]:<portname> \n " ) ;
log ( " \n " ) ;
log ( " Input ports are specified with the 'i' prefix, output ports with the 'o' \n " ) ;
log ( " prefix and inout ports with the 'io' prefix. The optional <num> specifies \n " ) ;
2015-08-14 03:56:05 -05:00
log ( " the position of the port in the parameter list (needed when instantiated \n " ) ;
2013-03-24 20:14:33 -05:00
log ( " using positional arguments). When <num> is not specified, the <portname> can \n " ) ;
log ( " also contain wildcard characters. \n " ) ;
log ( " \n " ) ;
2013-02-28 06:59:49 -06:00
log ( " This pass ignores the current selection and always operates on all modules \n " ) ;
log ( " in the current design. \n " ) ;
log ( " \n " ) ;
}
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
{
2016-04-21 16:28:37 -05:00
log_header ( design , " Executing HIERARCHY pass (managing design hierarchy). \n " ) ;
2013-01-05 04:13:26 -06:00
bool flag_check = false ;
2018-05-12 06:59:13 -05:00
bool flag_simcheck = false ;
2014-02-04 09:50:13 -06:00
bool purge_lib = false ;
2013-01-05 04:13:26 -06:00
RTLIL : : Module * top_mod = NULL ;
2018-06-20 16:45:01 -05:00
std : : string load_top_mod ;
2014-01-14 12:28:20 -06:00
std : : vector < std : : string > libdirs ;
2013-01-05 04:13:26 -06:00
2015-03-18 02:33:40 -05:00
bool auto_top_mode = false ;
2013-03-24 20:14:33 -05:00
bool generate_mode = false ;
2013-11-03 02:42:51 -06:00
bool keep_positionals = false ;
2017-01-01 15:52:52 -06:00
bool keep_portwidths = false ;
2014-09-30 12:16:40 -05:00
bool nokeep_asserts = false ;
2013-03-24 20:14:33 -05:00
std : : vector < std : : string > generate_cells ;
std : : vector < generate_port_decl_t > generate_ports ;
2019-03-13 14:42:18 -05:00
std : : map < std : : string , std : : string > parameters ;
2013-03-24 20:14:33 -05:00
2013-01-05 04:13:26 -06:00
size_t argidx ;
for ( argidx = 1 ; argidx < args . size ( ) ; argidx + + )
{
2018-05-12 06:59:13 -05:00
if ( args [ argidx ] = = " -generate " & & ! flag_check & & ! flag_simcheck & & ! top_mod ) {
2013-03-24 20:14:33 -05:00
generate_mode = true ;
log ( " Entering generate mode. \n " ) ;
while ( + + argidx < args . size ( ) ) {
const char * p = args [ argidx ] . c_str ( ) ;
generate_port_decl_t decl ;
if ( p [ 0 ] = = ' i ' & & p [ 1 ] = = ' o ' )
decl . input = true , decl . output = true , p + = 2 ;
else if ( * p = = ' i ' )
decl . input = true , decl . output = false , p + + ;
else if ( * p = = ' o ' )
decl . input = false , decl . output = true , p + + ;
else
goto is_celltype ;
if ( * p = = ' @ ' ) {
char * endptr ;
decl . index = strtol ( + + p , & endptr , 10 ) ;
if ( decl . index < 1 )
goto is_celltype ;
p = endptr ;
} else
decl . index = 0 ;
if ( * ( p + + ) ! = ' : ' )
goto is_celltype ;
if ( * p = = 0 )
goto is_celltype ;
decl . portname = p ;
log ( " Port declaration: %s " , decl . input ? decl . output ? " inout " : " input " : " output " ) ;
if ( decl . index > = 1 )
log ( " [at position %d] " , decl . index ) ;
log ( " %s \n " , decl . portname . c_str ( ) ) ;
generate_ports . push_back ( decl ) ;
continue ;
is_celltype :
log ( " Celltype: %s \n " , args [ argidx ] . c_str ( ) ) ;
generate_cells . push_back ( RTLIL : : unescape_id ( args [ argidx ] ) ) ;
}
continue ;
}
2013-01-05 04:13:26 -06:00
if ( args [ argidx ] = = " -check " ) {
flag_check = true ;
continue ;
}
2018-05-12 06:59:13 -05:00
if ( args [ argidx ] = = " -simcheck " ) {
flag_simcheck = true ;
continue ;
}
2014-02-04 09:50:13 -06:00
if ( args [ argidx ] = = " -purge_lib " ) {
purge_lib = true ;
continue ;
}
2013-11-03 02:42:51 -06:00
if ( args [ argidx ] = = " -keep_positionals " ) {
keep_positionals = true ;
continue ;
}
2017-01-01 15:52:52 -06:00
if ( args [ argidx ] = = " -keep_portwidths " ) {
keep_portwidths = true ;
continue ;
}
2014-09-30 12:16:40 -05:00
if ( args [ argidx ] = = " -nokeep_asserts " ) {
nokeep_asserts = true ;
continue ;
}
2014-01-14 12:28:20 -06:00
if ( args [ argidx ] = = " -libdir " & & argidx + 1 < args . size ( ) ) {
libdirs . push_back ( args [ + + argidx ] ) ;
continue ;
}
2013-01-05 04:13:26 -06:00
if ( args [ argidx ] = = " -top " ) {
if ( + + argidx > = args . size ( ) )
log_cmd_error ( " Option -top requires an additional argument! \n " ) ;
2019-05-03 15:03:43 -05:00
load_top_mod = args [ argidx ] ;
2013-01-05 04:13:26 -06:00
continue ;
}
2015-03-18 02:33:40 -05:00
if ( args [ argidx ] = = " -auto-top " ) {
auto_top_mode = true ;
continue ;
}
2019-03-13 14:42:18 -05:00
if ( args [ argidx ] = = " -chparam " & & argidx + 2 < args . size ( ) ) {
const std : : string & key = args [ + + argidx ] ;
const std : : string & value = args [ + + argidx ] ;
auto r = parameters . emplace ( key , value ) ;
if ( ! r . second ) {
2019-03-14 10:29:43 -05:00
log_warning ( " -chparam %s already specified: overwriting. \n " , key . c_str ( ) ) ;
2019-03-13 14:42:18 -05:00
r . first - > second = value ;
}
continue ;
}
2013-03-03 03:05:37 -06:00
break ;
2013-01-05 04:13:26 -06:00
}
2013-03-03 03:05:37 -06:00
extra_args ( args , argidx , design , false ) ;
2013-01-05 04:13:26 -06:00
2019-05-03 15:03:43 -05:00
if ( ! load_top_mod . empty ( ) )
{
IdString top_name = RTLIL : : escape_id ( load_top_mod ) ;
IdString abstract_id = " $abstract " + RTLIL : : escape_id ( load_top_mod ) ;
top_mod = design - > module ( top_name ) ;
dict < RTLIL : : IdString , RTLIL : : Const > top_parameters ;
for ( auto & para : parameters ) {
SigSpec sig_value ;
if ( ! RTLIL : : SigSpec : : parse ( sig_value , NULL , para . second ) )
log_cmd_error ( " Can't decode value '%s'! \n " , para . second . c_str ( ) ) ;
top_parameters [ RTLIL : : escape_id ( para . first ) ] = sig_value . as_const ( ) ;
}
if ( top_mod = = nullptr & & design - > module ( abstract_id ) )
top_mod = design - > module ( design - > module ( abstract_id ) - > derive ( design , top_parameters ) ) ;
else if ( top_mod ! = nullptr & & ! top_parameters . empty ( ) )
top_mod = design - > module ( top_mod - > derive ( design , top_parameters ) ) ;
if ( top_mod ! = nullptr & & top_mod - > name ! = top_name ) {
Module * m = top_mod - > clone ( ) ;
m - > name = top_name ;
Module * old_mod = design - > module ( top_name ) ;
if ( old_mod )
design - > remove ( old_mod ) ;
design - > add ( m ) ;
top_mod = m ;
}
}
if ( top_mod = = nullptr & & ! load_top_mod . empty ( ) ) {
2018-06-20 16:45:01 -05:00
# ifdef YOSYS_ENABLE_VERIFIC
if ( verific_import_pending ) {
2019-03-13 14:42:18 -05:00
verific_import ( design , parameters , load_top_mod ) ;
2018-06-20 16:45:01 -05:00
top_mod = design - > module ( RTLIL : : escape_id ( load_top_mod ) ) ;
}
# endif
if ( top_mod = = NULL )
log_cmd_error ( " Module `%s' not found! \n " , load_top_mod . c_str ( ) ) ;
} else {
# ifdef YOSYS_ENABLE_VERIFIC
if ( verific_import_pending )
2019-03-13 14:42:18 -05:00
verific_import ( design , parameters ) ;
2018-06-20 16:45:01 -05:00
# endif
}
2013-03-24 20:14:33 -05:00
if ( generate_mode ) {
generate ( design , generate_cells , generate_ports ) ;
return ;
}
2013-05-26 05:20:51 -05:00
log_push ( ) ;
2015-03-18 02:33:40 -05:00
if ( top_mod = = nullptr )
2014-07-27 03:18:00 -05:00
for ( auto & mod_it : design - > modules_ )
2013-11-23 22:03:43 -06:00
if ( mod_it . second - > get_bool_attribute ( " \\ top " ) )
top_mod = mod_it . second ;
2015-03-18 02:33:40 -05:00
if ( top_mod = = nullptr & & auto_top_mode ) {
2016-04-21 16:28:37 -05:00
log_header ( design , " Finding top of design hierarchy.. \n " ) ;
2015-03-18 02:33:40 -05:00
dict < Module * , int > db ;
2015-04-04 12:00:15 -05:00
for ( Module * mod : design - > selected_modules ( ) ) {
2015-03-18 02:33:40 -05:00
int score = find_top_mod_score ( design , mod , db ) ;
log ( " root of %3d design levels: %-20s \n " , score , log_id ( mod ) ) ;
if ( ! top_mod | | score > db [ top_mod ] )
top_mod = mod ;
}
if ( top_mod ! = nullptr )
log ( " Automatically selected %s as design top module. \n " , log_id ( top_mod ) ) ;
}
2018-05-12 06:59:13 -05:00
if ( flag_simcheck & & top_mod = = nullptr )
log_error ( " Design has no top module. \n " ) ;
2018-10-11 16:33:31 -05:00
if ( top_mod ! = NULL ) {
for ( auto & mod_it : design - > modules_ )
if ( mod_it . second = = top_mod )
mod_it . second - > attributes [ " \\ initial_top " ] = RTLIL : : Const ( 1 ) ;
else
mod_it . second - > attributes . erase ( " \\ initial_top " ) ;
}
2013-01-05 04:13:26 -06:00
bool did_something = true ;
2015-03-04 08:52:34 -06:00
while ( did_something )
{
2013-01-05 04:13:26 -06:00
did_something = false ;
2015-03-04 08:52:34 -06:00
2016-05-22 09:37:47 -05:00
std : : set < RTLIL : : Module * , IdString : : compare_ptr_by_name < Module > > used_modules ;
2015-03-04 08:52:34 -06:00
if ( top_mod ! = NULL ) {
2016-04-21 16:28:37 -05:00
log_header ( design , " Analyzing design hierarchy.. \n " ) ;
2015-03-04 08:52:34 -06:00
hierarchy_worker ( design , used_modules , top_mod , 0 ) ;
} else {
for ( auto mod : design - > modules ( ) )
used_modules . insert ( mod ) ;
}
for ( auto module : used_modules ) {
2018-05-12 06:59:13 -05:00
if ( expand_module ( design , module , flag_check , flag_simcheck , libdirs ) )
2013-01-05 04:13:26 -06:00
did_something = true ;
}
2018-10-11 16:33:31 -05:00
2018-10-13 13:34:44 -05:00
// The top module might have changed if interface instances have been detected in it:
2018-10-11 16:33:31 -05:00
RTLIL : : Module * tmp_top_mod = check_if_top_has_changed ( design , top_mod ) ;
if ( tmp_top_mod ! = NULL ) {
if ( tmp_top_mod ! = top_mod ) {
top_mod = tmp_top_mod ;
did_something = true ;
}
}
2018-10-13 13:34:44 -05:00
// Delete modules marked as 'to_delete':
2018-10-11 16:33:31 -05:00
std : : vector < RTLIL : : Module * > modules_to_delete ;
for ( auto & mod_it : design - > modules_ ) {
if ( mod_it . second - > get_bool_attribute ( " \\ to_delete " ) ) {
modules_to_delete . push_back ( mod_it . second ) ;
}
}
for ( size_t i = 0 ; i < modules_to_delete . size ( ) ; i + + ) {
design - > remove ( modules_to_delete [ i ] ) ;
}
2013-01-05 04:13:26 -06:00
}
2018-10-11 16:33:31 -05:00
2015-03-04 08:52:34 -06:00
if ( top_mod ! = NULL ) {
2016-04-21 16:28:37 -05:00
log_header ( design , " Analyzing design hierarchy.. \n " ) ;
2015-03-04 08:52:34 -06:00
hierarchy_clean ( design , top_mod , purge_lib ) ;
2013-05-26 05:20:51 -05:00
}
2013-11-23 22:03:43 -06:00
if ( top_mod ! = NULL ) {
2018-10-11 16:33:31 -05:00
for ( auto & mod_it : design - > modules_ ) {
2013-11-23 22:03:43 -06:00
if ( mod_it . second = = top_mod )
mod_it . second - > attributes [ " \\ top " ] = RTLIL : : Const ( 1 ) ;
else
mod_it . second - > attributes . erase ( " \\ top " ) ;
2018-10-11 16:33:31 -05:00
mod_it . second - > attributes . erase ( " \\ initial_top " ) ;
}
2013-11-23 22:03:43 -06:00
}
2014-09-30 12:16:40 -05:00
if ( ! nokeep_asserts ) {
std : : map < RTLIL : : Module * , bool > cache ;
for ( auto mod : design - > modules ( ) )
if ( set_keep_assert ( cache , mod ) ) {
2019-05-03 15:03:43 -05:00
log ( " Module %s directly or indirectly contains formal properties -> setting \" keep \" attribute. \n " , log_id ( mod ) ) ;
2014-09-30 12:16:40 -05:00
mod - > set_bool_attribute ( " \\ keep " ) ;
}
}
2013-11-03 02:42:51 -06:00
if ( ! keep_positionals )
{
std : : set < RTLIL : : Module * > pos_mods ;
std : : map < std : : pair < RTLIL : : Module * , int > , RTLIL : : IdString > pos_map ;
std : : vector < std : : pair < RTLIL : : Module * , RTLIL : : Cell * > > pos_work ;
2014-07-27 03:18:00 -05:00
for ( auto & mod_it : design - > modules_ )
2014-07-26 18:51:45 -05:00
for ( auto & cell_it : mod_it . second - > cells_ ) {
2013-11-03 02:42:51 -06:00
RTLIL : : Cell * cell = cell_it . second ;
2014-07-27 03:18:00 -05:00
if ( design - > modules_ . count ( cell - > type ) = = 0 )
2013-11-03 02:42:51 -06:00
continue ;
2014-07-26 07:32:50 -05:00
for ( auto & conn : cell - > connections ( ) )
2013-11-03 02:42:51 -06:00
if ( conn . first [ 0 ] = = ' $ ' & & ' 0 ' < = conn . first [ 1 ] & & conn . first [ 1 ] < = ' 9 ' ) {
2014-07-27 03:18:00 -05:00
pos_mods . insert ( design - > modules_ . at ( cell - > type ) ) ;
2013-11-03 02:42:51 -06:00
pos_work . push_back ( std : : pair < RTLIL : : Module * , RTLIL : : Cell * > ( mod_it . second , cell ) ) ;
break ;
}
}
for ( auto module : pos_mods )
2014-07-26 18:49:51 -05:00
for ( auto & wire_it : module - > wires_ ) {
2013-11-03 02:42:51 -06:00
RTLIL : : Wire * wire = wire_it . second ;
if ( wire - > port_id > 0 )
pos_map [ std : : pair < RTLIL : : Module * , int > ( module , wire - > port_id ) ] = wire - > name ;
}
for ( auto & work : pos_work ) {
RTLIL : : Module * module = work . first ;
RTLIL : : Cell * cell = work . second ;
log ( " Mapping positional arguments of cell %s.%s (%s). \n " ,
RTLIL : : id2cstr ( module - > name ) , RTLIL : : id2cstr ( cell - > name ) , RTLIL : : id2cstr ( cell - > type ) ) ;
2014-12-26 03:53:21 -06:00
dict < RTLIL : : IdString , RTLIL : : SigSpec > new_connections ;
2014-07-26 07:32:50 -05:00
for ( auto & conn : cell - > connections ( ) )
2013-11-03 02:42:51 -06:00
if ( conn . first [ 0 ] = = ' $ ' & & ' 0 ' < = conn . first [ 1 ] & & conn . first [ 1 ] < = ' 9 ' ) {
int id = atoi ( conn . first . c_str ( ) + 1 ) ;
2014-07-27 03:18:00 -05:00
std : : pair < RTLIL : : Module * , int > key ( design - > modules_ . at ( cell - > type ) , id ) ;
2013-11-03 02:42:51 -06:00
if ( pos_map . count ( key ) = = 0 ) {
log ( " Failed to map positional argument %d of cell %s.%s (%s). \n " ,
id , RTLIL : : id2cstr ( module - > name ) , RTLIL : : id2cstr ( cell - > name ) , RTLIL : : id2cstr ( cell - > type ) ) ;
new_connections [ conn . first ] = conn . second ;
} else
new_connections [ pos_map . at ( key ) ] = conn . second ;
} else
new_connections [ conn . first ] = conn . second ;
2014-07-26 08:57:57 -05:00
cell - > connections_ = new_connections ;
2013-11-03 02:42:51 -06:00
}
}
2018-01-04 06:23:29 -06:00
std : : set < Module * > blackbox_derivatives ;
2018-01-07 09:35:22 -06:00
std : : vector < Module * > design_modules = design - > modules ( ) ;
2019-05-27 11:00:22 -05:00
for ( auto module : design_modules )
{
2019-05-28 09:43:25 -05:00
pool < Wire * > wand_wor_index ;
dict < Wire * , SigSpec > wand_map , wor_map ;
vector < SigSig > new_connections ;
for ( auto wire : module - > wires ( ) )
{
if ( wire - > get_bool_attribute ( " \\ wand " ) ) {
wand_map [ wire ] = SigSpec ( ) ;
wand_wor_index . insert ( wire ) ;
}
if ( wire - > get_bool_attribute ( " \\ wor " ) ) {
wor_map [ wire ] = SigSpec ( ) ;
wand_wor_index . insert ( wire ) ;
}
2019-05-27 11:00:22 -05:00
}
for ( auto & conn : module - > connections ( ) )
{
2019-05-28 09:43:25 -05:00
SigSig new_conn ;
int cursor = 0 ;
2019-05-27 11:00:22 -05:00
2019-05-28 09:43:25 -05:00
for ( auto c : conn . first . chunks ( ) )
{
Wire * w = c . wire ;
SigSpec rhs = conn . second . extract ( cursor , GetSize ( c ) ) ;
if ( wand_wor_index . count ( w ) = = 0 ) {
new_conn . first . append ( c ) ;
new_conn . second . append ( rhs ) ;
} else {
if ( wand_map . count ( w ) ) {
SigSpec sig = SigSpec ( State : : S1 , GetSize ( w ) ) ;
sig . replace ( c . offset , rhs ) ;
wand_map . at ( w ) . append ( sig ) ;
} else {
SigSpec sig = SigSpec ( State : : S0 , GetSize ( w ) ) ;
sig . replace ( c . offset , rhs ) ;
wor_map . at ( w ) . append ( sig ) ;
}
2019-05-27 11:00:22 -05:00
}
2019-05-28 09:43:25 -05:00
cursor + = GetSize ( c ) ;
2019-05-27 11:00:22 -05:00
}
2019-05-28 09:43:25 -05:00
new_connections . push_back ( new_conn ) ;
2019-05-27 11:00:22 -05:00
}
module - > new_connections ( new_connections ) ;
2018-01-04 06:23:29 -06:00
2019-05-28 09:43:25 -05:00
for ( auto cell : module - > cells ( ) )
{
if ( ! cell - > known ( ) )
continue ;
2017-01-01 15:52:52 -06:00
2019-05-28 09:43:25 -05:00
for ( auto & conn : cell - > connections ( ) )
{
if ( ! cell - > output ( conn . first ) )
continue ;
2017-01-01 15:52:52 -06:00
2019-05-28 09:43:25 -05:00
SigSpec new_sig ;
bool update_port = false ;
for ( auto c : conn . second . chunks ( ) )
{
Wire * w = c . wire ;
if ( wand_wor_index . count ( w ) = = 0 ) {
new_sig . append ( c ) ;
continue ;
}
Wire * t = module - > addWire ( NEW_ID , GetSize ( c ) ) ;
new_sig . append ( t ) ;
update_port = true ;
if ( wand_map . count ( w ) ) {
SigSpec sig = SigSpec ( State : : S1 , GetSize ( w ) ) ;
sig . replace ( c . offset , t ) ;
wand_map . at ( w ) . append ( sig ) ;
} else {
SigSpec sig = SigSpec ( State : : S0 , GetSize ( w ) ) ;
sig . replace ( c . offset , t ) ;
wor_map . at ( w ) . append ( sig ) ;
}
}
if ( update_port )
cell - > setPort ( conn . first , new_sig ) ;
2018-01-04 06:23:29 -06:00
}
}
2019-05-28 09:43:25 -05:00
for ( auto w : wand_wor_index )
2017-07-22 08:08:30 -05:00
{
2019-05-28 09:43:25 -05:00
bool wand = wand_map . count ( w ) ;
SigSpec sigs = wand ? wand_map . at ( w ) : wor_map . at ( w ) ;
2017-01-01 15:52:52 -06:00
2019-05-28 09:43:25 -05:00
if ( GetSize ( sigs ) = = 0 )
2017-07-22 08:08:30 -05:00
continue ;
2017-07-21 12:32:31 -05:00
2019-05-28 09:43:25 -05:00
if ( GetSize ( w ) = = 1 ) {
if ( wand )
module - > addReduceAnd ( NEW_ID , sigs , w ) ;
else
module - > addReduceOr ( NEW_ID , sigs , w ) ;
2017-07-22 08:08:30 -05:00
continue ;
2019-05-28 09:43:25 -05:00
}
2017-01-01 15:52:52 -06:00
2019-05-28 09:43:25 -05:00
SigSpec s = sigs . extract ( 0 , GetSize ( w ) ) ;
for ( int i = GetSize ( w ) ; i < GetSize ( sigs ) ; i + = GetSize ( w ) ) {
if ( wand )
s = module - > And ( NEW_ID , s , sigs . extract ( i , GetSize ( w ) ) ) ;
2017-01-01 15:52:52 -06:00
else
2019-05-28 09:43:25 -05:00
s = module - > Or ( NEW_ID , s , sigs . extract ( i , GetSize ( w ) ) ) ;
}
module - > connect ( w , s ) ;
}
for ( auto cell : module - > cells ( ) )
{
Module * m = design - > module ( cell - > type ) ;
if ( m = = nullptr )
continue ;
2017-01-01 15:52:52 -06:00
2019-05-28 09:43:25 -05:00
if ( m - > get_blackbox_attribute ( ) & & ! cell - > parameters . empty ( ) & & m - > get_bool_attribute ( " \\ dynports " ) ) {
IdString new_m_name = m - > derive ( design , cell - > parameters , true ) ;
if ( new_m_name . empty ( ) )
continue ;
if ( new_m_name ! = m - > name ) {
m = design - > module ( new_m_name ) ;
blackbox_derivatives . insert ( m ) ;
}
2017-01-01 15:52:52 -06:00
}
2017-07-22 08:08:30 -05:00
2019-05-28 09:43:25 -05:00
for ( auto & conn : cell - > connections ( ) )
{
Wire * w = m - > wire ( conn . first ) ;
if ( w = = nullptr | | w - > port_id = = 0 )
continue ;
if ( GetSize ( conn . second ) = = 0 )
2019-05-27 11:00:22 -05:00
continue ;
2019-05-28 09:43:25 -05:00
SigSpec sig = conn . second ;
if ( ! keep_portwidths & & GetSize ( w ) ! = GetSize ( conn . second ) )
{
if ( GetSize ( w ) < GetSize ( conn . second ) )
{
int n = GetSize ( conn . second ) - GetSize ( w ) ;
if ( ! w - > port_input & & w - > port_output )
module - > connect ( sig . extract ( GetSize ( w ) , n ) , Const ( 0 , n ) ) ;
sig . remove ( GetSize ( w ) , n ) ;
}
else
{
int n = GetSize ( w ) - GetSize ( conn . second ) ;
if ( w - > port_input & & ! w - > port_output )
sig . append ( Const ( 0 , n ) ) ;
else
sig . append ( module - > addWire ( NEW_ID , n ) ) ;
2019-05-27 11:00:22 -05:00
}
2019-05-28 09:43:25 -05:00
if ( ! conn . second . is_fully_const ( ) | | ! w - > port_input | | w - > port_output )
log_warning ( " Resizing cell port %s.%s.%s from %d bits to %d bits. \n " , log_id ( module ) , log_id ( cell ) ,
log_id ( conn . first ) , GetSize ( conn . second ) , GetSize ( sig ) ) ;
cell - > setPort ( conn . first , sig ) ;
2019-05-27 11:00:22 -05:00
}
2019-05-28 09:43:25 -05:00
if ( w - > port_output & & ! w - > port_input & & sig . has_const ( ) )
log_error ( " Output port %s.%s.%s (%s) is connected to constants: %s \n " ,
log_id ( module ) , log_id ( cell ) , log_id ( conn . first ) , log_id ( cell - > type ) , log_signal ( sig ) ) ;
}
2017-01-01 15:52:52 -06:00
}
}
2018-01-04 06:23:29 -06:00
for ( auto module : blackbox_derivatives )
design - > remove ( module ) ;
2013-05-26 05:20:51 -05:00
log_pop ( ) ;
2013-01-05 04:13:26 -06:00
}
} HierarchyPass ;
2015-04-04 12:00:15 -05:00
2014-09-27 09:17:53 -05:00
PRIVATE_NAMESPACE_END