Merge branch 'refactoring' into dev

This commit is contained in:
tangxifan 2020-01-29 18:59:27 -07:00
commit 60d56cbdf1
8 changed files with 429 additions and 4 deletions

View File

@ -66,4 +66,7 @@ void write_xml_openfpga_arch(const char* fname,
/* Write the simulation */
write_xml_simulation_setting(fp, fname, openfpga_arch.sim_setting);
/* Close the file stream */
fp.close();
}

View File

@ -0,0 +1,254 @@
/********************************************************************
* This file includes functions to detect and correct any naming
* in the users' BLIF netlist that violates the syntax of OpenFPGA
* fabric generator, i.e., Verilog generator and SPICE generator
*******************************************************************/
#include <string>
#include <fstream>
/* Headers from vtrutil library */
#include "vtr_time.h"
#include "vtr_assert.h"
#include "vtr_log.h"
/* Headers from archopenfpga library */
#include "write_xml_utils.h"
/* Headers from openfpgautil library */
#include "openfpga_digest.h"
#include "check_netlist_naming_conflict.h"
/* Include global variables of VPR */
#include "globals.h"
/* begin namespace openfpga */
namespace openfpga {
/********************************************************************
* This function aims to check if the name contains any of the
* sensitive characters in the list
* Return a string of sensitive characters which are contained
* in the name
*******************************************************************/
static
std::string name_contain_sensitive_chars(const std::string& name,
const std::string& sensitive_chars) {
std::string violation;
for (const char& sensitive_char : sensitive_chars) {
/* Return true since we find a characters */
if (std::string::npos != name.find(sensitive_char)) {
violation.push_back(sensitive_char);
}
}
return violation;
}
/********************************************************************
* This function aims to fix up a name that contains any of the
* sensitive characters in the list
* Return a string the fixed name
*******************************************************************/
static
std::string fix_name_contain_sensitive_chars(const std::string& name,
const std::string& sensitive_chars,
const std::string& fix_chars) {
std::string fixed_name = name;
VTR_ASSERT(sensitive_chars.length() == fix_chars.length());
for (size_t ichar = 0; ichar < sensitive_chars.length(); ++ichar) {
/* Keep fixing the characters until we cannot find anymore */
std::string::size_type pos = 0u;
while (std::string::npos != (pos = fixed_name.find(sensitive_chars[ichar], pos))) {
fixed_name.replace(pos, 1, std::string(1, fix_chars[ichar]));
pos += 1;
}
}
return fixed_name;
}
/********************************************************************
* Detect and report any naming conflict by checking a list of
* sensitive characters
* - Iterate over all the blocks and see if any block name contain
* any sensitive character
* - Iterate over all the nets and see if any net name contain
* any sensitive character
*******************************************************************/
static
size_t detect_netlist_naming_conflict(const AtomNetlist& atom_netlist,
const std::string& sensitive_chars) {
size_t num_conflicts = 0;
/* Walk through blocks in the netlist */
for (const auto& block : atom_netlist.blocks()) {
const std::string& block_name = atom_netlist.block_name(block);
const std::string& violation = name_contain_sensitive_chars(block_name, sensitive_chars);
if (false == violation.empty()) {
VTR_LOG("Block '%s' contains illegal characters '%s'\n",
block_name.c_str(), violation.c_str());
num_conflicts++;
}
}
/* Walk through nets in the netlist */
for (const auto& net : atom_netlist.nets()) {
const std::string& net_name = atom_netlist.net_name(net);
const std::string& violation = name_contain_sensitive_chars(net_name, sensitive_chars);
if (false == violation.empty()) {
VTR_LOG("Net '%s' contains illegal characters '%s'\n",
net_name.c_str(), violation.c_str());
num_conflicts++;
}
}
return num_conflicts;
}
/********************************************************************
* Correct and report any naming conflict by checking a list of
* sensitive characters
* - Iterate over all the blocks and correct any block name that contains
* any sensitive character
* - Iterate over all the nets and correct any net name that contains
* any sensitive character
*******************************************************************/
static
void fix_netlist_naming_conflict(const AtomNetlist& atom_netlist,
const std::string& sensitive_chars,
const std::string& fix_chars,
VprNetlistAnnotation& vpr_netlist_annotation) {
size_t num_fixes = 0;
/* Walk through blocks in the netlist */
for (const auto& block : atom_netlist.blocks()) {
const std::string& block_name = atom_netlist.block_name(block);
const std::string& violation = name_contain_sensitive_chars(block_name, sensitive_chars);
if (false == violation.empty()) {
/* Apply fix-up here */
vpr_netlist_annotation.rename_block(block, fix_name_contain_sensitive_chars(block_name, sensitive_chars, fix_chars));
num_fixes++;
}
}
/* Walk through nets in the netlist */
for (const auto& net : atom_netlist.nets()) {
const std::string& net_name = atom_netlist.net_name(net);
const std::string& violation = name_contain_sensitive_chars(net_name, sensitive_chars);
if (false == violation.empty()) {
/* Apply fix-up here */
vpr_netlist_annotation.rename_net(net, fix_name_contain_sensitive_chars(net_name, sensitive_chars, fix_chars));
num_fixes++;
}
}
if (0 < num_fixes) {
VTR_LOG("Fixed %ld naming conflicts in the netlist.\n",
num_fixes);
}
}
/********************************************************************
* Report all the fix-up in the naming of netlist components,
* i.e., blocks, nets
*******************************************************************/
static
void print_netlist_naming_fix_report(const std::string& fname,
const AtomNetlist& atom_netlist,
const VprNetlistAnnotation& vpr_netlist_annotation) {
/* Create a file handler */
std::fstream fp;
/* Open the file stream */
fp.open(fname, std::fstream::out | std::fstream::trunc);
/* Validate the file stream */
openfpga::check_file_stream(fname.c_str(), fp);
fp << "<!-- Netlist naming fix-up report --> " << "\n";
fp << "<netlist>" << "\n";
fp << "\t" << "<blocks>" << "\n";
for (const auto& block : atom_netlist.blocks()) {
const std::string& block_name = atom_netlist.block_name(block);
if (false == vpr_netlist_annotation.is_block_renamed(block)) {
continue;
}
fp << "\t\t" << "<block";
write_xml_attribute(fp, "previous", block_name.c_str());
write_xml_attribute(fp, "current", vpr_netlist_annotation.block_name(block).c_str());
fp << "/>" << "\n";
}
fp << "\t" << "</blocks>" << "\n";
fp << "\t" << "<nets>" << "\n";
for (const auto& net : atom_netlist.nets()) {
const std::string& net_name = atom_netlist.net_name(net);
if (false == vpr_netlist_annotation.is_net_renamed(net)) {
continue;
}
fp << "\t\t" << "<net";
write_xml_attribute(fp, "previous", net_name.c_str());
write_xml_attribute(fp, "current", vpr_netlist_annotation.net_name(net).c_str());
fp << "/>" << "\n";
}
fp << "\t" << "</nets>" << "\n";
fp << "</netlist>" << "\n";
/* Close the file stream */
fp.close();
}
/********************************************************************
* Top-level function to detect and correct any naming
* in the users' BLIF netlist that violates the syntax of OpenFPGA
* fabric generator, i.e., Verilog generator and SPICE generator
*******************************************************************/
void check_netlist_naming_conflict(OpenfpgaContext& openfpga_context,
const Command& cmd, const CommandContext& cmd_context) {
vtr::ScopedStartFinishTimer timer("Check naming violations of netlist blocks and nets");
/* By default, we replace all the illegal characters with '_' */
const std::string& sensitive_chars(".,:;\'\"+-<>()[]{}!@#$%^&*~`?/");
const std::string& fix_chars("____________________________");
CommandOptionId opt_fix = cmd.option("fix");
/* Do the main job first: detect any naming in the BLIF netlist that violates the syntax */
if (false == cmd_context.option_enable(cmd, opt_fix)) {
size_t num_conflicts = detect_netlist_naming_conflict(g_vpr_ctx.atom().nlist, sensitive_chars);
VTR_LOGV_ERROR((0 < num_conflicts && (false == cmd_context.option_enable(cmd, opt_fix))),
"Found %ld naming conflicts in the netlist. Please correct so as to use any fabric generators.\n",
num_conflicts);
VTR_LOGV(0 == num_conflicts,
"Check naming conflicts in the netlist passed.\n");
return;
}
/* If the auto correction is enabled, we apply a fix */
if (true == cmd_context.option_enable(cmd, opt_fix)) {
fix_netlist_naming_conflict(g_vpr_ctx.atom().nlist, sensitive_chars,
fix_chars, openfpga_context.mutable_vpr_netlist_annotation());
CommandOptionId opt_report = cmd.option("report");
if (true == cmd_context.option_enable(cmd, opt_report)) {
print_netlist_naming_fix_report(cmd_context.option_value(cmd, opt_report),
g_vpr_ctx.atom().nlist,
openfpga_context.vpr_netlist_annotation());
VTR_LOG("Naming fix-up report is generated to file '%s'\n",
cmd_context.option_value(cmd, opt_report).c_str());
}
}
}
} /* end namespace openfpga */

