start transplanting FPGA-SPICE

This commit is contained in:
tangxifan 2020-07-05 12:10:12 -06:00
parent 1ad6e8292a
commit 81171a8f97
15 changed files with 515 additions and 0 deletions

View File

@ -67,6 +67,7 @@ class OpenfpgaContext : public Context {
const openfpga::IoLocationMap& io_location_map() const { return io_location_map_; } const openfpga::IoLocationMap& io_location_map() const { return io_location_map_; }
const std::unordered_map<AtomNetId, t_net_power>& net_activity() const { return net_activity_; } const std::unordered_map<AtomNetId, t_net_power>& net_activity() const { return net_activity_; }
const openfpga::NetlistManager& verilog_netlists() const { return verilog_netlists_; } const openfpga::NetlistManager& verilog_netlists() const { return verilog_netlists_; }
const openfpga::NetlistManager& spice_netlists() const { return spice_netlists_; }
public: /* Public mutators */ public: /* Public mutators */
openfpga::Arch& mutable_arch() { return arch_; } openfpga::Arch& mutable_arch() { return arch_; }
openfpga::SimulationSetting& mutable_simulation_setting() { return sim_setting_; } openfpga::SimulationSetting& mutable_simulation_setting() { return sim_setting_; }
@ -86,6 +87,7 @@ class OpenfpgaContext : public Context {
openfpga::IoLocationMap& mutable_io_location_map() { return io_location_map_; } openfpga::IoLocationMap& mutable_io_location_map() { return io_location_map_; }
std::unordered_map<AtomNetId, t_net_power>& mutable_net_activity() { return net_activity_; } std::unordered_map<AtomNetId, t_net_power>& mutable_net_activity() { return net_activity_; }
openfpga::NetlistManager& mutable_verilog_netlists() { return verilog_netlists_; } openfpga::NetlistManager& mutable_verilog_netlists() { return verilog_netlists_; }
openfpga::NetlistManager& mutable_spice_netlists() { return spice_netlists_; }
private: /* Internal data */ private: /* Internal data */
/* Data structure to store information from read_openfpga_arch library */ /* Data structure to store information from read_openfpga_arch library */
openfpga::Arch arch_; openfpga::Arch arch_;
@ -130,6 +132,7 @@ class OpenfpgaContext : public Context {
* TODO: Each format should have an independent entry * TODO: Each format should have an independent entry
*/ */
openfpga::NetlistManager verilog_netlists_; openfpga::NetlistManager verilog_netlists_;
openfpga::NetlistManager spice_netlists_;
/* Net activities of users' implementation */ /* Net activities of users' implementation */
std::unordered_map<AtomNetId, t_net_power> net_activity_; std::unordered_map<AtomNetId, t_net_power> net_activity_;

View File

@ -0,0 +1,47 @@
/********************************************************************
* This file includes functions to compress the hierachy of routing architecture
*******************************************************************/
/* Headers from vtrutil library */
#include "vtr_time.h"
#include "vtr_log.h"
/* Headers from openfpgashell library */
#include "command_exit_codes.h"
#include "spice_api.h"
#include "openfpga_spice.h"
/* Include global variables of VPR */
#include "globals.h"
/* begin namespace openfpga */
namespace openfpga {
/********************************************************************
* A wrapper function to call the fabric SPICE generator of FPGA-SPICE
*******************************************************************/
int write_fabric_spice(OpenfpgaContext& openfpga_ctx,
const Command& cmd, const CommandContext& cmd_context) {
CommandOptionId opt_output_dir = cmd.option("file");
CommandOptionId opt_explicit_port_mapping = cmd.option("explicit_port_mapping");
CommandOptionId opt_verbose = cmd.option("verbose");
/* This is an intermediate data structure which is designed to modularize the FPGA-SPICE
* Keep it independent from any other outside data structures
*/
FabricSpiceOption options;
options.set_output_directory(cmd_context.option_value(cmd, opt_output_dir));
options.set_explicit_port_mapping(cmd_context.option_enable(cmd, opt_explicit_port_mapping));
options.set_verbose_output(cmd_context.option_enable(cmd, opt_verbose));
options.set_compress_routing(openfpga_ctx.flow_manager().compress_routing());
fpga_fabric_spice(openfpga_ctx.module_graph(),
openfpga_ctx.mutable_spice_netlists(),
options);
/* TODO: should identify the error code from internal function execution */
return CMD_EXEC_SUCCESS;
}
} /* end namespace openfpga */

View File

@ -0,0 +1,23 @@
#ifndef OPENFPGA_SPICE_H
#define OPENFPGA_SPICE_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 {
int write_fabric_spice(OpenfpgaContext& openfpga_ctx,
const Command& cmd, const CommandContext& cmd_context);
} /* end namespace openfpga */
#endif

View File

@ -0,0 +1,78 @@
/********************************************************************
* Add commands to the OpenFPGA shell interface,
* in purpose of generate SPICE netlists modeling the full FPGA fabric
* This is one of the core engine of openfpga, including:
* - generate_fabric_spice : generate Verilog netlists about FPGA fabric
* - TODO: generate_spice_top_testbench : generate SPICE testbenches for top-level module
* - TODO: generate_spice_grid_testbench : generate SPICE testbenches for grids
* - TODO: generate_spice_cb_testbench : generate SPICE testbenches for connection blocks
* - TODO: generate_spice_sb_testbench : generate SPICE testbenches for switch blocks
* - TODO: generate_spice_lut_testbench : generate SPICE testbenches for Look-Up Tables
* - TODO: generate_spice_hard_logic_testbench : generate SPICE testbenches for all the hard logics
* - TODO: generate_spice_local_routing_testbench : generate SPICE testbenches for local routing
* - TODO: generate_spice_cb_routing_testbench : generate SPICE testbenches for routing circuit inside connection blocks
* - TODO: generate_spice_sb_routing_testbench : generate SPICE testbenches for routing circuit inside switch blocks
*******************************************************************/
#include "openfpga_spice.h"
#include "openfpga_spice_command.h"
/* begin namespace openfpga */
namespace openfpga {
/********************************************************************
* - Add a command to Shell environment: generate fabric Verilog
* - Add associated options
* - Add command dependency
*******************************************************************/
static
ShellCommandId add_openfpga_write_fabric_spice_command(openfpga::Shell<OpenfpgaContext>& shell,
const ShellCommandClassId& cmd_class_id,
const std::vector<ShellCommandId>& dependent_cmds) {
Command shell_cmd("write_fabric_spice");
/* Add an option '--file' in short '-f'*/
CommandOptionId output_opt = shell_cmd.add_option("file", true, "Specify the output directory for SPICE netlists");
shell_cmd.set_option_short_name(output_opt, "f");
shell_cmd.set_option_require_value(output_opt, openfpga::OPT_STRING);
/* Add an option '--explicit_port_mapping' */
shell_cmd.add_option("explicit_port_mapping", false, "Use explicit port mapping in Verilog netlists");
/* Add an option '--verbose' */
shell_cmd.add_option("verbose", false, "Enable verbose output");
/* Add command 'write_fabric_spice' to the Shell */
ShellCommandId shell_cmd_id = shell.add_command(shell_cmd, "generate SPICE netlists modeling full FPGA fabric");
shell.set_command_class(shell_cmd_id, cmd_class_id);
shell.set_command_execute_function(shell_cmd_id, write_fabric_spice);
/* Add command dependency to the Shell */
shell.set_command_dependency(shell_cmd_id, dependent_cmds);
return shell_cmd_id;
}
void add_openfpga_spice_commands(openfpga::Shell<OpenfpgaContext>& shell) {
/* Get the unique id of 'build_fabric' command which is to be used in creating the dependency graph */
const ShellCommandId& build_fabric_cmd_id = shell.command(std::string("build_fabric"));
/* Add a new class of commands */
ShellCommandClassId openfpga_spice_cmd_class = shell.add_command_class("FPGA-SPICE");
/********************************
* Command 'write_fabric_spice'
*/
/* The 'write_fabric_spice' command should NOT be executed before 'build_fabric' */
std::vector<ShellCommandId> fabric_spice_dependent_cmds;
fabric_spice_dependent_cmds.push_back(build_fabric_cmd_id);
add_openfpga_write_fabric_spice_command(shell,
openfpga_spice_cmd_class,
fabric_spice_dependent_cmds);
/********************************
* TODO: Command 'write_spice_top_testbench'
*/
/* The command 'write_spice_top_testbench' should NOT be executed before 'build_fabric' */
}
} /* end namespace openfpga */

View File

@ -0,0 +1,21 @@
#ifndef OPENFPGA_SPICE_COMMAND_H
#define OPENFPGA_SPICE_COMMAND_H
/********************************************************************
* Include header files that are required by function declaration
*******************************************************************/
#include "shell.h"
#include "openfpga_context.h"
/********************************************************************
* Function declaration
*******************************************************************/
/* begin namespace openfpga */
namespace openfpga {
void add_openfpga_spice_commands(openfpga::Shell<OpenfpgaContext>& shell);
} /* end namespace openfpga */
#endif

View File

@ -0,0 +1,59 @@
/******************************************************************************
* Memember functions for data structure FabricSpiceOption
******************************************************************************/
#include "vtr_assert.h"
#include "fabric_spice_options.h"
/* begin namespace openfpga */
namespace openfpga {
/**************************************************
* Public Constructors
*************************************************/
FabricSpiceOption::FabricSpiceOption() {
output_directory_.clear();
explicit_port_mapping_ = false;
compress_routing_ = false;
verbose_output_ = false;
}
/**************************************************
* Public Accessors
*************************************************/
std::string FabricSpiceOption::output_directory() const {
return output_directory_;
}
bool FabricSpiceOption::explicit_port_mapping() const {
return explicit_port_mapping_;
}
bool FabricSpiceOption::compress_routing() const {
return compress_routing_;
}
bool FabricSpiceOption::verbose_output() const {
return verbose_output_;
}
/******************************************************************************
* Private Mutators
******************************************************************************/
void FabricSpiceOption::set_output_directory(const std::string& output_dir) {
output_directory_ = output_dir;
}
void FabricSpiceOption::set_explicit_port_mapping(const bool& enabled) {
explicit_port_mapping_ = enabled;
}
void FabricSpiceOption::set_compress_routing(const bool& enabled) {
compress_routing_ = enabled;
}
void FabricSpiceOption::set_verbose_output(const bool& enabled) {
verbose_output_ = enabled;
}
} /* end namespace openfpga */

View File

@ -0,0 +1,38 @@
#ifndef FABRIC_SPICE_OPTIONS_H
#define FABRIC_SPICE_OPTIONS_H
/********************************************************************
* Include header files required by the data structure definition
*******************************************************************/
#include <string>
/* Begin namespace openfpga */
namespace openfpga {
/********************************************************************
* Options for Fabric Spice generator
*******************************************************************/
class FabricSpiceOption {
public: /* Public constructor */
/* Set default options */
FabricSpiceOption();
public: /* Public accessors */
std::string output_directory() const;
bool explicit_port_mapping() const;
bool compress_routing() const;
bool verbose_output() const;
public: /* Public mutators */
void set_output_directory(const std::string& output_dir);
void set_explicit_port_mapping(const bool& enabled);
void set_compress_routing(const bool& enabled);
void set_verbose_output(const bool& enabled);
private: /* Internal Data */
std::string output_directory_;
bool explicit_port_mapping_;
bool compress_routing_;
bool verbose_output_;
};
} /* End namespace openfpga*/
#endif

View File

@ -0,0 +1,76 @@
/********************************************************************
* This file include top-level function of FPGA-SPICE
********************************************************************/
/* Headers from vtrutil library */
#include "vtr_log.h"
#include "vtr_assert.h"
#include "vtr_time.h"
/* Headers from openfpgautil library */
#include "openfpga_digest.h"
#include "openfpga_reserved_words.h"
#include "spice_constants.h"
#include "spice_submodule.h"
/* Header file for this source file */
#include "spice_api.h"
/* begin namespace openfpga */
namespace openfpga {
/********************************************************************
* A top-level function of FPGA-SPICE which focuses on fabric Spice generation
* This function will generate
* - primitive modules required by the full fabric
* - which are LUTs, routing multiplexer, logic gates, transmission-gates etc.
* - Routing modules, which are Switch Blocks (SBs) and Connection Blocks (CBs)
* - Logic block modules, which are Configuration Logic Blocks (CLBs)
* - FPGA module, which are the full FPGA fabric with configuration protocol
*
* Note:
* - Please do NOT include ANY testbench generation in this function!!!
* It is about the fabric itself, independent from any implementation
* All the testbench generation should be in the function fpga_testbench_spice()
********************************************************************/
void fpga_fabric_spice(const ModuleManager &module_manager,
NetlistManager &netlist_manager,
const FabricSpiceOption &options) {
vtr::ScopedStartFinishTimer timer("Write SPICE netlists for FPGA fabric\n");
std::string src_dir_path = format_dir_path(options.output_directory());
/* Create directories */
create_directory(src_dir_path);
/* Sub directory under SRC directory to contain all the primitive block netlists */
std::string submodule_dir_path = src_dir_path + std::string(DEFAULT_SUBMODULE_DIR_NAME);
create_directory(submodule_dir_path);
/* Sub directory under SRC directory to contain all the logic block netlists */
std::string lb_dir_path = src_dir_path + std::string(DEFAULT_LB_DIR_NAME);
create_directory(lb_dir_path);
/* Sub directory under SRC directory to contain all the routing block netlists */
std::string rr_dir_path = src_dir_path + std::string(DEFAULT_RR_DIR_NAME);
create_directory(rr_dir_path);
/* Generate primitive Spice modules, which are corner stones of FPGA fabric
* Note that this function MUST be called before Spice generation of
* core logic (i.e., logic blocks and routing resources) !!!
* This is because that this function will add the primitive Spice modules to
* the module manager.
* Without the modules in the module manager, core logic generation is not possible!!!
*/
print_spice_submodule(netlist_manager,
submodule_dir_path);
/* Given a brief stats on how many Spice modules have been written to files */
VTR_LOGV(options.verbose_output(),
"Written %lu SPICE modules in total\n",
module_manager.num_modules());
}
} /* end namespace openfpga */

View File

@ -0,0 +1,27 @@
#ifndef SPICE_API_H
#define SPICE_API_H
/********************************************************************
* Include header files that are required by function declaration
*******************************************************************/
#include <string>
#include <vector>
#include "netlist_manager.h"
#include "module_manager.h"
#include "fabric_spice_options.h"
/********************************************************************
* Function declaration
*******************************************************************/
/* begin namespace openfpga */
namespace openfpga {
void fpga_fabric_spice(const ModuleManager& module_manager,
NetlistManager& netlist_manager,
const FabricSpiceOption& options);
} /* end namespace openfpga */
#endif

View File

@ -0,0 +1,11 @@
#ifndef SPICE_CONSTANTS_H
#define SPICE_CONSTANTS_H
/* global parameters for dumping spice netlists */
constexpr char* SPICE_NETLIST_FILE_POSTFIX = ".sp";
constexpr char* TRANSISTORS_SPICE_FILE_NAME = "transistor.sp";
constexpr char* ESSENTIALS_SPICE_FILE_NAME = "inv_buf_passgate.sp";
#endif

View File

@ -0,0 +1,51 @@
/************************************************
* This file includes functions on
* outputting Verilog netlists for essential gates
* which are inverters, buffers, transmission-gates
* logic gates etc.
***********************************************/
#include <fstream>
/* Headers from vtrutil library */
#include "vtr_assert.h"
#include "vtr_log.h"
/* Headers from openfpgautil library */
#include "openfpga_digest.h"
#include "spice_constants.h"
#include "spice_essential_gates.h"
/* begin namespace openfpga */
namespace openfpga {
/************************************************
* Generate the SPICE netlist for transistors
***********************************************/
void print_spice_transistor_wrapper(NetlistManager& netlist_manager,
const std::string& submodule_dir) {
std::string spice_fname = submodule_dir + std::string(ESSENTIALS_SPICE_FILE_NAME);
std::fstream fp;
/* Create the file stream */
fp.open(spice_fname, std::fstream::out | std::fstream::trunc);
/* Check if the file stream if valid or not */
check_file_stream(spice_fname.c_str(), fp);
/* Create file */
VTR_LOG("Generating SPICE netlist '%s' for transistor wrappers...",
spice_fname.c_str());
/* Close file handler*/
fp.close();
/* Add fname to the netlist name list */
NetlistId nlist_id = netlist_manager.add_netlist(spice_fname);
VTR_ASSERT(NetlistId::INVALID() != nlist_id);
netlist_manager.set_netlist_type(nlist_id, NetlistManager::SUBMODULE_NETLIST);
VTR_LOG("Done\n");
}
} /* end namespace openfpga */

View File

@ -0,0 +1,22 @@
#ifndef SPICE_ESSENTIAL_GATES_H
#define SPICE_ESSENTIAL_GATES_H
/********************************************************************
* Include header files that are required by function declaration
*******************************************************************/
#include <string>
#include "netlist_manager.h"
/********************************************************************
* Function declaration
*******************************************************************/
/* begin namespace openfpga */
namespace openfpga {
void print_spice_transistor_wrapper(NetlistManager& netlist_manager,
const std::string& submodule_dir);
} /* end namespace openfpga */
#endif

View File

@ -0,0 +1,34 @@
/*********************************************************************
* This file includes top-level function to generate Spice primitive modules
* and print them to files
********************************************************************/
/* Headers from vtrutil library */
#include "vtr_assert.h"
#include "vtr_log.h"
#include "spice_essential_gates.h"
#include "spice_constants.h"
#include "spice_submodule.h"
/* begin namespace openfpga */
namespace openfpga {
/*********************************************************************
* Top-level function to generate primitive modules:
* 1. Transistor wrapper
* 2. TODO: Logic gates: AND/OR, inverter, buffer and transmission-gate/pass-transistor
* 3. TODO: Routing multiplexers
* 4. TODO: Local encoders for routing multiplexers
* 5. TODO: Wires
* 6. TODO: Configuration memory blocks
********************************************************************/
void print_spice_submodule(NetlistManager& netlist_manager,
const std::string& submodule_dir) {
print_spice_transistor_wrapper(netlist_manager,
submodule_dir);
}
} /* end namespace openfpga */

View File

@ -0,0 +1,21 @@
#ifndef SPICE_SUBMODULE_H
#define SPICE_SUBMODULE_H
/********************************************************************
* Include header files that are required by function declaration
*******************************************************************/
#include "netlist_manager.h"
/********************************************************************
* Function declaration
*******************************************************************/
/* begin namespace openfpga */
namespace openfpga {
void print_spice_submodule(NetlistManager& netlist_manager,
const std::string& submodule_dir);
} /* end namespace openfpga */
#endif

View File

@ -15,6 +15,7 @@
#include "openfpga_setup_command.h" #include "openfpga_setup_command.h"
#include "openfpga_verilog_command.h" #include "openfpga_verilog_command.h"
#include "openfpga_bitstream_command.h" #include "openfpga_bitstream_command.h"
#include "openfpga_spice_command.h"
#include "openfpga_sdc_command.h" #include "openfpga_sdc_command.h"
#include "basic_command.h" #include "basic_command.h"
@ -63,6 +64,9 @@ int main(int argc, char** argv) {
/* Add openfpga bitstream commands */ /* Add openfpga bitstream commands */
openfpga::add_openfpga_bitstream_commands(shell); openfpga::add_openfpga_bitstream_commands(shell);
/* Add openfpga SPICE commands */
openfpga::add_openfpga_spice_commands(shell);
/* Add openfpga sdc commands */ /* Add openfpga sdc commands */
openfpga::add_openfpga_sdc_commands(shell); openfpga::add_openfpga_sdc_commands(shell);