Skip to content
Open
17 changes: 17 additions & 0 deletions doc/src/vpr/command_line_usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,23 @@ Use the options below to override this default naming behaviour.

* The x, y, and sub_tile location of the cluster that contains this atom.

.. option:: --flat_place_verbosity <int>

Controls how much annotation is written into flat placement files
(see :ref:`flat placement file format <vpr_flat_place_file>`). Annotations are
informational only: :option:`vpr --read_flat_place` ignores everything past the
``<atom_sub_tile>`` column. Each level includes what the levels below it print.

* ``0``: No annotation and no header comments, i.e. only the columns the reader
parses. The output is then exactly the input format documented above, and
carries no build timestamp, so it is reproducible across runs.
* ``1``: Header comments, plus the cluster block number and the primitive type
of each atom.
* ``2``: Additionally each atom's ``site_path``, the hierarchical path of the
primitive it was placed on within its cluster.

**Default:** ``1``

.. _netlist_options:

Netlist Options
Expand Down
16 changes: 16 additions & 0 deletions doc/src/vpr/file_formats.rst
Original file line number Diff line number Diff line change
Expand Up @@ -727,6 +727,22 @@ multiple clusters can be stacked there). A sub-tile of -1 may be used when
the sub-tile of an atom is unknown (allowing the packing algorithm to choose
any sub-tile at the given (x, y, layer) location).

Lines written by VPR (:option:`vpr --write_flat_place`) carry additional annotation
columns after ``<atom_sub_tile>``, controlled by :option:`vpr --flat_place_verbosity`.
These are informational only and are ignored when the file is read back. By default
the cluster block number the atom was packed into and the primitive type it was placed
on are appended; at verbosity ``2`` the path of that primitive is appended as well:

.. code-block:: none

<atom_name> <x> <y> <layer> <atom_sub_tile> #<clb_blk_id> <atom_pb_type> <site_path>

n523 6 8 0 0 #12 lut6 clb[0][default]/lab[0][default]/fle[3][n1_lut6]/ble6[0][default]/lut6[0]

``site_path`` is the hierarchical path of the primitive the atom was placed on within its
cluster (``t_pb_graph_node::hierarchical_type_name()``), including the mode selected at each
level.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would update this text to make it clear that anything after the pound symbol (#) is a comment and is not parsed by VPR when read; it is only for the user to better understand and interpret the file. Your new argument allows us to select how verbose we want it.

I really like the idea of adding a verbosity 0 since printing the CLB number and the primitive was always weird to me. This was grandfathered in by the first implementation of the flat placement file, which was not made by me.


When used with ``flat-recon`` full legalizer (see :option:`vpr --ap_full_legalizer`),
each atom in a molecule should have compatible location information. It is legal to
leave some molecules unconstrained; the reconstruction phase will choose where
Expand Down
3 changes: 2 additions & 1 deletion vpr/src/analytical_place/analytical_placement_flow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,8 @@ void run_analytical_placement_flow(t_vpr_setup& vpr_setup) {
write_flat_placement(vpr_setup.FileNameOpts.write_legalized_flat_place_file.c_str(),
g_vpr_ctx.clustering().clb_nlist,
g_vpr_ctx.placement().block_locs(),
g_vpr_ctx.clustering().atoms_lookup);
g_vpr_ctx.clustering().atoms_lookup,
vpr_setup.FileNameOpts.flat_place_verbosity);
}