View File

@ -0,0 +1,23 @@
#ifndef CHECK_NETLIST_NAMING_CONFLICT_H
#define CHECK_NETLIST_NAMING_CONFLICT_H
/********************************************************************
* Include header files that are required by function declaration
*******************************************************************/
#include "command.h"
#include "command_context.h"
#include "openfpga_context.h"
/********************************************************************
* Function declaration
*******************************************************************/
/* begin namespace openfpga */
namespace openfpga {
void check_netlist_naming_conflict(OpenfpgaContext& openfpga_context,
const Command& cmd, const CommandContext& cmd_context);
} /* end namespace openfpga */
#endif

View File

@ -3,6 +3,7 @@
#include "vpr_context.h"
#include "openfpga_arch.h"
#include "vpr_netlist_annotation.h"
#include "vpr_pb_type_annotation.h"
/********************************************************************
@ -36,14 +37,18 @@ class OpenfpgaContext : public Context {
public: /* Public accessors */
const openfpga::Arch& arch() const { return arch_; }
const openfpga::VprPbTypeAnnotation& vpr_pb_type_annotation() const { return vpr_pb_type_annotation_; }
const openfpga::VprNetlistAnnotation& vpr_netlist_annotation() const { return vpr_netlist_annotation_; }
public: /* Public mutators */
openfpga::Arch& mutable_arch() { return arch_; }
openfpga::VprPbTypeAnnotation& mutable_vpr_pb_type_annotation() { return vpr_pb_type_annotation_; }
openfpga::VprNetlistAnnotation& mutable_vpr_netlist_annotation() { return vpr_netlist_annotation_; }
private: /* Internal data */
/* Data structure to store information from read_openfpga_arch library */
openfpga::Arch arch_;
/* Annotation to pb_type of VPR */
openfpga::VprPbTypeAnnotation vpr_pb_type_annotation_;
/* Naming fix to netlist */
openfpga::VprNetlistAnnotation vpr_netlist_annotation_;
};
#endif

