add spice writer functions

This commit is contained in:
tangxifan 2020-07-05 13:58:05 -06:00
parent 81171a8f97
commit b38ee0e8be
2 changed files with 204 additions and 0 deletions

View File

@ -0,0 +1,152 @@
/************************************************
* Include functions for most frequently
* used Spice writers
***********************************************/
#include <chrono>
#include <ctime>
#include <string>
#include <fstream>
#include <iomanip>
/* Headers from vtrutil library */
#include "vtr_assert.h"
#include "vtr_log.h"
/* Headers from readarchopenfpga library */
#include "circuit_types.h"
/* Headers from openfpgautil library */
#include "openfpga_digest.h"
#include "spice_writer_utils.h"
/* begin namespace openfpga */
namespace openfpga {
/************************************************
* Generate header comments for a Spice netlist
* include the description
***********************************************/
void print_spice_file_header(std::fstream& fp,
const std::string& usage) {
VTR_ASSERT(true == valid_file_stream(fp));
auto end = std::chrono::system_clock::now();
std::time_t end_time = std::chrono::system_clock::to_time_t(end);
fp << "*********************************************" << std::endl;
fp << "*\tFPGA-SPICE Netlist" << std::endl;
fp << "*\tDescription: " << usage << std::endl;
fp << "*\tAuthor: Xifan TANG" << std::endl;
fp << "*\tOrganization: University of Utah" << std::endl;
fp << "*\tDate: " << std::ctime(&end_time) ;
fp << "*********************************************" << std::endl;
fp << std::endl;
}
/********************************************************************
* Print Spice codes to include a netlist
*******************************************************************/
void print_spice_include_netlist(std::fstream& fp,
const std::string& netlist_name) {
VTR_ASSERT(true == valid_file_stream(fp));
fp << ".include \"" << netlist_name << "\"" << std::endl;
}
/************************************************
* Print a Spice comment line
***********************************************/
void print_spice_comment(std::fstream& fp,
const std::string& comment) {
VTR_ASSERT(true == valid_file_stream(fp));
std::string comment_cover(comment.length() + 4, '*');
fp << comment_cover << std::endl;
fp << "* " << comment << " *" << std::endl;
fp << comment_cover << std::endl;
}
/************************************************
* Generate a string for a port in SPICE format
***********************************************/
std::string generate_spice_port(const BasicPort& port) {
VTR_ASSERT(1 == port.get_width());
std::string ret = port.get_name();
ret += "[";
ret += std::to_string(port.get_lsb());
ret += "]";
return ret;
}
/************************************************
* Print a SPICE subckt definition
* We use the following format:
* module <module_name> (<ports without directions>);
***********************************************/
void print_spice_subckt_definition(std::fstream& fp,
const ModuleManager& module_manager, const ModuleId& module_id) {
VTR_ASSERT(true == valid_file_stream(fp));
print_spice_comment(fp, std::string("SPICE module for " + module_manager.module_name(module_id)));
std::string module_head_line = ".subckt " + module_manager.module_name(module_id) + " ";
fp << module_head_line;
/* Port sequence: global, inout, input, output and clock ports, */
bool new_line = false;
size_t pin_cnt = 0;
for (int port_type = ModuleManager::MODULE_GLOBAL_PORT;
port_type < ModuleManager::NUM_MODULE_PORT_TYPES;
++port_type) {
for (const auto& port : module_manager.module_ports_by_type(module_id, static_cast<ModuleManager::e_module_port_type>(port_type))) {
ModulePortId port_id = module_manager.find_module_port(module_id, port.get_name());
VTR_ASSERT(ModulePortId::INVALID() != port_id);
/* Print port: only the port name is enough */
for (const auto& pin : port.pins()) {
if (true == new_line) {
std::string port_whitespace(module_head_line.length() - 2, ' ');
fp << "+ " << port_whitespace;
}
if (0 != pin_cnt) {
write_space_to_file(fp, 1);
}
BasicPort port_pin(port.get_name(), pin, pin);
fp << generate_spice_port(port_pin);
/* Increase the counter */
pin_cnt++;
/* Currently we limit 10 ports per line to keep a clean netlist */
new_line = false;
if (10 == pin_cnt) {
pin_cnt = 0;
fp << std::endl;
new_line = true;
}
}
}
}
fp << std::endl;
}
/************************************************
* Print an end line for a Spice module
***********************************************/
void print_spice_subckt_end(std::fstream& fp,
const std::string& module_name) {
VTR_ASSERT(true == valid_file_stream(fp));
fp << ".ends" << std::endl;
print_spice_comment(fp, std::string("***** END SPICE module for " + module_name + " *****"));
fp << std::endl;
}
} /* end namespace openfpga */

View File

@ -0,0 +1,52 @@
/************************************************
* Header file for spice_writer_utils.cpp
* Include function declaration for most frequently
* used Verilog writers
***********************************************/
#ifndef SPICE_WRITER_UTILS_H
#define SPICE_WRITER_UTILS_H
/********************************************************************
* Include header files that are required by function declaration
*******************************************************************/
#include <fstream>
#include <vector>
#include <string>
#include "openfpga_port.h"
#include "circuit_library.h"
#include "module_manager.h"
/********************************************************************
* Function declaration
*******************************************************************/
/* begin namespace openfpga */
namespace openfpga {
/* Tips: for naming your function in this header/source file
* If a function outputs to a file, its name should begin with "print_spice"
* If a function creates a string without outputting to a file, its name should begin with "generate_spice"
* Please show respect to this naming convention, in order to keep a clean header/source file
* as well maintain a easy way to identify the functions
*/
void print_spice_file_header(std::fstream& fp,
const std::string& usage);
void print_spice_include_netlist(std::fstream& fp,
const std::string& netlist_name);
void print_spice_comment(std::fstream& fp,
const std::string& comment);
std::string generate_spice_port(const BasicPort& port);
void print_spice_subckt_definition(std::fstream& fp,
const ModuleManager& module_manager, const ModuleId& module_id);
void print_spice_subckt_end(std::fstream& fp,
const std::string& module_name);
} /* end namespace openfpga */
#endif