Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create top-level wrapper for AIG partitioning #10

Merged
merged 3 commits into from
Oct 18, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
212 changes: 201 additions & 11 deletions lib/mockturtle/include/mockturtle/io/write_verilog.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@

#include <ez/direct_iterator.hpp>
#include <fmt/format.h>
#include <oracle/partitioning/partition_manager.hpp>
#include <oracle/partitioning/partition_view.hpp>

#include "../traits.hpp"
#include "../utils/node_map.hpp"
Expand Down Expand Up @@ -95,7 +97,7 @@ namespace mockturtle
* \param os Output stream
*/
template<class Ntk>
void write_verilog( Ntk const& ntk, std::ostream& os )
void write_verilog( Ntk const& ntk, std::ostream& os, std::string const& modulename )
{
static_assert( is_network_type_v<Ntk>, "Ntk is not a network type" );
static_assert( has_num_latches_v<Ntk>, "Ntk does not implement the has_latches method" );
Expand Down Expand Up @@ -134,17 +136,23 @@ namespace mockturtle
ez::make_direct_iterator(ntk.num_latches()),
[](auto i) { return fmt::format("lo{}", i+1); }, ", "s);
std::string clk = "clock";
os << fmt::format( "module top({}, {}, {});\n", clk, xs, ys )
<< fmt::format( " input {};\n", clk )
<< fmt::format( " input {};\n", xs )
<< fmt::format( " output {};\n", ys )
os << fmt::format( "module {}({}, {}, {});\n", modulename, clk, xs, ys );

if (ntk.num_pis()>0)
{
os << fmt::format( " input {};\n", clk )
<< fmt::format( " input {};\n", xs );
}

os << fmt::format( " output {};\n", ys )
<< fmt::format( " reg {};\n", rs );
}

else {
os << fmt::format( "module top({}, {});\n", xs, ys )
<< fmt::format( " input {};\n", xs )
<< fmt::format( " output {};\n", ys );
os << fmt::format( "module {}({}, {});\n", modulename, xs, ys );
if (ntk.num_pis()>0)
os << fmt::format( " input {};\n", xs );
os << fmt::format( " output {};\n", ys );
}

node_map<std::string, Ntk> node_names( ntk );
Expand Down Expand Up @@ -314,11 +322,193 @@ namespace mockturtle
* \param filename Filename
*/
template<class Ntk>
void write_verilog( Ntk const& ntk, std::string const& filename )
void write_verilog( Ntk const& ntk, std::string const& filename, std::string const& modulename = "top" )
{
std::ofstream os( filename.c_str(), std::ofstream::out );
write_verilog( ntk, os );
write_verilog( ntk, os, modulename );
os.close();
}

