[FPGA-SPICE] Add SPICE writer for routing multiplexers

This commit is contained in:
tangxifan 2020-09-20 11:49:02 -06:00
parent c7e3d97d1b
commit 0f9fce92b2
8 changed files with 234 additions and 3 deletions

View File

@ -40,6 +40,7 @@ int write_fabric_spice(OpenfpgaContext& openfpga_ctx,
status = fpga_fabric_spice(openfpga_ctx.module_graph(),
openfpga_ctx.mutable_spice_netlists(),
openfpga_ctx.arch(),
openfpga_ctx.mux_lib(),
options);
return status;

View File

@ -40,6 +40,7 @@ namespace openfpga {
int fpga_fabric_spice(const ModuleManager& module_manager,
NetlistManager& netlist_manager,
const Arch& openfpga_arch,
const MuxLibrary& mux_lib,
const FabricSpiceOption& options) {
vtr::ScopedStartFinishTimer timer("Write SPICE netlists for FPGA fabric\n");
@ -73,6 +74,7 @@ int fpga_fabric_spice(const ModuleManager& module_manager,
status = print_spice_submodule(netlist_manager,
module_manager,
openfpga_arch,
mux_lib,
submodule_dir_path);
if (CMD_EXEC_SUCCESS != status) {

View File

@ -10,6 +10,7 @@
#include "netlist_manager.h"
#include "module_manager.h"
#include "openfpga_arch.h"
#include "mux_library.h"
#include "fabric_spice_options.h"
/********************************************************************
@ -22,6 +23,7 @@ namespace openfpga {
int fpga_fabric_spice(const ModuleManager& module_manager,
NetlistManager& netlist_manager,
const Arch& openfpga_arch,
const MuxLibrary& mux_lib,
const FabricSpiceOption& options);
} /* end namespace openfpga */

View File

@ -9,8 +9,12 @@ constexpr char* TRANSISTOR_WRAPPER_POSTFIX = "_wrapper";
constexpr char* TRANSISTORS_SPICE_FILE_NAME = "transistor.sp";
constexpr char* SUPPLY_WRAPPER_SPICE_FILE_NAME = "supply_wrapper.sp";
constexpr char* MUXES_SPICE_FILE_NAME = "muxes.sp";
constexpr char* SPICE_SUBCKT_VDD_PORT_NAME = "VDD";
constexpr char* SPICE_SUBCKT_GND_PORT_NAME = "VSS";
constexpr char* SPICE_MUX_BASIS_POSTFIX = "_basis";
constexpr char* SPICE_MEM_POSTFIX = "_mem";
#endif

View File

@ -0,0 +1,189 @@
/***********************************************
* This file includes functions to generate
* SPICE subcircuits for multiplexers.
* including both fundamental submodules
* such as a branch in a multiplexer
* and the full multiplexer
**********************************************/
#include <string>
#include <algorithm>
/* Headers from vtrutil library */
#include "vtr_assert.h"
#include "vtr_log.h"
/* Headers from readarch library */
#include "physical_types.h"
/* Headers from readarcopenfpga library */
#include "circuit_types.h"
/* Headers from openfpgautil library */
#include "openfpga_digest.h"
/* Headers from openfpgashell library */
#include "command_exit_codes.h"
#include "mux_graph.h"
#include "module_manager.h"
#include "mux_utils.h"
#include "circuit_library_utils.h"
#include "decoder_library_utils.h"
#include "openfpga_naming.h"
#include "spice_constants.h"
#include "spice_writer_utils.h"
#include "spice_subckt_writer.h"
#include "spice_mux.h"
/* begin namespace openfpga */
namespace openfpga {
/***********************************************
* Generate SPICE modeling for an branch circuit
* for a multiplexer with the given size
**********************************************/
static
void generate_spice_mux_branch_subckt(const ModuleManager& module_manager,
const CircuitLibrary& circuit_lib,
std::fstream& fp,
const CircuitModelId& mux_model,
const size_t& mux_size,
const MuxGraph& mux_graph) {
std::string module_name = generate_mux_branch_subckt_name(circuit_lib, mux_model, mux_size, mux_graph.num_inputs(), SPICE_MUX_BASIS_POSTFIX);
/* Multiplexers built with different technology is in different organization */
switch (circuit_lib.design_tech_type(mux_model)) {
case CIRCUIT_MODEL_DESIGN_CMOS: {
/* Skip module writing if the branch subckt is a standard cell! */
if (true == circuit_lib.valid_model_id(circuit_lib.model(module_name))) {
/* This model must be a MUX2 gate */
VTR_ASSERT(CIRCUIT_MODEL_GATE == circuit_lib.model_type(circuit_lib.model(module_name)));
VTR_ASSERT(CIRCUIT_MODEL_GATE_MUX2 == circuit_lib.gate_type(circuit_lib.model(module_name)));
break;
}
/* Structural verilog can be easily generated by module writer */
ModuleId mux_module = module_manager.find_module(module_name);
VTR_ASSERT(true == module_manager.valid_module_id(mux_module));
write_spice_subckt_to_file(fp, module_manager, mux_module);
/* Add an empty line as a splitter */
fp << std::endl;
break;
}
case CIRCUIT_MODEL_DESIGN_RRAM:
/* TODO: RRAM-based Multiplexer SPICE module generation */
VTR_LOGF_ERROR(__FILE__, __LINE__,
"RRAM multiplexer '%s' is not supported yet\n",
circuit_lib.model_name(mux_model).c_str());
exit(1);
break;
default:
VTR_LOGF_ERROR(__FILE__, __LINE__,
"Invalid design technology of multiplexer '%s'\n",
circuit_lib.model_name(mux_model).c_str());
exit(1);
}
}
/***********************************************
* Generate SPICE modeling for a multiplexer
* with the given graph-level description
**********************************************/
static
void generate_spice_mux_subckt(const ModuleManager& module_manager,
const CircuitLibrary& circuit_lib,
std::fstream& fp,
const CircuitModelId& mux_model,
const MuxGraph& mux_graph) {
std::string module_name = generate_mux_subckt_name(circuit_lib, mux_model,
find_mux_num_datapath_inputs(circuit_lib, mux_model, mux_graph.num_inputs()),
std::string(""));
/* Multiplexers built with different technology is in different organization */
switch (circuit_lib.design_tech_type(mux_model)) {
case CIRCUIT_MODEL_DESIGN_CMOS: {
/* Use Verilog writer to print the module to file */
ModuleId mux_module = module_manager.find_module(module_name);
VTR_ASSERT(true == module_manager.valid_module_id(mux_module));
write_spice_subckt_to_file(fp, module_manager, mux_module);
/* Add an empty line as a splitter */
fp << std::endl;
break;
}
case CIRCUIT_MODEL_DESIGN_RRAM:
/* TODO: RRAM-based Multiplexer SPICE module generation */
VTR_LOGF_ERROR(__FILE__, __LINE__,
"RRAM multiplexer '%s' is not supported yet\n",
circuit_lib.model_name(mux_model).c_str());
exit(1);
break;
default:
VTR_LOGF_ERROR(__FILE__, __LINE__,
"Invalid design technology of multiplexer '%s'\n",
circuit_lib.model_name(mux_model).c_str());
exit(1);
}
}
/***********************************************
* Generate SPICE subcircuits for all the unique
* multiplexers in the FPGA device
**********************************************/
int print_spice_submodule_muxes(NetlistManager& netlist_manager,
const ModuleManager& module_manager,
const MuxLibrary& mux_lib,
const CircuitLibrary& circuit_lib,
const std::string& submodule_dir) {
int status = CMD_EXEC_SUCCESS;
std::string spice_fname(submodule_dir + std::string(MUXES_SPICE_FILE_NAME));
/* Create the file stream */
std::fstream fp;
fp.open(spice_fname, std::fstream::out | std::fstream::trunc);
check_file_stream(spice_fname.c_str(), fp);
/* Print out debugging information for if the file is not opened/created properly */
VTR_LOG("Writing SPICE netlist for Multiplexers '%s' ...",
spice_fname.c_str());
print_spice_file_header(fp, "Multiplexers");
/* Generate basis sub-circuit for unique branches shared by the multiplexers */
for (auto mux : mux_lib.muxes()) {
const MuxGraph& mux_graph = mux_lib.mux_graph(mux);
CircuitModelId mux_circuit_model = mux_lib.mux_circuit_model(mux);
/* Create a mux graph for the branch circuit */
std::vector<MuxGraph> branch_mux_graphs = mux_graph.build_mux_branch_graphs();
/* Create branch circuits, which are N:1 one-level or 2:1 tree-like MUXes */
for (auto branch_mux_graph : branch_mux_graphs) {
generate_spice_mux_branch_subckt(module_manager, circuit_lib, fp, mux_circuit_model,
find_mux_num_datapath_inputs(circuit_lib, mux_circuit_model, mux_graph.num_inputs()),
branch_mux_graph);
}
}
/* Generate unique Verilog modules for the multiplexers */
for (auto mux : mux_lib.muxes()) {
const MuxGraph& mux_graph = mux_lib.mux_graph(mux);
CircuitModelId mux_circuit_model = mux_lib.mux_circuit_model(mux);
/* Create MUX circuits */
generate_spice_mux_subckt(module_manager, circuit_lib, fp, mux_circuit_model, mux_graph);
}
/* Close the file stream */
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");
return status;
}
} /* end namespace openfpga */

View File

@ -0,0 +1,31 @@
#ifndef SPICE_MUX_H
#define SPICE_MUX_H
/********************************************************************
* Include header files that are required by function declaration
*******************************************************************/
#include <fstream>
#include <vector>
#include "circuit_library.h"
#include "mux_graph.h"
#include "mux_library.h"
#include "module_manager.h"
#include "netlist_manager.h"
/********************************************************************
* Function declaration
*******************************************************************/
/* begin namespace openfpga */
namespace openfpga {
int print_spice_submodule_muxes(NetlistManager& netlist_manager,
const ModuleManager& module_manager,
const MuxLibrary& mux_lib,
const CircuitLibrary& circuit_lib,
const std::string& submodule_dir);
} /* end namespace openfpga */
#endif

View File

@ -1,5 +1,5 @@
/*********************************************************************
* This file includes top-level function to generate Spice primitive modules
* This file includes top-level function to generate SPICE primitive modules
* and print them to files
********************************************************************/
@ -12,6 +12,7 @@
#include "spice_transistor_wrapper.h"
#include "spice_essential_gates.h"
#include "spice_mux.h"
#include "spice_constants.h"
#include "spice_submodule.h"
@ -31,6 +32,7 @@ namespace openfpga {
int print_spice_submodule(NetlistManager& netlist_manager,
const ModuleManager& module_manager,
const Arch& openfpga_arch,
const MuxLibrary& mux_lib,
const std::string& submodule_dir) {
int status = CMD_EXEC_SUCCESS;
@ -74,13 +76,11 @@ int print_spice_submodule(NetlistManager& netlist_manager,
}
/* Routing multiplexers */
/*
status = print_spice_submodule_muxes(netlist_manager,
module_manager,
mux_lib,
openfpga_arch.circuit_lib,
submodule_dir);
*/
/* Error out if fatal errors have been reported */
if (CMD_EXEC_SUCCESS != status) {

View File

@ -7,6 +7,7 @@
#include "netlist_manager.h"
#include "module_manager.h"
#include "openfpga_arch.h"
#include "mux_library.h"
/********************************************************************
* Function declaration
@ -18,6 +19,7 @@ namespace openfpga {
int print_spice_submodule(NetlistManager& netlist_manager,
const ModuleManager& module_manager,
const Arch& openfpga_arch,
const MuxLibrary& mux_lib,
const std::string& submodule_dir);
} /* end namespace openfpga */