// Run the Detailed Placer.
Expand Down
60 changes: 44 additions & 16 deletions vpr/src/base/load_flat_place.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,23 @@
*
* @param fp
* File pointer to the file the cluster is printed to.
* @param flat_place_verbosity
* How much annotation the file carries; decides which columns the
* header announces. See write_flat_placement().
*/
static void print_flat_placement_file_header(FILE* fp) {
static void print_flat_placement_file_header(FILE* fp, int flat_place_verbosity) {
fprintf(fp, "# Flat Placement File\n");
fprintf(fp, "# Auto-generated by VPR %s\n",
vtr::VERSION);
fprintf(fp, "# Created: %s\n",
vtr::BUILD_TIMESTAMP);
fprintf(fp, "#\n");
fprintf(fp, "# This file prints the following information for each atom in the netlist:\n");
fprintf(fp, "# <atom_name> <x> <y> <layer> <atom_sub_tile> #<clb_blk_id> <atom_pb_type>\n");
if (flat_place_verbosity >= 2) {
fprintf(fp, "# <atom_name> <x> <y> <layer> <atom_sub_tile> #<clb_blk_id> <atom_pb_type> <site_path>\n");
} else {
fprintf(fp, "# <atom_name> <x> <y> <layer> <atom_sub_tile> #<clb_blk_id> <atom_pb_type>\n");
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be written slightly cleaner (and easier) by printing the common part first, then the uncommon part in an if, and then print the \n. A bit of a nit, but will make it easier to extend in the future if we want to add more.

fprintf(fp, "\n");
}

Expand All @@ -57,36 +64,54 @@ static void print_flat_placement_file_header(FILE* fp) {
* @param atoms_lookup
* A lookup between all clusters and the atom blocks that they
* contain.
* @param flat_place_verbosity
* How much annotation to append to each atom's line. See
* write_flat_placement().
*/
static void print_flat_cluster(FILE* fp,
ClusterBlockId blk_id,
const vtr::vector_map<ClusterBlockId, t_block_loc>& block_locs,
const vtr::vector<ClusterBlockId, std::unordered_set<AtomBlockId>>& atoms_lookup) {
// Atom context used to get the atom_pb for each atom in the cluster.
const vtr::vector<ClusterBlockId, std::unordered_set<AtomBlockId>>& atoms_lookup,
int flat_place_verbosity) {
const AtomContext& atom_ctx = g_vpr_ctx.atom();

// Get the location of this cluster.
const t_pl_loc& blk_loc = block_locs[blk_id].loc;

// Print a line for each atom.
for (AtomBlockId atom : atoms_lookup[blk_id]) {
// Get the atom pb graph node.
t_pb_graph_node* atom_pbgn = atom_ctx.lookup().atom_pb_bimap().atom_pb(atom)->pb_graph_node;

// Print the flat placement information for this atom.
fprintf(fp, "%s %d %d %d %d #%zu %s\n",
// Print the placement of this atom. These are the only columns the
// flat placement reader parses; everything below is annotation.
fprintf(fp, "%s %d %d %d %d",
atom_ctx.netlist().block_name(atom).c_str(),
blk_loc.x, blk_loc.y, blk_loc.layer,
blk_loc.sub_tile,
static_cast<size_t>(blk_id),
atom_pbgn->pb_type->name);
blk_loc.sub_tile);

if (flat_place_verbosity >= 1) {
// Get the atom pb graph node, which holds the primitive the atom
// was placed on.
t_pb_graph_node* atom_pbgn = atom_ctx.lookup().atom_pb_bimap().atom_pb(atom)->pb_graph_node;

fprintf(fp, " #%zu %s",
static_cast<size_t>(blk_id),
atom_pbgn->pb_type->name);

if (flat_place_verbosity >= 2) {
// The hierarchical path of the primitive this atom was placed
// on, e.g. "clb[0][default]/lab[0][default]/fle[3][n1_lut6]".
fprintf(fp, " %s", atom_pbgn->hierarchical_type_name().c_str());
}
}

fprintf(fp, "\n");
}
}

void write_flat_placement(const char* flat_place_file_path,
const ClusteredNetlist& cluster_netlist,
const vtr::vector_map<ClusterBlockId, t_block_loc>& block_locs,
const vtr::vector<ClusterBlockId, std::unordered_set<AtomBlockId>>& atoms_lookup) {
const vtr::vector<ClusterBlockId, std::unordered_set<AtomBlockId>>& atoms_lookup,
int flat_place_verbosity) {
// Writes the flat placement to the given flat_place_file_path.

// Only print a flat placement if the clusters have been placed.
Expand All @@ -96,13 +121,16 @@ void write_flat_placement(const char* flat_place_file_path,
// Create a file in write mode for the flat placement.
FILE* fp = fopen(flat_place_file_path, "w");

// Add a header to the flat placement file.
print_flat_placement_file_header(fp);
// Add a header to the flat placement file. The header is itself a comment,
// so it is omitted when no annotation was asked for.
if (flat_place_verbosity >= 1) {
print_flat_placement_file_header(fp, flat_place_verbosity);
}

// For each cluster, write out the atoms in the cluster at this cluster's
// location.
for (ClusterBlockId iblk : cluster_netlist.blocks()) {
print_flat_cluster(fp, iblk, block_locs, atoms_lookup);
print_flat_cluster(fp, iblk, block_locs, atoms_lookup, flat_place_verbosity);
}

// Close the file.
Expand Down
17 changes: 16 additions & 1 deletion vpr/src/base/load_flat_place.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,26 @@ struct t_vpr_setup;
* The locations of all of the blocks in the cluster_netlist.
* @param atoms_lookup
* A lookup between each cluster and the atoms within it.
* @param flat_place_verbosity
* How much annotation to write (see --flat_place_verbosity).
* Annotations are informational only; read_flat_placement()
* ignores everything past the sub-tile column. Each level
* includes what the levels below it print:
* 0: no annotation and no header comments, i.e. only the
* columns the reader parses. The output is then exactly
* the documented input format, and carries no build
* timestamp, so it is reproducible across runs.
* 1: header comments, plus the cluster block id and the
* primitive type of each atom.
* 2: additionally each atom's site_path, the hierarchical
* path of the primitive it was placed on within its
* cluster.
*/
void write_flat_placement(const char* flat_place_file_path,
const ClusteredNetlist& cluster_netlist,
const vtr::vector_map<ClusterBlockId, t_block_loc>& block_locs,
const vtr::vector<ClusterBlockId, std::unordered_set<AtomBlockId>>& atoms_lookup);
const vtr::vector<ClusterBlockId, std::unordered_set<AtomBlockId>>& atoms_lookup,
int flat_place_verbosity);

/**
* @brief Reads a flat placement file generated from a previous run of VTR or
Expand Down
13 changes: 13 additions & 0 deletions vpr/src/base/read_options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2066,6 +2066,19 @@ argparse::ArgumentParser create_arg_parser(const std::string& prog_name, t_optio
"VPR's (or reconstructed external) placement solution after legalization and before anneal in flat placement file format; this file lists (x, y, layer) coordinates and subtile for each atom and can be used to reconstruct a clustering and placement solution.")
.show_in(argparse::ShowIn::HELP_ONLY);

file_grp.add_argument<int>(args.flat_place_verbosity, "--flat_place_verbosity")
.help(
"Controls how much annotation is written into flat placement files."
" Annotations are informational only; the flat placement reader ignores"
" everything past the sub-tile column."
" 0: no annotations and no header comments, i.e. only the columns the reader parses."
" 1: header comments, plus the cluster block id and primitive type of each atom."
" 2: additionally the site_path of each atom, the hierarchical path of the"
" primitive it was placed on within its cluster."
" Larger values produce more detail.")
.default_value("1")
.show_in(argparse::ShowIn::HELP_ONLY);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comment above about making this an integer instead of a bool.


file_grp.add_argument(args.read_router_lookahead, "--read_router_lookahead")
.help(
"Reads the lookahead data from the specified file instead of computing it.")
Expand Down
1 change: 1 addition & 0 deletions vpr/src/base/read_options.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ struct t_options {
argparse::ArgValue<std::string> read_flat_place_file;
argparse::ArgValue<std::string> write_flat_place_file;
argparse::ArgValue<std::string> write_legalized_flat_place_file;
argparse::ArgValue<int> flat_place_verbosity;

argparse::ArgValue<std::string> write_placement_delay_lookup;
argparse::ArgValue<std::string> read_placement_delay_lookup;
Expand Down
1 change: 1 addition & 0 deletions vpr/src/base/setup_vpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ void SetupVPR(const t_options* options,
fileNameOpts->read_flat_place_file = options->read_flat_place_file;
fileNameOpts->write_flat_place_file = options->write_flat_place_file;
fileNameOpts->write_legalized_flat_place_file = options->write_legalized_flat_place_file;
fileNameOpts->flat_place_verbosity = options->flat_place_verbosity;
fileNameOpts->write_block_usage = options->write_block_usage;

fileNameOpts->verify_file_digests = options->verify_file_digests;
Expand Down
9 changes: 6 additions & 3 deletions vpr/src/base/vpr_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,8 @@ bool vpr_flow(t_vpr_setup& vpr_setup, t_arch& arch) {
write_flat_placement(vpr_setup.FileNameOpts.write_flat_place_file.c_str(),
g_vpr_ctx.clustering().clb_nlist,
g_vpr_ctx.placement().block_locs(),
g_vpr_ctx.clustering().atoms_lookup);
g_vpr_ctx.clustering().atoms_lookup,
vpr_setup.FileNameOpts.flat_place_verbosity);
}

// Print the placement generated by AP to a .place file.
Expand Down Expand Up @@ -865,7 +866,8 @@ bool vpr_load_flat_placement(t_vpr_setup& vpr_setup, const t_arch& arch) {
write_flat_placement(getEchoFileName(E_ECHO_FLAT_PLACE),
g_vpr_ctx.clustering().clb_nlist,
g_vpr_ctx.placement().block_locs(),
g_vpr_ctx.clustering().atoms_lookup);
g_vpr_ctx.clustering().atoms_lookup,
vpr_setup.FileNameOpts.flat_place_verbosity);
}

// reset the device grid
Expand Down Expand Up @@ -925,7 +927,8 @@ bool vpr_place_flow(const Netlist<>& net_list,
write_flat_placement(filename_opts.write_flat_place_file.c_str(),
g_vpr_ctx.clustering().clb_nlist,
g_vpr_ctx.placement().block_locs(),
g_vpr_ctx.clustering().atoms_lookup);
g_vpr_ctx.clustering().atoms_lookup,
filename_opts.flat_place_verbosity);
}

return true;
Expand Down
2 changes: 2 additions & 0 deletions vpr/src/base/vpr_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -687,6 +687,8 @@ struct t_file_name_opts {
std::string write_legalized_flat_place_file;
std::string write_block_usage;
bool verify_file_digests;
///@brief How much annotation to write into flat placement files.
int flat_place_verbosity;
};

///@brief Options for netlist loading
Expand Down
Loading