template<class Ntk>
void write_toplevel_verilog( Ntk const& ntk, oracle::partition_manager<Ntk> const& pm, std::string const& filename, node_map<std::string, Ntk> node_names, node_map<std::string, Ntk> input_names, std::string const& modulename = "toplevel")
{
static_assert( is_network_type_v<Ntk>, "Ntk is not a network type" );
static_assert( has_num_latches_v<Ntk>, "Ntk does not implement the has_latches method" );
static_assert( has_num_pis_v<Ntk>, "Ntk does not implement the num_pis method" );
static_assert( has_num_pos_v<Ntk>, "Ntk does not implement the num_pos method" );
static_assert( has_foreach_pi_v<Ntk>, "Ntk does not implement the foreach_pi method" );
static_assert( has_foreach_node_v<Ntk>, "Ntk does not implement the foreach_node method" );
static_assert( has_foreach_fanin_v<Ntk>, "Ntk does not implement the foreach_fanin method" );
static_assert( has_foreach_ri_v<Ntk>, "Ntk does not implement the foreach_ri method" );
static_assert( has_foreach_ro_v<Ntk>, "Ntk does not implement the foreach_ro method" );
static_assert( has_get_node_v<Ntk>, "Ntk does not implement the get_node method" );
static_assert( has_get_constant_v<Ntk>, "Ntk does not implement the get_constant method" );
static_assert( has_is_constant_v<Ntk>, "Ntk does not implement the is_constant method" );
static_assert( has_is_pi_v<Ntk>, "Ntk does not implement the is_pi method" );
static_assert( has_is_and_v<Ntk>, "Ntk does not implement the is_and method" );
static_assert( has_is_or_v<Ntk>, "Ntk does not implement the is_or method" );
static_assert( has_is_xor_v<Ntk>, "Ntk does not implement the is_xor method" );
static_assert( has_is_xor3_v<Ntk>, "Ntk does not implement the is_xor3 method" );
static_assert( has_is_maj_v<Ntk>, "Ntk does not implement the is_maj method" );
static_assert( has_node_to_index_v<Ntk>, "Ntk does not implement the node_to_index method" );

int num_parts = pm.get_part_num();
std::ofstream os( filename.c_str(), std::ofstream::out );
auto digitsIn = std::to_string(ntk.num_pis()).length();
auto digitsOut = std::to_string(ntk.num_pos()).length();

const auto xs = map_and_join( ez::make_direct_iterator<decltype( ntk.num_pis() )>( 0 ),
ez::make_direct_iterator( ntk.num_pis() - ntk.num_latches() ),
[&digitsIn]( auto i ) { return fmt::format( "pi{0:0{1}}", i, digitsIn); }, ", "s );
const auto ys = map_and_join( ez::make_direct_iterator<decltype( ntk.num_pis() )>( 0 ),
ez::make_direct_iterator( ntk.num_pos() - ntk.num_latches() ),
[&digitsOut]( auto i ) { return fmt::format( "po{0:0{1}}", i, digitsOut); }, ", "s );


os << fmt::format( "module {}({}, {});\n", modulename, xs, ys)
<< fmt::format( " input {};\n", xs )
<< fmt::format( " output {};\n", ys );

// Initialize
ntk.foreach_node( [&](auto n) {
input_names[n] = "1'b0";
node_names[n] = "1'b0";
});

std::vector<int> vector_output;

ntk.foreach_pi( [&]( auto const& n, auto i ) {
input_names[n] = fmt::format( "pi{0:0{1}}", i, digitsIn);
} );

// Store names of inputs and outpus
auto node_list = pm.get_part_inputs(0);
auto output_list = pm.get_part_outputs(0);

for (int i = 0; i < num_parts; i++)
{
auto temp_i = pm.get_part_inputs(i);
node_list.insert(temp_i.begin(), temp_i.end());

auto temp_o = pm.get_part_outputs(i);
node_list.insert(temp_o.begin(), temp_o.end());

output_list.insert(temp_o.begin(), temp_o.end());
}


auto first = true;
int count = 0;
for (auto const &n: node_list )
{
if (!ntk.is_pi(n) && !ntk.is_po(n))
{
if (first) {
first = false;
os << " wire ";
}
else
os << ", ";

node_names[n] = fmt::format( "n{}", count);
os << fmt::format("n{}", count);
count++;
}
}

ntk.foreach_po( [&]( auto const& n, auto i ) {
if ( node_names[n] == "1'b0" ) {
node_names[n] = fmt::format( "tpo{0:0{1}}", i, digitsOut);
vector_output.push_back( -1 );
if (first) {
first = false;
os << " wire ";
}
else
os << ", ";

os << node_names[n];
}
else {
vector_output.push_back( ntk._storage->outputs.at(i).index );
}
} );

if (!first)
os << ";\n";

for ( int i = 0; i < ntk.num_pos(); i++ ) {
if ( vector_output[ i ] != -1 )
os << fmt::format( " assign po{0:0{1}} = {2}{3};\n", i, digitsOut, ntk.is_complemented( ntk._storage->outputs.at(i) ) ? "~" : "", node_names[ vector_output[i] ] );
else
os << fmt::format( " assign po{0:0{1}} = {2}tpo{0:0{1}};\n", i, digitsOut, ntk.is_complemented( ntk._storage->outputs.at(i) ) ? "~" : "" );
}

os.close();
}


