2019-02-06 14:19:48 -06:00
/*
* yosys - - Yosys Open SYnthesis Suite
*
2021-06-07 17:39:36 -05:00
* Copyright ( C ) 2012 Claire Xenia Wolf < claire @ yosyshq . com >
2019-06-12 11:40:51 -05:00
* 2019 Eddie Hung < eddie @ fpgeh . com >
2019-02-06 14:19:48 -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 .
*
* 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 .
*
*/
// [[CITE]] The AIGER And-Inverter Graph (AIG) Format Version 20071012
// Armin Biere. The AIGER And-Inverter Graph (AIG) Format Version 20071012. Technical Report 07/1, October 2011, FMV Reports Series, Institute for Formal Models and Verification, Johannes Kepler University, Altenbergerstr. 69, 4040 Linz, Austria.
// http://fmv.jku.at/papers/Biere-FMV-TR-07-1.pdf
2019-06-14 14:40:51 -05:00
// https://stackoverflow.com/a/46137633
# ifdef _MSC_VER
2019-02-19 12:19:53 -06:00
# include <stdlib.h>
2019-06-14 14:40:51 -05:00
# define __builtin_bswap32 _byteswap_ulong
# elif defined(__APPLE__)
# include <libkern/OSByteOrder.h>
# define __builtin_bswap32 OSSwapInt32
2019-02-19 12:19:53 -06:00
# endif
2020-04-07 14:50:31 -05:00
# ifndef __STDC_FORMAT_MACROS
2019-08-09 11:17:35 -05:00
# define __STDC_FORMAT_MACROS
2020-04-07 14:50:31 -05:00
# endif
2019-06-14 14:00:02 -05:00
# include <inttypes.h>
2019-02-17 22:59:53 -06:00
2019-02-06 14:19:48 -06:00
# include "kernel/yosys.h"
# include "kernel/sigtools.h"
2019-06-14 12:27:30 -05:00
# include "kernel/celltypes.h"
2019-02-06 14:19:48 -06:00
# include "aigerparse.h"
YOSYS_NAMESPACE_BEGIN
2019-06-14 14:25:06 -05:00
inline int32_t from_big_endian ( int32_t i32 ) {
# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
return __builtin_bswap32 ( i32 ) ;
# elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
return i32 ;
# else
# error "Unknown endianness"
# endif
}
2019-06-21 19:33:49 -05:00
# define log_debug2(...) ;
//#define log_debug2(...) log_debug(__VA_ARGS__)
2021-02-01 13:23:44 -06:00
static int decimal_digits ( uint32_t n ) {
static uint32_t digit_cutoff [ 9 ] = {
10 , 100 , 1000 , 10000 , 100000 ,
1000000 , 10000000 , 100000000 , 1000000000
} ;
for ( int i = 0 ; i < 9 ; + + i ) {
if ( n < digit_cutoff [ i ] ) return i + 1 ;
}
return 10 ;
2021-01-21 14:20:53 -06:00
}
2019-06-13 18:28:11 -05:00
struct ConstEvalAig
{
RTLIL : : Module * module ;
2019-06-13 19:02:58 -05:00
dict < RTLIL : : SigBit , RTLIL : : State > values_map ;
dict < RTLIL : : SigBit , RTLIL : : Cell * > sig2driver ;
2019-06-13 18:28:11 -05:00
dict < SigBit , pool < RTLIL : : SigBit > > sig2deps ;
ConstEvalAig ( RTLIL : : Module * module ) : module ( module )
{
for ( auto & it : module - > cells_ ) {
2019-06-14 12:27:30 -05:00
if ( ! yosys_celltypes . cell_known ( it . second - > type ) )
2019-06-13 18:28:11 -05:00
continue ;
for ( auto & it2 : it . second - > connections ( ) )
2019-06-14 12:27:30 -05:00
if ( yosys_celltypes . cell_output ( it . second - > type , it2 . first ) ) {
2020-06-18 20:32:48 -05:00
auto r = sig2driver . insert ( std : : make_pair ( it2 . second , it . second ) ) ;
2019-06-13 19:02:58 -05:00
log_assert ( r . second ) ;
}
2019-06-13 18:28:11 -05:00
}
}
void clear ( )
{
values_map . clear ( ) ;
sig2deps . clear ( ) ;
}
2019-06-13 19:02:58 -05:00
void set ( RTLIL : : SigBit sig , RTLIL : : State value )
2019-06-13 18:28:11 -05:00
{
auto it = values_map . find ( sig ) ;
2019-06-13 19:02:58 -05:00
# ifndef NDEBUG
if ( it ! = values_map . end ( ) ) {
RTLIL : : State current_val = it - > second ;
log_assert ( current_val = = value ) ;
}
2019-06-13 18:28:11 -05:00
# endif
2019-06-13 19:02:58 -05:00
if ( it ! = values_map . end ( ) )
it - > second = value ;
else
values_map [ sig ] = value ;
2019-06-13 18:28:11 -05:00
}
void set_incremental ( RTLIL : : SigSpec sig , RTLIL : : Const value )
{
log_assert ( GetSize ( sig ) = = GetSize ( value ) ) ;
for ( int i = 0 ; i < GetSize ( sig ) ; i + + ) {
auto it = values_map . find ( sig [ i ] ) ;
if ( it ! = values_map . end ( ) ) {
2019-06-13 19:02:58 -05:00
RTLIL : : State current_val = it - > second ;
2019-06-13 18:28:11 -05:00
if ( current_val ! = value [ i ] )
for ( auto dep : sig2deps [ sig [ i ] ] )
values_map . erase ( dep ) ;
it - > second = value [ i ] ;
}
else
values_map [ sig [ i ] ] = value [ i ] ;
}
}
void compute_deps ( RTLIL : : SigBit output , const pool < RTLIL : : SigBit > & inputs )
{
sig2deps [ output ] . insert ( output ) ;
2019-06-13 19:02:58 -05:00
RTLIL : : Cell * cell = sig2driver . at ( output ) ;
2020-03-12 14:57:01 -05:00
RTLIL : : SigBit sig_a = cell - > getPort ( ID : : A ) ;
2019-06-21 16:23:39 -05:00
sig2deps [ sig_a ] . reserve ( sig2deps [ sig_a ] . size ( ) + sig2deps [ output ] . size ( ) ) ; // Reserve so that any invalidation
// that may occur does so here, and
// not mid insertion (below)
2019-06-13 19:02:58 -05:00
sig2deps [ sig_a ] . insert ( sig2deps [ output ] . begin ( ) , sig2deps [ output ] . end ( ) ) ;
if ( ! inputs . count ( sig_a ) )
compute_deps ( sig_a , inputs ) ;
2020-04-02 11:51:32 -05:00
if ( cell - > type = = ID ( $ _AND_ ) ) {
2020-03-12 14:57:01 -05:00
RTLIL : : SigSpec sig_b = cell - > getPort ( ID : : B ) ;
2019-06-21 16:23:39 -05:00
sig2deps [ sig_b ] . reserve ( sig2deps [ sig_b ] . size ( ) + sig2deps [ output ] . size ( ) ) ; // Reserve so that any invalidation
// that may occur does so here, and
// not mid insertion (below)
2019-06-13 19:02:58 -05:00
sig2deps [ sig_b ] . insert ( sig2deps [ output ] . begin ( ) , sig2deps [ output ] . end ( ) ) ;
2019-06-21 16:23:39 -05:00
2019-06-13 19:02:58 -05:00
if ( ! inputs . count ( sig_b ) )
compute_deps ( sig_b , inputs ) ;
2019-06-13 18:28:11 -05:00
}
2020-04-02 11:51:32 -05:00
else if ( cell - > type = = ID ( $ _NOT_ ) ) {
2019-06-13 19:02:58 -05:00
}
else log_abort ( ) ;
2019-06-13 18:28:11 -05:00
}
bool eval ( RTLIL : : Cell * cell )
{
2020-03-12 14:57:01 -05:00
RTLIL : : SigBit sig_y = cell - > getPort ( ID : : Y ) ;
2019-06-13 19:02:58 -05:00
if ( values_map . count ( sig_y ) )
2019-06-13 18:28:11 -05:00
return true ;
2020-03-12 14:57:01 -05:00
RTLIL : : SigBit sig_a = cell - > getPort ( ID : : A ) ;
2019-06-13 19:02:58 -05:00
if ( ! eval ( sig_a ) )
2019-06-13 18:28:11 -05:00
return false ;
2019-06-13 19:02:58 -05:00
RTLIL : : State eval_ret = RTLIL : : Sx ;
2020-04-02 11:51:32 -05:00
if ( cell - > type = = ID ( $ _NOT_ ) ) {
2019-08-06 18:23:37 -05:00
if ( sig_a = = State : : S0 ) eval_ret = State : : S1 ;
else if ( sig_a = = State : : S1 ) eval_ret = State : : S0 ;
2019-06-13 18:28:11 -05:00
}
2020-04-02 11:51:32 -05:00
else if ( cell - > type = = ID ( $ _AND_ ) ) {
2019-08-06 18:23:37 -05:00
if ( sig_a = = State : : S0 ) {
eval_ret = State : : S0 ;
2019-06-13 18:28:11 -05:00
goto eval_end ;
}
{
2020-03-12 14:57:01 -05:00
RTLIL : : SigBit sig_b = cell - > getPort ( ID : : B ) ;
2019-06-13 19:02:58 -05:00
if ( ! eval ( sig_b ) )
2019-06-13 18:28:11 -05:00
return false ;
2019-08-06 18:23:37 -05:00
if ( sig_b = = State : : S0 ) {
eval_ret = State : : S0 ;
2019-06-13 18:28:11 -05:00
goto eval_end ;
}
2019-08-06 18:23:37 -05:00
if ( sig_a ! = State : : S1 | | sig_b ! = State : : S1 )
2019-06-13 18:28:11 -05:00
goto eval_end ;
2019-08-06 18:23:37 -05:00
eval_ret = State : : S1 ;
2019-06-13 18:28:11 -05:00
}
}
else log_abort ( ) ;
eval_end :
set ( sig_y , eval_ret ) ;
return true ;
}
2019-06-13 19:02:58 -05:00
bool eval ( RTLIL : : SigBit & sig )
2019-06-13 18:28:11 -05:00
{
auto it = values_map . find ( sig ) ;
2019-06-13 19:02:58 -05:00
if ( it ! = values_map . end ( ) ) {
2019-06-13 18:28:11 -05:00
sig = it - > second ;
return true ;
2019-06-13 19:02:58 -05:00
}
2019-06-13 18:28:11 -05:00
2019-06-13 19:02:58 -05:00
RTLIL : : Cell * cell = sig2driver . at ( sig ) ;
if ( ! eval ( cell ) )
return false ;
2019-06-13 18:28:11 -05:00
it = values_map . find ( sig ) ;
2019-06-13 19:02:58 -05:00
if ( it ! = values_map . end ( ) ) {
2019-06-13 18:28:11 -05:00
sig = it - > second ;
return true ;
2019-06-13 19:02:58 -05:00
}
2019-06-13 18:28:11 -05:00
return false ;
}
} ;
2019-02-12 14:58:10 -06:00
AigerReader : : AigerReader ( RTLIL : : Design * design , std : : istream & f , RTLIL : : IdString module_name , RTLIL : : IdString clk_name , std : : string map_filename , bool wideports )
2020-01-13 23:28:27 -06:00
: design ( design ) , f ( f ) , clk_name ( clk_name ) , map_filename ( map_filename ) , wideports ( wideports ) , aiger_autoidx ( autoidx + + )
2019-02-06 14:19:48 -06:00
{
2019-06-07 17:44:57 -05:00
module = new RTLIL : : Module ;
module - > name = module_name ;
if ( design - > module ( module - > name ) )
log_error ( " Duplicate definition of module %s! \n " , log_id ( module - > name ) ) ;
2019-02-08 14:04:26 -06:00
}
2019-02-08 13:45:16 -06:00
2019-02-08 14:04:26 -06:00
void AigerReader : : parse_aiger ( )
{
2019-06-07 17:44:57 -05:00
std : : string header ;
f > > header ;
if ( header ! = " aag " & & header ! = " aig " )
log_error ( " Unsupported AIGER file! \n " ) ;
// Parse rest of header
if ( ! ( f > > M > > I > > L > > O > > A ) )
log_error ( " Invalid AIGER header \n " ) ;
// Optional values
B = C = J = F = 0 ;
if ( f . peek ( ) ! = ' ' ) goto end_of_header ;
if ( ! ( f > > B ) ) log_error ( " Invalid AIGER header \n " ) ;
if ( f . peek ( ) ! = ' ' ) goto end_of_header ;
if ( ! ( f > > C ) ) log_error ( " Invalid AIGER header \n " ) ;
if ( f . peek ( ) ! = ' ' ) goto end_of_header ;
if ( ! ( f > > J ) ) log_error ( " Invalid AIGER header \n " ) ;
if ( f . peek ( ) ! = ' ' ) goto end_of_header ;
if ( ! ( f > > F ) ) log_error ( " Invalid AIGER header \n " ) ;
2019-05-21 20:20:31 -05:00
end_of_header :
2019-02-08 14:04:26 -06:00
2019-06-07 17:44:57 -05:00
std : : string line ;
std : : getline ( f , line ) ; // Ignore up to start of next line, as standard
// says anything that follows could be used for
// optional sections
log_debug ( " M=%u I=%u L=%u O=%u A=%u B=%u C=%u J=%u F=%u \n " , M , I , L , O , A , B , C , J , F ) ;
line_count = 1 ;
2019-06-12 10:50:39 -05:00
piNum = 0 ;
flopNum = 0 ;
2019-06-07 17:44:57 -05:00
if ( header = = " aag " )
parse_aiger_ascii ( ) ;
else if ( header = = " aig " )
parse_aiger_binary ( ) ;
else
log_abort ( ) ;
2020-01-14 11:01:53 -06:00
RTLIL : : Wire * n0 = module - > wire ( stringf ( " $aiger%d$0 " , aiger_autoidx ) ) ;
2019-06-07 17:44:57 -05:00
if ( n0 )
2019-08-06 18:23:37 -05:00
module - > connect ( n0 , State : : S0 ) ;
2019-06-07 17:44:57 -05:00
// Parse footer (symbol table, comments, etc.)
unsigned l1 ;
std : : string s ;
for ( int c = f . peek ( ) ; c ! = EOF ; c = f . peek ( ) , + + line_count ) {
if ( c = = ' i ' | | c = = ' l ' | | c = = ' o ' | | c = = ' b ' ) {
f . ignore ( 1 ) ;
if ( ! ( f > > l1 > > s ) )
log_error ( " Line %u cannot be interpreted as a symbol entry! \n " , line_count ) ;
if ( ( c = = ' i ' & & l1 > inputs . size ( ) ) | | ( c = = ' l ' & & l1 > latches . size ( ) ) | | ( c = = ' o ' & & l1 > outputs . size ( ) ) )
log_error ( " Line %u has invalid symbol position! \n " , line_count ) ;
2020-01-07 13:22:48 -06:00
RTLIL : : IdString escaped_s = stringf ( " \\ %s " , s . c_str ( ) ) ;
2019-06-07 17:44:57 -05:00
RTLIL : : Wire * wire ;
if ( c = = ' i ' ) wire = inputs [ l1 ] ;
else if ( c = = ' l ' ) wire = latches [ l1 ] ;
2020-01-07 13:22:48 -06:00
else if ( c = = ' o ' ) {
wire = module - > wire ( escaped_s ) ;
if ( wire ) {
// Could have been renamed by a latch
module - > swap_names ( wire , outputs [ l1 ] ) ;
2020-01-07 13:43:28 -06:00
module - > connect ( outputs [ l1 ] , wire ) ;
2020-01-07 13:22:48 -06:00
goto next ;
}
wire = outputs [ l1 ] ;
}
2019-06-07 17:44:57 -05:00
else if ( c = = ' b ' ) wire = bad_properties [ l1 ] ;
else log_abort ( ) ;
2020-01-07 13:22:48 -06:00
module - > rename ( wire , escaped_s ) ;
2019-06-07 17:44:57 -05:00
}
else if ( c = = ' j ' | | c = = ' f ' ) {
// TODO
}
else if ( c = = ' c ' ) {
f . ignore ( 1 ) ;
2019-09-29 08:40:37 -05:00
if ( f . peek ( ) = = ' \r ' )
f . ignore ( 1 ) ;
2019-06-07 17:44:57 -05:00
if ( f . peek ( ) = = ' \n ' )
break ;
// Else constraint (TODO)
}
else
log_error ( " Line %u: cannot interpret first character '%c'! \n " , line_count , c ) ;
2020-01-07 13:22:48 -06:00
next :
2019-06-07 17:44:57 -05:00
std : : getline ( f , line ) ; // Ignore up to start of next line
}
2019-06-12 10:50:39 -05:00
post_process ( ) ;
2019-02-08 13:45:16 -06:00
}
2019-02-12 11:36:22 -06:00
static uint32_t parse_xaiger_literal ( std : : istream & f )
{
2019-06-12 10:50:39 -05:00
uint32_t l ;
f . read ( reinterpret_cast < char * > ( & l ) , sizeof ( l ) ) ;
if ( f . gcount ( ) ! = sizeof ( l ) )
2019-07-31 04:49:48 -05:00
# if defined(_WIN32) && defined(__MINGW32__)
log_error ( " Offset %I64d: unable to read literal! \n " , static_cast < int64_t > ( f . tellg ( ) ) ) ;
# else
2019-06-14 14:00:02 -05:00
log_error ( " Offset % " PRId64 " : unable to read literal! \n " , static_cast < int64_t > ( f . tellg ( ) ) ) ;
2019-07-31 04:49:48 -05:00
# endif
2019-06-14 14:25:06 -05:00
return from_big_endian ( l ) ;
2019-02-12 11:36:22 -06:00
}
2020-01-13 23:28:27 -06:00
RTLIL : : Wire * AigerReader : : createWireIfNotExists ( RTLIL : : Module * module , unsigned literal )
2019-02-13 19:00:00 -06:00
{
2019-06-07 17:44:57 -05:00
const unsigned variable = literal > > 1 ;
const bool invert = literal & 1 ;
2020-01-13 23:28:27 -06:00
RTLIL : : IdString wire_name ( stringf ( " $aiger%d$%d%s " , aiger_autoidx , variable , invert ? " b " : " " ) ) ;
2019-06-07 17:44:57 -05:00
RTLIL : : Wire * wire = module - > wire ( wire_name ) ;
if ( wire ) return wire ;
2019-06-21 19:33:49 -05:00
log_debug2 ( " Creating %s \n " , wire_name . c_str ( ) ) ;
2019-06-07 17:44:57 -05:00
wire = module - > addWire ( wire_name ) ;
2019-06-12 10:50:39 -05:00
wire - > port_input = wire - > port_output = false ;
2019-06-07 17:44:57 -05:00
if ( ! invert ) return wire ;
2020-01-13 23:28:27 -06:00
RTLIL : : IdString wire_inv_name ( stringf ( " $aiger%d$%d " , aiger_autoidx , variable ) ) ;
2019-06-07 17:44:57 -05:00
RTLIL : : Wire * wire_inv = module - > wire ( wire_inv_name ) ;
if ( wire_inv ) {
if ( module - > cell ( wire_inv_name ) ) return wire ;
}
else {
2019-06-21 19:33:49 -05:00
log_debug2 ( " Creating %s \n " , wire_inv_name . c_str ( ) ) ;
2019-06-07 17:44:57 -05:00
wire_inv = module - > addWire ( wire_inv_name ) ;
2019-06-12 10:50:39 -05:00
wire_inv - > port_input = wire_inv - > port_output = false ;
2019-02-21 19:01:07 -06:00
}
2019-06-21 19:33:49 -05:00
log_debug2 ( " Creating %s = ~%s \n " , wire_name . c_str ( ) , wire_inv_name . c_str ( ) ) ;
2020-01-13 23:28:27 -06:00
module - > addNotGate ( stringf ( " $not$aiger%d$%d " , aiger_autoidx , variable ) , wire_inv , wire ) ;
2019-02-21 19:01:07 -06:00
2019-06-07 17:44:57 -05:00
return wire ;
2019-02-21 19:01:07 -06:00
}
2019-12-31 19:06:03 -06:00
void AigerReader : : parse_xaiger ( )
2019-02-11 17:19:17 -06:00
{
2019-06-12 10:50:39 -05:00
std : : string header ;
f > > header ;
if ( header ! = " aag " & & header ! = " aig " )
log_error ( " Unsupported AIGER file! \n " ) ;
// Parse rest of header
if ( ! ( f > > M > > I > > L > > O > > A ) )
log_error ( " Invalid AIGER header \n " ) ;
// Optional values
B = C = J = F = 0 ;
std : : string line ;
std : : getline ( f , line ) ; // Ignore up to start of next line, as standard
// says anything that follows could be used for
// optional sections
log_debug ( " M=%u I=%u L=%u O=%u A=%u \n " , M , I , L , O , A ) ;
line_count = 1 ;
piNum = 0 ;
flopNum = 0 ;
if ( header = = " aag " )
parse_aiger_ascii ( ) ;
else if ( header = = " aig " )
parse_aiger_binary ( ) ;
else
log_abort ( ) ;
2020-01-14 11:01:53 -06:00
RTLIL : : Wire * n0 = module - > wire ( stringf ( " $aiger%d$0 " , aiger_autoidx ) ) ;
2019-06-12 10:50:39 -05:00
if ( n0 )
2019-08-06 18:23:37 -05:00
module - > connect ( n0 , State : : S0 ) ;
2019-06-12 10:50:39 -05:00
2019-12-06 18:35:57 -06:00
int c = f . get ( ) ;
if ( c ! = ' c ' )
log_error ( " Line %u: cannot interpret first character '%c'! \n " , line_count , c ) ;
2019-12-17 17:43:21 -06:00
if ( f . peek ( ) = = ' \n ' )
f . get ( ) ;
2019-12-06 18:35:57 -06:00
2019-06-12 10:50:39 -05:00
// Parse footer (symbol table, comments, etc.)
std : : string s ;
2019-12-06 18:35:57 -06:00
for ( int c = f . get ( ) ; c ! = EOF ; c = f . get ( ) ) {
// XAIGER extensions
if ( c = = ' m ' ) {
2020-06-18 20:32:48 -05:00
uint32_t dataSize = parse_xaiger_literal ( f ) ;
2019-12-06 18:35:57 -06:00
uint32_t lutNum = parse_xaiger_literal ( f ) ;
2020-06-18 20:32:48 -05:00
uint32_t lutSize = parse_xaiger_literal ( f ) ;
2019-12-06 18:35:57 -06:00
log_debug ( " m: dataSize=%u lutNum=%u lutSize=%u \n " , dataSize , lutNum , lutSize ) ;
ConstEvalAig ce ( module ) ;
for ( unsigned i = 0 ; i < lutNum ; + + i ) {
uint32_t rootNodeID = parse_xaiger_literal ( f ) ;
uint32_t cutLeavesM = parse_xaiger_literal ( f ) ;
log_debug2 ( " rootNodeID=%d cutLeavesM=%d \n " , rootNodeID , cutLeavesM ) ;
2020-01-13 23:28:27 -06:00
RTLIL : : Wire * output_sig = module - > wire ( stringf ( " $aiger%d$%d " , aiger_autoidx , rootNodeID ) ) ;
log_assert ( output_sig ) ;
2019-12-06 18:35:57 -06:00
uint32_t nodeID ;
2020-01-28 12:37:16 -06:00
RTLIL : : SigSpec input_sig ;
2019-12-06 18:35:57 -06:00
for ( unsigned j = 0 ; j < cutLeavesM ; + + j ) {
nodeID = parse_xaiger_literal ( f ) ;
log_debug2 ( " \t %u \n " , nodeID ) ;
2020-01-21 13:56:01 -06:00
if ( nodeID = = 0 ) {
2020-01-21 13:16:50 -06:00
log_debug ( " \t LUT '$lut$aiger%d$%d' input %d is constant! \n " , aiger_autoidx , rootNodeID , cutLeavesM ) ;
continue ;
}
2020-01-13 23:28:27 -06:00
RTLIL : : Wire * wire = module - > wire ( stringf ( " $aiger%d$%d " , aiger_autoidx , nodeID ) ) ;
2019-12-06 18:35:57 -06:00
log_assert ( wire ) ;
2020-01-28 12:37:16 -06:00
input_sig . append ( wire ) ;
2019-06-12 10:50:39 -05:00
}
2020-01-21 14:29:07 -06:00
// Reverse input order as fastest input is returned first
2020-01-28 12:37:16 -06:00
input_sig . reverse ( ) ;
2019-12-06 18:35:57 -06:00
// TODO: Compute LUT mask from AIG in less than O(2 ** input_sig.size())
ce . clear ( ) ;
ce . compute_deps ( output_sig , input_sig . to_sigbit_pool ( ) ) ;
2020-01-21 13:16:50 -06:00
RTLIL : : Const lut_mask ( RTLIL : : State : : Sx , 1 < < GetSize ( input_sig ) ) ;
for ( int j = 0 ; j < GetSize ( lut_mask ) ; + + j ) {
2019-12-06 18:35:57 -06:00
int gray = j ^ ( j > > 1 ) ;
2020-01-21 13:16:50 -06:00
ce . set_incremental ( input_sig , RTLIL : : Const { gray , GetSize ( input_sig ) } ) ;
2019-12-06 18:35:57 -06:00
RTLIL : : SigBit o ( output_sig ) ;
2020-06-18 20:32:48 -05:00
bool success = ce . eval ( o ) ;
2019-12-06 18:35:57 -06:00
log_assert ( success ) ;
log_assert ( o . wire = = nullptr ) ;
lut_mask [ gray ] = o . data ;
2019-06-12 10:50:39 -05:00
}
2020-01-13 23:28:27 -06:00
RTLIL : : Cell * output_cell = module - > cell ( stringf ( " $and$aiger%d$%d " , aiger_autoidx , rootNodeID ) ) ;
2019-12-06 18:35:57 -06:00
log_assert ( output_cell ) ;
module - > remove ( output_cell ) ;
2020-01-13 23:28:27 -06:00
module - > addLut ( stringf ( " $lut$aiger%d$%d " , aiger_autoidx , rootNodeID ) , input_sig , output_sig , std : : move ( lut_mask ) ) ;
2019-06-12 10:50:39 -05:00
}
2019-12-06 18:35:57 -06:00
}
else if ( c = = ' r ' ) {
2020-06-18 20:32:48 -05:00
uint32_t dataSize = parse_xaiger_literal ( f ) ;
2019-12-06 18:35:57 -06:00
flopNum = parse_xaiger_literal ( f ) ;
log_debug ( " flopNum = %u \n " , flopNum ) ;
log_assert ( dataSize = = ( flopNum + 1 ) * sizeof ( uint32_t ) ) ;
2020-01-22 16:21:25 -06:00
mergeability . reserve ( flopNum ) ;
for ( unsigned i = 0 ; i < flopNum ; i + + )
mergeability . emplace_back ( parse_xaiger_literal ( f ) ) ;
2019-12-06 18:35:57 -06:00
}
2020-04-09 16:31:14 -05:00
else if ( c = = ' s ' ) {
2020-06-18 20:32:48 -05:00
uint32_t dataSize = parse_xaiger_literal ( f ) ;
2020-04-09 16:31:14 -05:00
flopNum = parse_xaiger_literal ( f ) ;
log_assert ( dataSize = = ( flopNum + 1 ) * sizeof ( uint32_t ) ) ;
initial_state . reserve ( flopNum ) ;
for ( unsigned i = 0 ; i < flopNum ; i + + )
initial_state . emplace_back ( parse_xaiger_literal ( f ) ) ;
}
2019-12-06 18:35:57 -06:00
else if ( c = = ' n ' ) {
parse_xaiger_literal ( f ) ;
f > > s ;
log_debug ( " n: '%s' \n " , s . c_str ( ) ) ;
}
else if ( c = = ' h ' ) {
f . ignore ( sizeof ( uint32_t ) ) ;
2020-06-18 20:32:48 -05:00
uint32_t version = parse_xaiger_literal ( f ) ;
2019-12-06 18:35:57 -06:00
log_assert ( version = = 1 ) ;
2020-06-18 20:32:48 -05:00
uint32_t ciNum = parse_xaiger_literal ( f ) ;
2019-12-06 18:35:57 -06:00
log_debug ( " ciNum = %u \n " , ciNum ) ;
2020-06-18 20:32:48 -05:00
uint32_t coNum = parse_xaiger_literal ( f ) ;
2019-12-06 18:35:57 -06:00
log_debug ( " coNum = %u \n " , coNum ) ;
piNum = parse_xaiger_literal ( f ) ;
log_debug ( " piNum = %u \n " , piNum ) ;
2020-06-18 20:32:48 -05:00
uint32_t poNum = parse_xaiger_literal ( f ) ;
2019-12-06 18:35:57 -06:00
log_debug ( " poNum = %u \n " , poNum ) ;
uint32_t boxNum = parse_xaiger_literal ( f ) ;
log_debug ( " boxNum = %u \n " , boxNum ) ;
for ( unsigned i = 0 ; i < boxNum ; i + + ) {
2020-01-07 11:48:11 -06:00
uint32_t boxInputs = parse_xaiger_literal ( f ) ;
uint32_t boxOutputs = parse_xaiger_literal ( f ) ;
2019-12-06 18:35:57 -06:00
uint32_t boxUniqueId = parse_xaiger_literal ( f ) ;
log_assert ( boxUniqueId > 0 ) ;
uint32_t oldBoxNum = parse_xaiger_literal ( f ) ;
2020-01-07 11:48:11 -06:00
RTLIL : : Cell * cell = module - > addCell ( stringf ( " $box%u " , oldBoxNum ) , stringf ( " $__boxid%u " , boxUniqueId ) ) ;
2020-04-02 11:51:32 -05:00
cell - > setPort ( ID ( i ) , SigSpec ( State : : S0 , boxInputs ) ) ;
cell - > setPort ( ID ( o ) , SigSpec ( State : : S0 , boxOutputs ) ) ;
cell - > attributes [ ID : : abc9_box_seq ] = oldBoxNum ;
2019-12-06 18:35:57 -06:00
boxes . emplace_back ( cell ) ;
2019-06-12 10:50:39 -05:00
}
}
2019-12-06 18:35:57 -06:00
else if ( c = = ' a ' | | c = = ' i ' | | c = = ' o ' | | c = = ' s ' ) {
uint32_t dataSize = parse_xaiger_literal ( f ) ;
f . ignore ( dataSize ) ;
log_debug ( " ignoring '%c' \n " , c ) ;
}
else {
break ;
}
2019-06-12 10:50:39 -05:00
}
post_process ( ) ;
2019-02-11 17:19:17 -06:00
}
2019-02-13 19:00:00 -06:00
void AigerReader : : parse_aiger_ascii ( )
2019-02-06 16:58:47 -06:00
{
2019-06-07 17:44:57 -05:00
std : : string line ;
std : : stringstream ss ;
unsigned l1 , l2 , l3 ;
// Parse inputs
2021-01-21 14:20:53 -06:00
int digits = decimal_digits ( I ) ;
2019-06-07 17:44:57 -05:00
for ( unsigned i = 1 ; i < = I ; + + i , + + line_count ) {
if ( ! ( f > > l1 ) )
log_error ( " Line %u cannot be interpreted as an input! \n " , line_count ) ;
2019-06-21 19:33:49 -05:00
log_debug2 ( " %d is an input \n " , l1 ) ;
2020-01-07 11:48:11 -06:00
log_assert ( ! ( l1 & 1 ) ) ; // Inputs can't be inverted
2020-01-07 13:59:57 -06:00
RTLIL : : Wire * wire = module - > addWire ( stringf ( " $i%0*d " , digits , l1 > > 1 ) ) ;
2019-06-07 17:44:57 -05:00
wire - > port_input = true ;
2020-01-07 13:59:57 -06:00
module - > connect ( createWireIfNotExists ( module , l1 ) , wire ) ;
2019-06-07 17:44:57 -05:00
inputs . push_back ( wire ) ;
}
// Parse latches
RTLIL : : Wire * clk_wire = nullptr ;
2019-06-15 11:07:53 -05:00
if ( L > 0 & & ! clk_name . empty ( ) ) {
2019-06-07 17:44:57 -05:00
clk_wire = module - > wire ( clk_name ) ;
log_assert ( ! clk_wire ) ;
2019-06-21 19:33:49 -05:00
log_debug2 ( " Creating %s \n " , clk_name . c_str ( ) ) ;
2019-06-07 17:44:57 -05:00
clk_wire = module - > addWire ( clk_name ) ;
clk_wire - > port_input = true ;
2019-06-12 10:50:39 -05:00
clk_wire - > port_output = false ;
2019-06-07 17:44:57 -05:00
}
2021-01-21 14:20:53 -06:00
digits = decimal_digits ( L ) ;
2019-06-07 17:44:57 -05:00
for ( unsigned i = 0 ; i < L ; + + i , + + line_count ) {
if ( ! ( f > > l1 > > l2 ) )
log_error ( " Line %u cannot be interpreted as a latch! \n " , line_count ) ;
2019-06-21 19:33:49 -05:00
log_debug2 ( " %d %d is a latch \n " , l1 , l2 ) ;
2019-06-14 14:25:06 -05:00
log_assert ( ! ( l1 & 1 ) ) ;
2020-01-07 15:30:31 -06:00
RTLIL : : Wire * q_wire = module - > addWire ( stringf ( " $l%0*d " , digits , l1 > > 1 ) ) ;
module - > connect ( createWireIfNotExists ( module , l1 ) , q_wire ) ;
2019-06-07 17:44:57 -05:00
RTLIL : : Wire * d_wire = createWireIfNotExists ( module , l2 ) ;
2019-06-15 11:07:53 -05:00
if ( clk_wire )
module - > addDffGate ( NEW_ID , clk_wire , d_wire , q_wire ) ;
else
module - > addFfGate ( NEW_ID , d_wire , q_wire ) ;
2019-06-07 17:44:57 -05:00
// Reset logic is optional in AIGER 1.9
if ( f . peek ( ) = = ' ' ) {
if ( ! ( f > > l3 ) )
log_error ( " Line %u cannot be interpreted as a latch! \n " , line_count ) ;
if ( l3 = = 0 )
2020-04-02 11:51:32 -05:00
q_wire - > attributes [ ID : : init ] = State : : S0 ;
2019-06-07 17:44:57 -05:00
else if ( l3 = = 1 )
2020-04-02 11:51:32 -05:00
q_wire - > attributes [ ID : : init ] = State : : S1 ;
2019-06-07 17:44:57 -05:00
else if ( l3 = = l1 ) {
2020-04-02 11:51:32 -05:00
//q_wire->attributes[ID::init] = RTLIL::Sx;
2019-06-07 17:44:57 -05:00
}
else
log_error ( " Line %u has invalid reset literal for latch! \n " , line_count ) ;
}
else {
// AIGER latches are assumed to be initialized to zero
2020-04-02 11:51:32 -05:00
q_wire - > attributes [ ID : : init ] = State : : S0 ;
2019-06-07 17:44:57 -05:00
}
latches . push_back ( q_wire ) ;
}
// Parse outputs
2021-01-21 14:20:53 -06:00
digits = decimal_digits ( O ) ;
2019-06-07 17:44:57 -05:00
for ( unsigned i = 0 ; i < O ; + + i , + + line_count ) {
if ( ! ( f > > l1 ) )
log_error ( " Line %u cannot be interpreted as an output! \n " , line_count ) ;
2019-06-21 19:33:49 -05:00
log_debug2 ( " %d is an output \n " , l1 ) ;
2020-01-07 11:32:34 -06:00
RTLIL : : Wire * wire = module - > addWire ( stringf ( " $o%0*d " , digits , i ) ) ;
2019-06-07 17:44:57 -05:00
wire - > port_output = true ;
2020-01-07 11:32:34 -06:00
module - > connect ( wire , createWireIfNotExists ( module , l1 ) ) ;
2019-06-07 17:44:57 -05:00
outputs . push_back ( wire ) ;
}
2020-01-07 13:59:57 -06:00
//std::getline(f, line); // Ignore up to start of next line
2019-06-07 17:44:57 -05:00
// Parse bad properties
for ( unsigned i = 0 ; i < B ; + + i , + + line_count ) {
if ( ! ( f > > l1 ) )
log_error ( " Line %u cannot be interpreted as a bad state property! \n " , line_count ) ;
2019-06-21 19:33:49 -05:00
log_debug2 ( " %d is a bad state property \n " , l1 ) ;
2019-06-07 17:44:57 -05:00
RTLIL : : Wire * wire = createWireIfNotExists ( module , l1 ) ;
wire - > port_output = true ;
bad_properties . push_back ( wire ) ;
}
2020-01-07 13:59:57 -06:00
//if (B > 0)
// std::getline(f, line); // Ignore up to start of next line
2019-06-07 17:44:57 -05:00
// TODO: Parse invariant constraints
for ( unsigned i = 0 ; i < C ; + + i , + + line_count )
std : : getline ( f , line ) ; // Ignore up to start of next line
// TODO: Parse justice properties
for ( unsigned i = 0 ; i < J ; + + i , + + line_count )
std : : getline ( f , line ) ; // Ignore up to start of next line
// TODO: Parse fairness constraints
for ( unsigned i = 0 ; i < F ; + + i , + + line_count )
std : : getline ( f , line ) ; // Ignore up to start of next line
// Parse AND
for ( unsigned i = 0 ; i < A ; + + i ) {
if ( ! ( f > > l1 > > l2 > > l3 ) )
log_error ( " Line %u cannot be interpreted as an AND! \n " , line_count ) ;
2019-06-21 19:33:49 -05:00
log_debug2 ( " %d %d %d is an AND \n " , l1 , l2 , l3 ) ;
2019-06-12 10:50:39 -05:00
log_assert ( ! ( l1 & 1 ) ) ;
2019-06-07 17:44:57 -05:00
RTLIL : : Wire * o_wire = createWireIfNotExists ( module , l1 ) ;
RTLIL : : Wire * i1_wire = createWireIfNotExists ( module , l2 ) ;
RTLIL : : Wire * i2_wire = createWireIfNotExists ( module , l3 ) ;
2020-01-13 19:34:37 -06:00
module - > addAndGate ( " $and " + o_wire - > name . str ( ) , i1_wire , i2_wire , o_wire ) ;
2019-06-07 17:44:57 -05:00
}
std : : getline ( f , line ) ; // Ignore up to start of next line
2019-02-08 13:45:16 -06:00
}
2019-02-06 14:19:48 -06:00
2019-02-08 13:45:16 -06:00
static unsigned parse_next_delta_literal ( std : : istream & f , unsigned ref )
{
2019-06-07 17:44:57 -05:00
unsigned x = 0 , i = 0 ;
unsigned char ch ;
while ( ( ch = f . get ( ) ) & 0x80 )
x | = ( ch & 0x7f ) < < ( 7 * i + + ) ;
return ref - ( x | ( ch < < ( 7 * i ) ) ) ;
2019-02-06 14:19:48 -06:00
}
2019-02-13 19:00:00 -06:00
void AigerReader : : parse_aiger_binary ( )
2019-02-08 09:31:04 -06:00
{
2019-06-07 17:44:57 -05:00
unsigned l1 , l2 , l3 ;
std : : string line ;
// Parse inputs
2021-01-21 14:20:53 -06:00
int digits = decimal_digits ( I ) ;
2019-06-07 17:44:57 -05:00
for ( unsigned i = 1 ; i < = I ; + + i ) {
2019-06-21 19:33:49 -05:00
log_debug2 ( " %d is an input \n " , i ) ;
2019-12-17 17:50:01 -06:00
RTLIL : : Wire * wire = module - > addWire ( stringf ( " $i%0*d " , digits , i ) ) ;
2019-06-07 17:44:57 -05:00
wire - > port_input = true ;
2019-12-13 18:21:09 -06:00
module - > connect ( createWireIfNotExists ( module , i < < 1 ) , wire ) ;
2019-06-07 17:44:57 -05:00
inputs . push_back ( wire ) ;
}
// Parse latches
RTLIL : : Wire * clk_wire = nullptr ;
2019-06-15 11:07:53 -05:00
if ( L > 0 & & ! clk_name . empty ( ) ) {
2019-06-07 17:44:57 -05:00
clk_wire = module - > wire ( clk_name ) ;
log_assert ( ! clk_wire ) ;
2019-06-21 19:33:49 -05:00
log_debug2 ( " Creating %s \n " , clk_name . c_str ( ) ) ;
2019-06-07 17:44:57 -05:00
clk_wire = module - > addWire ( clk_name ) ;
clk_wire - > port_input = true ;
2019-06-12 10:50:39 -05:00
clk_wire - > port_output = false ;
2019-06-07 17:44:57 -05:00
}
2021-01-21 14:20:53 -06:00
digits = decimal_digits ( L ) ;
2019-06-07 17:44:57 -05:00
l1 = ( I + 1 ) * 2 ;
for ( unsigned i = 0 ; i < L ; + + i , + + line_count , l1 + = 2 ) {
if ( ! ( f > > l2 ) )
log_error ( " Line %u cannot be interpreted as a latch! \n " , line_count ) ;
log_debug ( " %d %d is a latch \n " , l1 , l2 ) ;
2020-01-07 15:30:31 -06:00
RTLIL : : Wire * q_wire = module - > addWire ( stringf ( " $l%0*d " , digits , l1 > > 1 ) ) ;
module - > connect ( createWireIfNotExists ( module , l1 ) , q_wire ) ;
2019-06-07 17:44:57 -05:00
RTLIL : : Wire * d_wire = createWireIfNotExists ( module , l2 ) ;
2019-06-15 11:07:53 -05:00
if ( clk_wire )
module - > addDff ( NEW_ID , clk_wire , d_wire , q_wire ) ;
else
module - > addFf ( NEW_ID , d_wire , q_wire ) ;
2019-06-07 17:44:57 -05:00
// Reset logic is optional in AIGER 1.9
if ( f . peek ( ) = = ' ' ) {
if ( ! ( f > > l3 ) )
log_error ( " Line %u cannot be interpreted as a latch! \n " , line_count ) ;
if ( l3 = = 0 )
2020-04-02 11:51:32 -05:00
q_wire - > attributes [ ID : : init ] = State : : S0 ;
2019-06-07 17:44:57 -05:00
else if ( l3 = = 1 )
2020-04-02 11:51:32 -05:00
q_wire - > attributes [ ID : : init ] = State : : S1 ;
2019-06-07 17:44:57 -05:00
else if ( l3 = = l1 ) {
2020-04-02 11:51:32 -05:00
//q_wire->attributes[ID::init] = RTLIL::Sx;
2019-06-07 17:44:57 -05:00
}
else
log_error ( " Line %u has invalid reset literal for latch! \n " , line_count ) ;
}
else {
// AIGER latches are assumed to be initialized to zero
2020-04-02 11:51:32 -05:00
q_wire - > attributes [ ID : : init ] = State : : S0 ;
2019-06-07 17:44:57 -05:00
}
latches . push_back ( q_wire ) ;
}
// Parse outputs
2021-01-21 14:20:53 -06:00
digits = decimal_digits ( O ) ;
2019-06-07 17:44:57 -05:00
for ( unsigned i = 0 ; i < O ; + + i , + + line_count ) {
if ( ! ( f > > l1 ) )
log_error ( " Line %u cannot be interpreted as an output! \n " , line_count ) ;
2019-06-21 19:33:49 -05:00
log_debug2 ( " %d is an output \n " , l1 ) ;
2019-12-17 17:50:01 -06:00
RTLIL : : Wire * wire = module - > addWire ( stringf ( " $o%0*d " , digits , i ) ) ;
2019-06-07 17:44:57 -05:00
wire - > port_output = true ;
2019-12-13 18:21:09 -06:00
module - > connect ( wire , createWireIfNotExists ( module , l1 ) ) ;
2019-06-07 17:44:57 -05:00
outputs . push_back ( wire ) ;
}
std : : getline ( f , line ) ; // Ignore up to start of next line
// Parse bad properties
for ( unsigned i = 0 ; i < B ; + + i , + + line_count ) {
if ( ! ( f > > l1 ) )
log_error ( " Line %u cannot be interpreted as a bad state property! \n " , line_count ) ;
2019-06-21 19:33:49 -05:00
log_debug2 ( " %d is a bad state property \n " , l1 ) ;
2019-06-07 17:44:57 -05:00
RTLIL : : Wire * wire = createWireIfNotExists ( module , l1 ) ;
wire - > port_output = true ;
bad_properties . push_back ( wire ) ;
}
if ( B > 0 )
std : : getline ( f , line ) ; // Ignore up to start of next line
// TODO: Parse invariant constraints
for ( unsigned i = 0 ; i < C ; + + i , + + line_count )
std : : getline ( f , line ) ; // Ignore up to start of next line
// TODO: Parse justice properties
for ( unsigned i = 0 ; i < J ; + + i , + + line_count )
std : : getline ( f , line ) ; // Ignore up to start of next line
// TODO: Parse fairness constraints
for ( unsigned i = 0 ; i < F ; + + i , + + line_count )
std : : getline ( f , line ) ; // Ignore up to start of next line
// Parse AND
l1 = ( I + L + 1 ) < < 1 ;
for ( unsigned i = 0 ; i < A ; + + i , + + line_count , l1 + = 2 ) {
l2 = parse_next_delta_literal ( f , l1 ) ;
l3 = parse_next_delta_literal ( f , l2 ) ;
2019-06-21 19:33:49 -05:00
log_debug2 ( " %d %d %d is an AND \n " , l1 , l2 , l3 ) ;
2019-06-12 10:50:39 -05:00
log_assert ( ! ( l1 & 1 ) ) ;
2019-06-07 17:44:57 -05:00
RTLIL : : Wire * o_wire = createWireIfNotExists ( module , l1 ) ;
RTLIL : : Wire * i1_wire = createWireIfNotExists ( module , l2 ) ;
RTLIL : : Wire * i2_wire = createWireIfNotExists ( module , l3 ) ;
2020-01-13 19:34:37 -06:00
module - > addAndGate ( " $and " + o_wire - > name . str ( ) , i1_wire , i2_wire , o_wire ) ;
2019-06-12 10:50:39 -05:00
}
}
2019-06-07 17:44:57 -05:00
2019-06-12 10:50:39 -05:00
void AigerReader : : post_process ( )
{
2020-01-07 11:48:11 -06:00
unsigned ci_count = 0 , co_count = 0 ;
2019-06-12 10:50:39 -05:00
for ( auto cell : boxes ) {
2020-04-02 11:51:32 -05:00
for ( auto & bit : cell - > connections_ . at ( ID ( i ) ) ) {
2020-01-07 11:48:11 -06:00
log_assert ( bit = = State : : S0 ) ;
log_assert ( co_count < outputs . size ( ) ) ;
bit = outputs [ co_count + + ] ;
log_assert ( bit . wire & & GetSize ( bit . wire ) = = 1 ) ;
log_assert ( bit . wire - > port_output ) ;
bit . wire - > port_output = false ;
2019-12-31 18:50:22 -06:00
}
2020-04-02 11:51:32 -05:00
for ( auto & bit : cell - > connections_ . at ( ID ( o ) ) ) {
2020-01-07 11:48:11 -06:00
log_assert ( bit = = State : : S0 ) ;
log_assert ( ( piNum + ci_count ) < inputs . size ( ) ) ;
bit = inputs [ piNum + ci_count + + ] ;
log_assert ( bit . wire & & GetSize ( bit . wire ) = = 1 ) ;
log_assert ( bit . wire - > port_input ) ;
bit . wire - > port_input = false ;
2019-08-20 20:17:14 -05:00
}
2020-01-07 11:48:11 -06:00
}
2019-08-20 20:17:14 -05:00
2020-01-07 11:48:11 -06:00
for ( uint32_t i = 0 ; i < flopNum ; i + + ) {
RTLIL : : Wire * d = outputs [ outputs . size ( ) - flopNum + i ] ;
log_assert ( d ) ;
log_assert ( d - > port_output ) ;
d - > port_output = false ;
RTLIL : : Wire * q = inputs [ piNum - flopNum + i ] ;
log_assert ( q ) ;
log_assert ( q - > port_input ) ;
q - > port_input = false ;
2020-04-16 16:01:54 -05:00
Cell * ff = module - > addFfGate ( NEW_ID , d , q ) ;
ff - > attributes [ ID : : abc9_mergeability ] = mergeability [ i ] ;
2020-04-13 15:11:25 -05:00
q - > attributes [ ID : : init ] = initial_state [ i ] ;
2019-06-12 10:50:39 -05:00
}
2020-05-02 11:55:34 -05:00
dict < RTLIL : : IdString , std : : pair < int , int > > wideports_cache ;
2019-06-12 10:50:39 -05:00
if ( ! map_filename . empty ( ) ) {
std : : ifstream mf ( map_filename ) ;
std : : string type , symbol ;
int variable , index ;
while ( mf > > type > > variable > > index > > symbol ) {
RTLIL : : IdString escaped_s = RTLIL : : escape_id ( symbol ) ;
if ( type = = " input " ) {
log_assert ( static_cast < unsigned > ( variable ) < inputs . size ( ) ) ;
RTLIL : : Wire * wire = inputs [ variable ] ;
log_assert ( wire ) ;
log_assert ( wire - > port_input ) ;
2019-06-15 11:07:53 -05:00
log_debug ( " Renaming input %s " , log_id ( wire ) ) ;
2019-06-12 10:50:39 -05:00
2020-05-02 11:55:34 -05:00
RTLIL : : Wire * existing = nullptr ;
2019-06-12 10:50:39 -05:00
if ( index = = 0 ) {
// Cope with the fact that a CI might be identical
// to a PI (necessary due to ABC); in those cases
// simply connect the latter to the former
2020-05-02 11:55:34 -05:00
existing = module - > wire ( escaped_s ) ;
2019-06-12 10:50:39 -05:00
if ( ! existing )
module - > rename ( wire , escaped_s ) ;
else {
wire - > port_input = false ;
module - > connect ( wire , existing ) ;
}
2020-01-09 12:02:19 -06:00
log_debug ( " -> %s \n " , log_id ( escaped_s ) ) ;
2019-06-12 10:50:39 -05:00
}
2020-05-02 11:55:34 -05:00
else {
RTLIL : : IdString indexed_name = stringf ( " %s[%d] " , escaped_s . c_str ( ) , index ) ;
existing = module - > wire ( indexed_name ) ;
if ( ! existing )
2019-06-12 10:50:39 -05:00
module - > rename ( wire , indexed_name ) ;
else {
module - > connect ( wire , existing ) ;
wire - > port_input = false ;
}
2020-01-09 12:02:19 -06:00
log_debug ( " -> %s \n " , log_id ( indexed_name ) ) ;
2019-06-12 10:50:39 -05:00
}
2020-05-02 11:55:34 -05:00
if ( wideports & & ! existing ) {
auto r = wideports_cache . insert ( escaped_s ) ;
if ( r . second ) {
r . first - > second . first = index ;
r . first - > second . second = index ;
}
else {
r . first - > second . first = std : : min ( r . first - > second . first , index ) ;
r . first - > second . second = std : : max ( r . first - > second . second , index ) ;
}
}
2019-06-12 10:50:39 -05:00
}
else if ( type = = " output " ) {
log_assert ( static_cast < unsigned > ( variable + co_count ) < outputs . size ( ) ) ;
RTLIL : : Wire * wire = outputs [ variable + co_count ] ;
log_assert ( wire ) ;
log_assert ( wire - > port_output ) ;
2019-07-11 12:07:14 -05:00
log_debug ( " Renaming output %s " , log_id ( wire ) ) ;
2019-06-12 10:50:39 -05:00
2020-05-02 11:55:34 -05:00
RTLIL : : Wire * existing ;
2019-06-12 10:50:39 -05:00
if ( index = = 0 ) {
// Cope with the fact that a CO might be identical
// to a PO (necessary due to ABC); in those cases
// simply connect the latter to the former
2020-05-02 11:55:34 -05:00
existing = module - > wire ( escaped_s ) ;
if ( ! existing )
2019-12-17 17:44:35 -06:00
module - > rename ( wire , escaped_s ) ;
2019-06-12 10:50:39 -05:00
else {
wire - > port_output = false ;
2020-01-13 23:45:27 -06:00
existing - > port_output = true ;
2019-06-12 10:50:39 -05:00
module - > connect ( wire , existing ) ;
2019-06-15 20:13:44 -05:00
wire = existing ;
2019-06-12 10:50:39 -05:00
}
2020-01-09 12:02:19 -06:00
log_debug ( " -> %s \n " , log_id ( escaped_s ) ) ;
2019-06-12 10:50:39 -05:00
}
2020-05-02 11:55:34 -05:00
else {
RTLIL : : IdString indexed_name = stringf ( " %s[%d] " , escaped_s . c_str ( ) , index ) ;
existing = module - > wire ( indexed_name ) ;
if ( ! existing )
2019-12-17 17:44:35 -06:00
module - > rename ( wire , indexed_name ) ;
2019-06-12 10:50:39 -05:00
else {
wire - > port_output = false ;
2020-01-13 23:45:27 -06:00
existing - > port_output = true ;
module - > connect ( wire , existing ) ;
2019-06-12 10:50:39 -05:00
}
2020-01-09 12:02:19 -06:00
log_debug ( " -> %s \n " , log_id ( indexed_name ) ) ;
2019-06-12 10:50:39 -05:00
}
2020-05-02 11:55:34 -05:00
if ( wideports & & ! existing ) {
auto r = wideports_cache . insert ( escaped_s ) ;
if ( r . second ) {
r . first - > second . first = index ;
r . first - > second . second = index ;
}
else {
r . first - > second . first = std : : min ( r . first - > second . first , index ) ;
r . first - > second . second = std : : max ( r . first - > second . second , index ) ;
}
}
2019-06-12 10:50:39 -05:00
}
else if ( type = = " box " ) {
2019-12-31 19:06:03 -06:00
RTLIL : : Cell * cell = module - > cell ( stringf ( " $box%d " , variable ) ) ;
2020-05-25 09:17:54 -05:00
if ( ! cell )
log_debug ( " Box %d (%s) no longer exists. \n " , variable , log_id ( escaped_s ) ) ;
else
2019-06-12 10:50:39 -05:00
module - > rename ( cell , escaped_s ) ;
}
else
log_error ( " Symbol type '%s' not recognised. \n " , type . c_str ( ) ) ;
}
}
for ( auto & wp : wideports_cache ) {
auto name = wp . first ;
2020-05-02 11:55:34 -05:00
int min = wp . second . first ;
int max = wp . second . second ;
2020-05-25 09:17:54 -05:00
if ( min = = 0 & & max = = 0 )
continue ;
2019-06-12 10:50:39 -05:00
RTLIL : : Wire * wire = module - > wire ( name ) ;
if ( wire )
module - > rename ( wire , RTLIL : : escape_id ( stringf ( " %s[%d] " , name . c_str ( ) , 0 ) ) ) ;
// Do not make ports with a mix of input/output into
// wide ports
bool port_input = false , port_output = false ;
2020-05-02 11:55:34 -05:00
for ( int i = min ; i < = max ; i + + ) {
2019-06-12 10:50:39 -05:00
RTLIL : : IdString other_name = name . str ( ) + stringf ( " [%d] " , i ) ;
RTLIL : : Wire * other_wire = module - > wire ( other_name ) ;
if ( other_wire ) {
port_input = port_input | | other_wire - > port_input ;
port_output = port_output | | other_wire - > port_output ;
}
}
2020-05-02 11:55:34 -05:00
wire = module - > addWire ( name , max - min + 1 ) ;
wire - > start_offset = min ;
2019-06-12 10:50:39 -05:00
wire - > port_input = port_input ;
wire - > port_output = port_output ;
2020-05-02 11:55:34 -05:00
for ( int i = min ; i < = max ; i + + ) {
RTLIL : : IdString other_name = stringf ( " %s[%d] " , name . c_str ( ) , i ) ;
2019-06-12 10:50:39 -05:00
RTLIL : : Wire * other_wire = module - > wire ( other_name ) ;
if ( other_wire ) {
other_wire - > port_input = false ;
other_wire - > port_output = false ;
2019-12-06 18:21:06 -06:00
if ( wire - > port_input )
2020-05-02 11:55:34 -05:00
module - > connect ( other_wire , SigSpec ( wire , i - min ) ) ;
2019-12-06 18:21:06 -06:00
else
2020-05-02 11:55:34 -05:00
module - > connect ( SigSpec ( wire , i - min ) , other_wire ) ;
2019-06-12 10:50:39 -05:00
}
}
}
module - > fixup_ports ( ) ;
2019-08-02 00:21:30 -05:00
// Insert into a new (temporary) design so that "clean" will only
// operate (and run checks on) this one module
RTLIL : : Design * mapped_design = new RTLIL : : Design ;
mapped_design - > add ( module ) ;
Pass : : call ( mapped_design , " clean " ) ;
mapped_design - > modules_ . erase ( module - > name ) ;
delete mapped_design ;
2019-06-12 10:50:39 -05:00
2019-08-02 00:21:30 -05:00
design - > add ( module ) ;
2019-06-12 10:50:39 -05:00
for ( auto cell : module - > cells ( ) . to_vector ( ) ) {
2020-04-02 11:51:32 -05:00
if ( cell - > type ! = ID ( $ lut ) ) continue ;
2020-03-12 14:57:01 -05:00
auto y_port = cell - > getPort ( ID : : Y ) . as_bit ( ) ;
2019-06-12 10:50:39 -05:00
if ( y_port . wire - > width = = 1 )
2020-01-15 16:31:32 -06:00
module - > rename ( cell , stringf ( " $lut%s " , y_port . wire - > name . c_str ( ) ) ) ;
2019-06-12 10:50:39 -05:00
else
2020-01-15 16:31:32 -06:00
module - > rename ( cell , stringf ( " $lut%s[%d] " , y_port . wire - > name . c_str ( ) , y_port . offset ) ) ;
2019-06-07 17:44:57 -05:00
}
2019-02-08 09:31:04 -06:00
}
2019-02-06 14:19:48 -06:00
struct AigerFrontend : public Frontend {
2019-06-07 17:44:57 -05:00
AigerFrontend ( ) : Frontend ( " aiger " , " read AIGER file " ) { }
2020-06-18 18:34:52 -05:00
void help ( ) override
2019-06-07 17:44:57 -05:00
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log ( " \n " ) ;
log ( " read_aiger [options] [filename] \n " ) ;
log ( " \n " ) ;
log ( " Load module from an AIGER file into the current design. \n " ) ;
log ( " \n " ) ;
log ( " -module_name <module_name> \n " ) ;
2020-01-06 14:43:29 -06:00
log ( " name of module to be created (default: <filename>) \n " ) ;
2019-06-07 17:44:57 -05:00
log ( " \n " ) ;
log ( " -clk_name <wire_name> \n " ) ;
2020-01-06 14:43:29 -06:00
log ( " if specified, AIGER latches to be transformed into $_DFF_P_ cells \n " ) ;
log ( " clocked by wire of this name. otherwise, $_FF_ cells will be used \n " ) ;
2019-06-07 17:44:57 -05:00
log ( " \n " ) ;
2019-06-12 10:50:39 -05:00
log ( " -map <filename> \n " ) ;
log ( " read file with port and latch symbols \n " ) ;
log ( " \n " ) ;
log ( " -wideports \n " ) ;
2020-01-06 14:43:29 -06:00
log ( " merge ports that match the pattern 'name[int]' into a single \n " ) ;
log ( " multi-bit port 'name' \n " ) ;
log ( " \n " ) ;
log ( " -xaiger \n " ) ;
log ( " read XAIGER extensions \n " ) ;
2019-06-12 10:50:39 -05:00
log ( " \n " ) ;
2019-06-07 17:44:57 -05:00
}
2020-06-18 18:34:52 -05:00
void execute ( std : : istream * & f , std : : string filename , std : : vector < std : : string > args , RTLIL : : Design * design ) override
2019-06-07 17:44:57 -05:00
{
log_header ( design , " Executing AIGER frontend. \n " ) ;
2020-01-07 13:21:45 -06:00
RTLIL : : IdString clk_name ;
2019-06-07 17:44:57 -05:00
RTLIL : : IdString module_name ;
2019-06-12 10:50:39 -05:00
std : : string map_filename ;
2020-01-06 14:43:29 -06:00
bool wideports = false , xaiger = false ;
2019-02-08 14:40:43 -06:00
2019-02-06 14:19:48 -06:00
size_t argidx ;
for ( argidx = 1 ; argidx < args . size ( ) ; argidx + + ) {
std : : string arg = args [ argidx ] ;
2019-02-08 14:40:43 -06:00
if ( arg = = " -module_name " & & argidx + 1 < args . size ( ) ) {
module_name = RTLIL : : escape_id ( args [ + + argidx ] ) ;
continue ;
}
2019-02-08 14:49:55 -06:00
if ( arg = = " -clk_name " & & argidx + 1 < args . size ( ) ) {
clk_name = RTLIL : : escape_id ( args [ + + argidx ] ) ;
continue ;
}
2019-06-12 10:50:39 -05:00
if ( map_filename . empty ( ) & & arg = = " -map " & & argidx + 1 < args . size ( ) ) {
map_filename = args [ + + argidx ] ;
continue ;
}
if ( arg = = " -wideports " ) {
wideports = true ;
continue ;
}
2020-01-06 14:43:29 -06:00
if ( arg = = " -xaiger " ) {
xaiger = true ;
continue ;
}
2019-02-06 14:19:48 -06:00
break ;
}
2019-09-29 06:22:11 -05:00
extra_args ( f , filename , args , argidx , true ) ;
2019-02-06 14:19:48 -06:00
2019-06-07 17:44:57 -05:00
if ( module_name . empty ( ) ) {
2019-02-08 14:40:43 -06:00
# ifdef _WIN32
2019-06-12 10:50:39 -05:00
char fname [ _MAX_FNAME ] ;
2019-07-14 10:57:08 -05:00
_splitpath ( filename . c_str ( ) , NULL /* drive */ , NULL /* dir */ , fname , NULL /* ext */ ) ;
2019-09-29 08:40:37 -05:00
char * bn = strdup ( fname ) ;
module_name = RTLIL : : escape_id ( bn ) ;
free ( bn ) ;
2019-02-08 14:40:43 -06:00
# else
2019-06-07 17:44:57 -05:00
char * bn = strdup ( filename . c_str ( ) ) ;
module_name = RTLIL : : escape_id ( bn ) ;
free ( bn ) ;
2019-02-08 14:40:43 -06:00
# endif
2019-06-07 17:44:57 -05:00
}
2019-02-08 14:40:43 -06:00
2019-06-12 10:50:39 -05:00
AigerReader reader ( design , * f , module_name , clk_name , map_filename , wideports ) ;
2020-01-06 14:43:29 -06:00
if ( xaiger )
reader . parse_xaiger ( ) ;
else
reader . parse_aiger ( ) ;
2019-06-07 17:44:57 -05:00
}
2019-02-06 14:19:48 -06:00
} AigerFrontend ;
YOSYS_NAMESPACE_END