diff --git a/include/mockturtle/io/verilog_reader.hpp b/include/mockturtle/io/verilog_reader.hpp index 9f88abc0e..bce18a8cd 100644 --- a/include/mockturtle/io/verilog_reader.hpp +++ b/include/mockturtle/io/verilog_reader.hpp @@ -77,7 +77,7 @@ template class verilog_reader : public lorina::verilog_reader { public: - explicit verilog_reader( Ntk& ntk ) : _ntk( ntk ) + explicit verilog_reader( Ntk& ntk ) : ntk_( ntk ) { static_assert( is_network_type_v, "Ntk is not a network type" ); static_assert( has_create_pi_v, "Ntk does not implement the create_pi function" ); @@ -89,18 +89,16 @@ class verilog_reader : public lorina::verilog_reader static_assert( has_create_xor_v, "Ntk does not implement the create_xor function" ); static_assert( has_create_maj_v, "Ntk does not implement the create_maj function" ); - signals["0"] = _ntk.get_constant( false ); - signals["1"] = _ntk.get_constant( true ); - signals["1'b0"] = _ntk.get_constant( false ); - signals["1'b1"] = _ntk.get_constant( true ); + signals_["0"] = ntk_.get_constant( false ); + signals_["1"] = ntk_.get_constant( true ); + signals_["1'b0"] = ntk_.get_constant( false ); + signals_["1'b1"] = ntk_.get_constant( true ); } - ~verilog_reader() + void on_module_header( const std::string& module_name, const std::vector& inouts ) const override { - for ( auto const& o : outputs ) - { - _ntk.create_po( signals[o], o ); - } + (void)inouts; + name_ = module_name; } void on_inputs( const std::vector& names, std::string const& size = "" ) const override @@ -110,18 +108,21 @@ class verilog_reader : public lorina::verilog_reader { if ( size.empty() ) { - signals[name] = _ntk.create_pi( name ); + signals_[name] = ntk_.create_pi( name ); + input_names_.emplace_back( name, 1u ); } else { std::vector> word; - for ( auto i = 0u; i < parse_size( size ); ++i ) + const auto length = parse_size( size ); + for ( auto i = 0u; i < length; ++i ) { const auto sname = fmt::format( "{}[{}]", name, i ); - word.push_back( _ntk.create_pi( sname ) ); - signals[sname] = word.back(); + word.push_back( ntk_.create_pi( sname ) ); + signals_[sname] = word.back(); } - registers[name] = word; + registers_[name] = word; + input_names_.emplace_back( name, length ); } } } @@ -133,100 +134,102 @@ class verilog_reader : public lorina::verilog_reader { if ( size.empty() ) { - outputs.emplace_back( name ); + outputs_.emplace_back( name ); + output_names_.emplace_back( name, 1u ); } else { - // TODO store bundles - for ( auto i = 0u; i < parse_size( size ); ++i ) + const auto length = parse_size( size ); + for ( auto i = 0u; i < length; ++i ) { - outputs.emplace_back( fmt::format( "{}[{}]", name, i ) ); + outputs_.emplace_back( fmt::format( "{}[{}]", name, i ) ); } + output_names_.emplace_back( name, length ); } } } void on_assign( const std::string& lhs, const std::pair& rhs ) const override { - if ( signals.find( rhs.first ) == signals.end() ) + if ( signals_.find( rhs.first ) == signals_.end() ) std::cerr << fmt::format( "[w] undefined signal {} assigned 0", rhs.first ) << std::endl; - auto r = signals[rhs.first]; - signals[lhs] = rhs.second ? _ntk.create_not( r ) : r; + auto r = signals_[rhs.first]; + signals_[lhs] = rhs.second ? ntk_.create_not( r ) : r; } void on_and( const std::string& lhs, const std::pair& op1, const std::pair& op2 ) const override { - if ( signals.find( op1.first ) == signals.end() ) + if ( signals_.find( op1.first ) == signals_.end() ) std::cerr << fmt::format( "[w] undefined signal {} assigned 0", op1.first ) << std::endl; - if ( signals.find( op2.first ) == signals.end() ) + if ( signals_.find( op2.first ) == signals_.end() ) std::cerr << fmt::format( "[w] undefined signal {} assigned 0", op2.first ) << std::endl; - auto a = signals[op1.first]; - auto b = signals[op2.first]; - signals[lhs] = _ntk.create_and( op1.second ? _ntk.create_not( a ) : a, op2.second ? _ntk.create_not( b ) : b ); + auto a = signals_[op1.first]; + auto b = signals_[op2.first]; + signals_[lhs] = ntk_.create_and( op1.second ? ntk_.create_not( a ) : a, op2.second ? ntk_.create_not( b ) : b ); } void on_or( const std::string& lhs, const std::pair& op1, const std::pair& op2 ) const override { - if ( signals.find( op1.first ) == signals.end() ) + if ( signals_.find( op1.first ) == signals_.end() ) std::cerr << fmt::format( "[w] undefined signal {} assigned 0", op1.first ) << std::endl; - if ( signals.find( op2.first ) == signals.end() ) + if ( signals_.find( op2.first ) == signals_.end() ) std::cerr << fmt::format( "[w] undefined signal {} assigned 0", op2.first ) << std::endl; - auto a = signals[op1.first]; - auto b = signals[op2.first]; - signals[lhs] = _ntk.create_or( op1.second ? _ntk.create_not( a ) : a, op2.second ? _ntk.create_not( b ) : b ); + auto a = signals_[op1.first]; + auto b = signals_[op2.first]; + signals_[lhs] = ntk_.create_or( op1.second ? ntk_.create_not( a ) : a, op2.second ? ntk_.create_not( b ) : b ); } void on_xor( const std::string& lhs, const std::pair& op1, const std::pair& op2 ) const override { - if ( signals.find( op1.first ) == signals.end() ) + if ( signals_.find( op1.first ) == signals_.end() ) std::cerr << fmt::format( "[w] undefined signal {} assigned 0", op1.first ) << std::endl; - if ( signals.find( op2.first ) == signals.end() ) + if ( signals_.find( op2.first ) == signals_.end() ) std::cerr << fmt::format( "[w] undefined signal {} assigned 0", op2.first ) << std::endl; - auto a = signals[op1.first]; - auto b = signals[op2.first]; - signals[lhs] = _ntk.create_xor( op1.second ? _ntk.create_not( a ) : a, op2.second ? _ntk.create_not( b ) : b ); + auto a = signals_[op1.first]; + auto b = signals_[op2.first]; + signals_[lhs] = ntk_.create_xor( op1.second ? ntk_.create_not( a ) : a, op2.second ? ntk_.create_not( b ) : b ); } void on_xor3( const std::string& lhs, const std::pair& op1, const std::pair& op2, const std::pair& op3 ) const override { - if ( signals.find( op1.first ) == signals.end() ) + if ( signals_.find( op1.first ) == signals_.end() ) std::cerr << fmt::format( "[w] undefined signal {} assigned 0", op1.first ) << std::endl; - if ( signals.find( op2.first ) == signals.end() ) + if ( signals_.find( op2.first ) == signals_.end() ) std::cerr << fmt::format( "[w] undefined signal {} assigned 0", op2.first ) << std::endl; - if ( signals.find( op3.first ) == signals.end() ) + if ( signals_.find( op3.first ) == signals_.end() ) std::cerr << fmt::format( "[w] undefined signal {} assigned 0", op3.first ) << std::endl; - auto a = signals[op1.first]; - auto b = signals[op2.first]; - auto c = signals[op3.first]; + auto a = signals_[op1.first]; + auto b = signals_[op2.first]; + auto c = signals_[op3.first]; if constexpr ( has_create_xor3_v ) { - signals[lhs] = _ntk.create_xor3( op1.second ? _ntk.create_not( a ) : a, op2.second ? _ntk.create_not( b ) : b, op3.second ? _ntk.create_not( c ) : c ); + signals_[lhs] = ntk_.create_xor3( op1.second ? ntk_.create_not( a ) : a, op2.second ? ntk_.create_not( b ) : b, op3.second ? ntk_.create_not( c ) : c ); } else { - signals[lhs] = _ntk.create_xor( _ntk.create_xor( op1.second ? _ntk.create_not( a ) : a, op2.second ? _ntk.create_not( b ) : b ), op3.second ? _ntk.create_not( c ) : c ); + signals_[lhs] = ntk_.create_xor( ntk_.create_xor( op1.second ? ntk_.create_not( a ) : a, op2.second ? ntk_.create_not( b ) : b ), op3.second ? ntk_.create_not( c ) : c ); } } void on_maj3( const std::string& lhs, const std::pair& op1, const std::pair& op2, const std::pair& op3 ) const override { - if ( signals.find( op1.first ) == signals.end() ) + if ( signals_.find( op1.first ) == signals_.end() ) std::cerr << fmt::format( "[w] undefined signal {} assigned 0", op1.first ) << std::endl; - if ( signals.find( op2.first ) == signals.end() ) + if ( signals_.find( op2.first ) == signals_.end() ) std::cerr << fmt::format( "[w] undefined signal {} assigned 0", op2.first ) << std::endl; - if ( signals.find( op3.first ) == signals.end() ) + if ( signals_.find( op3.first ) == signals_.end() ) std::cerr << fmt::format( "[w] undefined signal {} assigned 0", op3.first ) << std::endl; - auto a = signals[op1.first]; - auto b = signals[op2.first]; - auto c = signals[op3.first]; - signals[lhs] = _ntk.create_maj( op1.second ? _ntk.create_not( a ) : a, op2.second ? _ntk.create_not( b ) : b, op3.second ? _ntk.create_not( c ) : c ); + auto a = signals_[op1.first]; + auto b = signals_[op2.first]; + auto c = signals_[op3.first]; + signals_[lhs] = ntk_.create_maj( op1.second ? ntk_.create_not( a ) : a, op2.second ? ntk_.create_not( b ) : b, op3.second ? ntk_.create_not( c ) : c ); } void on_module_instantiation( std::string const& module_name, std::vector const& params, std::string const& inst_name, @@ -255,7 +258,7 @@ class verilog_reader : public lorina::verilog_reader }; const auto register_exists = [&]( std::string const& name ) { - if ( registers.find( name ) == registers.end() ) + if ( registers_.find( name ) == registers_.end() ) { std::cerr << fmt::format( "[e] register {} does not exist\n", name ); return false; @@ -264,7 +267,7 @@ class verilog_reader : public lorina::verilog_reader }; const auto register_has_size = [&]( std::string const& name, uint32_t size ) { - if ( !register_exists( name ) || registers[name].size() != size ) + if ( !register_exists( name ) || registers_[name].size() != size ) { std::cerr << fmt::format( "[e] register {} must have size {}\n", name, size ); return false; @@ -275,9 +278,9 @@ class verilog_reader : public lorina::verilog_reader const auto add_register = [&]( std::string const& name, std::vector> const& fs ) { for ( auto i = 0u; i < fs.size(); ++i ) { - signals[fmt::format( "{}[{}]", name, i) ] = fs[i]; + signals_[fmt::format( "{}[{}]", name, i) ] = fs[i]; } - registers[name] = fs; + registers_[name] = fs; }; if ( module_name == "ripple_carry_adder" ) @@ -288,10 +291,10 @@ class verilog_reader : public lorina::verilog_reader if ( !register_has_size( args[0].second, bitwidth ) ) return; if ( !register_has_size( args[1].second, bitwidth ) ) return; - auto a_copy = registers[args[0].second]; - const auto& b = registers[args[1].second]; - auto carry = _ntk.get_constant( false ); - carry_ripple_adder_inplace( _ntk, a_copy, b, carry ); + auto a_copy = registers_[args[0].second]; + const auto& b = registers_[args[1].second]; + auto carry = ntk_.get_constant( false ); + carry_ripple_adder_inplace( ntk_, a_copy, b, carry ); a_copy.push_back( carry ); add_register( args[2].second, a_copy ); } @@ -309,7 +312,7 @@ class verilog_reader : public lorina::verilog_reader N.resize( bitwidth ); NN.resize( bitwidth ); - add_register( args[2].second, montgomery_multiplication( _ntk, registers[args[0].second], registers[args[1].second], N, NN ) ); + add_register( args[2].second, montgomery_multiplication( ntk_, registers_[args[0].second], registers_[args[1].second], N, NN ) ); } else { @@ -317,6 +320,29 @@ class verilog_reader : public lorina::verilog_reader } } + void on_endmodule() const override + { + for ( auto const& o : outputs_ ) + { + ntk_.create_po( signals_[o], o ); + } + } + + const std::string& name() const + { + return name_; + } + + const std::vector> input_names() + { + return input_names_; + } + + const std::vector> output_names() + { + return output_names_; + } + private: std::vector parse_value( const std::string& value ) const { @@ -356,7 +382,7 @@ class verilog_reader : public lorina::verilog_reader if ( auto const l = size.size(); l > 2 && size[l - 2] == ':' && size[l - 1] == '0' ) { - return parse_small_value( size.substr( 0u, l - 2 ) ) + 1u; + return static_cast( parse_small_value( size.substr( 0u, l - 2 ) ) + 1u ); } assert( false ); @@ -364,11 +390,14 @@ class verilog_reader : public lorina::verilog_reader } private: - Ntk& _ntk; - - mutable std::map> signals; - mutable std::map>> registers; - mutable std::vector outputs; + Ntk& ntk_; + + mutable std::map> signals_; + mutable std::map>> registers_; + mutable std::vector outputs_; + mutable std::string name_; + mutable std::vector> input_names_; + mutable std::vector> output_names_; std::regex hex_string{"(\\d+)'h([0-9a-fA-F]+)"}; }; diff --git a/test/io/verilog_reader.cpp b/test/io/verilog_reader.cpp index 438701e3d..0fbebe895 100644 --- a/test/io/verilog_reader.cpp +++ b/test/io/verilog_reader.cpp @@ -93,7 +93,8 @@ TEST_CASE( "read a VERILOG file to create large Montgomery multiplier", "[verilo "endmodule\n"}; std::istringstream in( file ); - const auto result = lorina::read_verilog( in, verilog_reader( xag ) ); + verilog_reader reader( xag ); + const auto result = lorina::read_verilog( in, reader ); xag = cleanup_dangling( xag ); /* structural checks */ @@ -101,4 +102,9 @@ TEST_CASE( "read a VERILOG file to create large Montgomery multiplier", "[verilo CHECK( xag.num_pis() == 768u ); CHECK( xag.num_pos() == 384u ); CHECK( xag.num_gates() == 909459u ); + + /* name checks */ + CHECK( reader.name() == "top" ); + CHECK( reader.input_names() == std::vector>{{{"a", 384}, {"b", 384}}} ); + CHECK( reader.output_names() == std::vector>{{{"c", 384}}} ); }