template<class Ntk>
void call_submodule( Ntk const& ntk, Ntk const& part_ntk, std::string const& filename, std::string const& modulename, int part_num, oracle::partition_view<Ntk> const& part, node_map<std::string, Ntk> node_names, node_map<std::string, Ntk> input_names )
{
static_assert( is_network_type_v<Ntk>, "Ntk is not a network type" );
static_assert( has_num_latches_v<Ntk>, "Ntk does not implement the has_latches method" );
static_assert( has_num_pis_v<Ntk>, "Ntk does not implement the num_pis method" );
static_assert( has_num_pos_v<Ntk>, "Ntk does not implement the num_pos method" );
static_assert( has_foreach_pi_v<Ntk>, "Ntk does not implement the foreach_pi method" );
static_assert( has_foreach_node_v<Ntk>, "Ntk does not implement the foreach_node method" );
static_assert( has_foreach_fanin_v<Ntk>, "Ntk does not implement the foreach_fanin method" );
static_assert( has_foreach_ri_v<Ntk>, "Ntk does not implement the foreach_ri method" );
static_assert( has_foreach_ro_v<Ntk>, "Ntk does not implement the foreach_ro method" );
static_assert( has_get_node_v<Ntk>, "Ntk does not implement the get_node method" );
static_assert( has_get_constant_v<Ntk>, "Ntk does not implement the get_constant method" );
static_assert( has_is_constant_v<Ntk>, "Ntk does not implement the is_constant method" );
static_assert( has_is_pi_v<Ntk>, "Ntk does not implement the is_pi method" );
static_assert( has_is_and_v<Ntk>, "Ntk does not implement the is_and method" );
static_assert( has_is_or_v<Ntk>, "Ntk does not implement the is_or method" );
static_assert( has_is_xor_v<Ntk>, "Ntk does not implement the is_xor method" );
static_assert( has_is_xor3_v<Ntk>, "Ntk does not implement the is_xor3 method" );
static_assert( has_is_maj_v<Ntk>, "Ntk does not implement the is_maj method" );
static_assert( has_node_to_index_v<Ntk>, "Ntk does not implement the node_to_index method" );

std::ofstream os( filename.c_str(), std::ofstream::app );
os << fmt::format(" {} U{} ( ", modulename, part_num);

auto digitsIn = std::to_string(part_ntk.num_pis()-part_ntk.num_latches()).length();
auto digitsOut = std::to_string(part_ntk.num_pos()-part_ntk.num_latches()).length();

auto first = true;
part_ntk.foreach_pi( [&]( auto const& n, auto i ) {
auto idx = part_ntk.node_to_index( n );
auto node_id = part.index_to_node( idx );
if (first)
first = false;
else
os << ", ";

if ( ntk.is_pi( node_id ) )
os << fmt::format(".pi{0:0{1}}( ", i, digitsIn) << input_names[node_id] << " )";
else
os << fmt::format(".pi{0:0{1}}( ", i, digitsIn) << node_names[node_id] << " )";

} );

part_ntk.foreach_po( [&]( auto const& n, auto i ) {
auto idx = part_ntk._storage->outputs.at(i).index;
auto node_id = part.index_to_node( idx );
if (first)
first = false;
else
os << ", ";

if ( node_names[node_id] == "1'b0" )
os << fmt::format(".po{0:0{1}}( )", i, digitsOut);
else
os << fmt::format(".po{0:0{1}}( ", i, digitsOut) << node_names[node_id] << " )";
} );

os << " );\n";
os.close();
}

} /* namespace mockturtle */
} /* namespace mockturtle */
25 changes: 22 additions & 3 deletions lib/oracle/include/oracle/commands/get_all_partitions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,11 @@ namespace alice
auto ntk = store<mockturtle::aig_network>().current();
std::cout << "\n";
if(!store<oracle::partition_manager<mockturtle::aig_network>>().empty()){
auto partitions = store<oracle::partition_manager<mockturtle::aig_network>>().current();
auto partitions = store<oracle::partition_manager<mockturtle::aig_network>>().current();
mockturtle::node_map<std::string, mockturtle::aig_network> node_names( ntk );
mockturtle::node_map<std::string, mockturtle::aig_network> input_names( ntk );
std::string toplevel_module = std::filesystem::path(ntk._storage->net_name).filename();
std::string toplevel_file = dir + "/" + toplevel_module + ".v";
for(int i = 0; i < partitions.get_part_num(); i++){
std::vector<mockturtle::aig_network> parts;
std::vector<std::string> filenames;
Expand All @@ -88,16 +92,31 @@ namespace alice
oracle::partition_view<mockturtle::aig_network> part = partitions.create_part(ntk, partition);
auto part_ntk = mockturtle::node_resynthesis<mockturtle::aig_network>(part, resyn_aig);

std::string filename = dir + "/" + ntk._storage->net_name + "_" + std::to_string(partition) + ".v";
std::string modulename = std::filesystem::path( ntk._storage->net_name + "_" + std::to_string(partition) ).filename();
std::string filename = dir + "/" + modulename + ".v";
filenames.push_back(filename);
parts.push_back(part_ntk);

if ( part_ntk.num_pos() == 0 )
continue;

assert(parts.size() == filenames.size());
for(int j = 0; j < parts.size(); j++){
mockturtle::write_verilog(parts.at(j), filenames.at(j));
mockturtle::write_verilog(parts.at(j), filenames.at(j), modulename);
}

if (i == 0)
mockturtle::write_toplevel_verilog(ntk, partitions, toplevel_file, node_names, input_names, toplevel_module);

mockturtle::call_submodule( ntk, part_ntk, toplevel_file, modulename, i, part, node_names, input_names);

std::cout << "\n";
}
std::ofstream os( toplevel_file.c_str(), std::ofstream::app);
os << "endmodule\n"
<< std::flush;

os.close();
}
else{
std::cout << "Partitions have not been mapped\n";
Expand Down
4 changes: 2 additions & 2 deletions lib/oracle/include/oracle/partitioning/hyperg.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ void hypergraph<Ntk>::get_hypergraph(Ntk const& ntk) {

template<class Ntk>
void hypergraph<Ntk>::dump() {
ofstream myfile;
std::ofstream myfile;
myfile.open ("hypergraph.txt");
myfile << hyperEdges.size() << " " << ntk.size()-1 << "\n";
for (int i = 0; i < hyperEdges.size(); i++) {
Expand Down Expand Up @@ -145,4 +145,4 @@ void hypergraph<Ntk>::get_indeces(std::vector<unsigned long> &indeces) {
count += (hyperEdges.at(last_index).size());
indeces.push_back(count);
}
} //end of namespace
} //end of namespace