View File

@ -5,16 +5,22 @@
*******************************************************************/
#include "openfpga_read_arch.h"
#include "openfpga_link_arch.h"
#include "check_netlist_naming_conflict.h"
#include "openfpga_setup_command.h"
/* begin namespace openfpga */
namespace openfpga {
void add_openfpga_setup_commands(openfpga::Shell<OpenfpgaContext>& shell) {
/* Get the unique id of 'vpr' command which is to be used in creating the dependency graph */
const ShellCommandId& shell_cmd_vpr_id = shell.command(std::string("vpr"));
/* Add a new class of commands */
ShellCommandClassId openfpga_setup_cmd_class = shell.add_command_class("OpenFPGA setup");
/* Command 'read_openfpga_arch' */
/********************************
* Command 'read_openfpga_arch'
*/
Command shell_cmd_read_arch("read_openfpga_arch");
/* Add an option '--file' in short '-f'*/
CommandOptionId read_arch_opt_file = shell_cmd_read_arch.add_option("file", true, "file path to the architecture XML");
@ -26,7 +32,9 @@ void add_openfpga_setup_commands(openfpga::Shell<OpenfpgaContext>& shell) {
shell.set_command_class(shell_cmd_read_arch_id, openfpga_setup_cmd_class);
shell.set_command_execute_function(shell_cmd_read_arch_id, read_arch);
/* Command 'write_openfpga_arch' */
/********************************
* Command 'write_openfpga_arch'
*/
Command shell_cmd_write_arch("write_openfpga_arch");
/* Add an option '--file' in short '-f'*/
CommandOptionId write_arch_opt_file = shell_cmd_write_arch.add_option("file", true, "file path to the architecture XML");
@ -40,7 +48,9 @@ void add_openfpga_setup_commands(openfpga::Shell<OpenfpgaContext>& shell) {
/* The 'write_openfpga_arch' command should NOT be executed before 'read_openfpga_arch' */
shell.set_command_dependency(shell_cmd_write_arch_id, std::vector<ShellCommandId>(1, shell_cmd_read_arch_id));
/* Command 'link_openfpga_arch' */
/********************************
* Command 'link_openfpga_arch'
*/
Command shell_cmd_link_openfpga_arch("link_openfpga_arch");
/* Add command 'link_openfpga_arch' to the Shell */
@ -48,12 +58,28 @@ void add_openfpga_setup_commands(openfpga::Shell<OpenfpgaContext>& shell) {
shell.set_command_class(shell_cmd_link_openfpga_arch_id, openfpga_setup_cmd_class);
shell.set_command_execute_function(shell_cmd_link_openfpga_arch_id, link_arch);
/* The 'link_openfpga_arch' command should NOT be executed before 'read_openfpga_arch' and 'vpr' */
const ShellCommandId& shell_cmd_vpr_id = shell.command(std::string("vpr"));
std::vector<ShellCommandId> cmd_dependency_link_openfpga_arch;
cmd_dependency_link_openfpga_arch.push_back(shell_cmd_read_arch_id);
cmd_dependency_link_openfpga_arch.push_back(shell_cmd_vpr_id);
shell.set_command_dependency(shell_cmd_link_openfpga_arch_id, cmd_dependency_link_openfpga_arch);
/*******************************************
* Command 'check_netlist_naming_conflict'
*/
Command shell_cmd_check_netlist_naming_conflict("check_netlist_naming_conflict");
/* Add an option '--correction' */
shell_cmd_check_netlist_naming_conflict.add_option("fix", false, "Apply correction to any conflicts found");
/* Add an option '--report' */
CommandOptionId check_netlist_opt_rpt = shell_cmd_check_netlist_naming_conflict.add_option("report", false, "Output a report file about what any correction applied");
shell_cmd_check_netlist_naming_conflict.set_option_require_value(check_netlist_opt_rpt, openfpga::OPT_STRING);
/* Add command 'check_netlist_naming_conflict' to the Shell */
ShellCommandId shell_cmd_check_netlist_naming_conflict_id = shell.add_command(shell_cmd_check_netlist_naming_conflict, "Check any block/net naming in users' BLIF netlist violates the syntax of fabric generator");
shell.set_command_class(shell_cmd_check_netlist_naming_conflict_id, openfpga_setup_cmd_class);
shell.set_command_execute_function(shell_cmd_check_netlist_naming_conflict_id, check_netlist_naming_conflict);
/* The 'link_openfpga_arch' command should NOT be executed before 'read_openfpga_arch' and 'vpr' */
std::vector<ShellCommandId> cmd_dependency_check_netlist_naming_conflict(1, shell_cmd_vpr_id);
shell.set_command_dependency(shell_cmd_link_openfpga_arch_id, cmd_dependency_check_netlist_naming_conflict);
}
} /* end namespace openfpga */

View File

@ -0,0 +1,68 @@
/************************************************************************
* Member functions for class VprNetlistAnnotation
***********************************************************************/
#include "vtr_log.h"
#include "vtr_assert.h"
#include "vpr_netlist_annotation.h"
/* namespace openfpga begins */
namespace openfpga {
/************************************************************************
* Constructors
***********************************************************************/
VprNetlistAnnotation::VprNetlistAnnotation() {
return;
}
/************************************************************************
* Public accessors
***********************************************************************/
bool VprNetlistAnnotation::is_block_renamed(const AtomBlockId& block) const {
/* Ensure that the pb_type is in the list */
std::map<AtomBlockId, std::string>::const_iterator it = block_names_.find(block);
return it != block_names_.end();
}
std::string VprNetlistAnnotation::block_name(const AtomBlockId& block) const {
VTR_ASSERT(true == is_block_renamed(block));
return block_names_.at(block);
}
bool VprNetlistAnnotation::is_net_renamed(const AtomNetId& net) const {
/* Ensure that the pb_type is in the list */
std::map<AtomNetId, std::string>::const_iterator it = net_names_.find(net);
return it != net_names_.end();
}
std::string VprNetlistAnnotation::net_name(const AtomNetId& net) const {
VTR_ASSERT(true == is_net_renamed(net));
return net_names_.at(net);
}
/************************************************************************
* Public mutators
***********************************************************************/
void VprNetlistAnnotation::rename_block(const AtomBlockId& block, const std::string& name) {
/* Warn any override attempt */
std::map<AtomBlockId, std::string>::const_iterator it = block_names_.find(block);
if (it != block_names_.end()) {
VTR_LOG_WARN("Override the block with name '%s' in netlist annotation!\n",
name.c_str());
}
block_names_[block] = name;
}
void VprNetlistAnnotation::rename_net(const AtomNetId& net, const std::string& name) {
/* Warn any override attempt */
std::map<AtomNetId, std::string>::const_iterator it = net_names_.find(net);
if (it != net_names_.end()) {
VTR_LOG_WARN("Override the net with name '%s' in netlist annotation!\n",
name.c_str());
}
net_names_[net] = name;
}
} /* End namespace openfpga*/

View File

@ -0,0 +1,43 @@
#ifndef VPR_NETLIST_ANNOTATION_H
#define VPR_NETLIST_ANNOTATION_H
/********************************************************************
* Include header files required by the data structure definition
*******************************************************************/
#include <map>
/* Header from vpr library */
#include "atom_netlist.h"
/* Begin namespace openfpga */
namespace openfpga {
/********************************************************************
* This is the critical data structure to link the pb_type in VPR
* to openfpga annotations
* With a given pb_type pointer, it aims to identify:
* 1. if the pb_type is a physical pb_type or a operating pb_type
* 2. what is the circuit model id linked to a physical pb_type
* 3. what is the physical pb_type for an operating pb_type
* 4. what is the mode pointer that represents the physical mode for a pb_type
*******************************************************************/
class VprNetlistAnnotation {
public: /* Constructor */
VprNetlistAnnotation();
public: /* Public accessors */
bool is_block_renamed(const AtomBlockId& block) const;
std::string block_name(const AtomBlockId& block) const;
bool is_net_renamed(const AtomNetId& net) const;
std::string net_name(const AtomNetId& net) const;
public: /* Public mutators */
void rename_block(const AtomBlockId& block, const std::string& name);
void rename_net(const AtomNetId& net, const std::string& name);
private: /* Internal data */
/* Pair a regular pb_type to its physical pb_type */
std::map<AtomBlockId, std::string> block_names_;
std::map<AtomNetId, std::string> net_names_;
};
} /* End namespace openfpga*/
#endif

View File

@ -7,5 +7,8 @@ read_openfpga_arch -f ./test_openfpga_arch/k6_N10_40nm_openfpga.xml
# Annotate the OpenFPGA architecture to VPR data base
link_openfpga_arch
# Check and correct any naming conflicts in the BLIF netlist
check_netlist_naming_conflict --fix --report ./netlist_renaming.rpt
# Finish and exit OpenFPGA
exit