diff --git a/openfpga_flow/tasks/basic_flow/latest b/openfpga_flow/tasks/basic_flow/latest index 9407a80a8..92a41ae5e 120000 --- a/openfpga_flow/tasks/basic_flow/latest +++ b/openfpga_flow/tasks/basic_flow/latest @@ -1 +1 @@ -run002 \ No newline at end of file +run003 \ No newline at end of file diff --git a/vpr7_x2p/libarchfpga/SRC/check_circuit_library.cpp b/vpr7_x2p/libarchfpga/SRC/check_circuit_library.cpp index 8fc98cc50..b39925326 100644 --- a/vpr7_x2p/libarchfpga/SRC/check_circuit_library.cpp +++ b/vpr7_x2p/libarchfpga/SRC/check_circuit_library.cpp @@ -202,7 +202,7 @@ size_t check_one_circuit_model_port_type_and_size_required(const CircuitLibrary& size_t num_err = 0; - std::vector ports = circuit_lib.model_ports_by_type(circuit_model, port_type_to_check, include_global_ports); + std::vector ports = circuit_lib.model_ports_by_type(circuit_model, port_type_to_check, false == include_global_ports); if (num_ports_to_check != ports.size()) { vpr_printf(TIO_MESSAGE_ERROR, "Expect %d %s ports for a %s circuit model, but only have %d %s ports!\n", diff --git a/vpr7_x2p/libarchfpga/SRC/circuit_library.cpp b/vpr7_x2p/libarchfpga/SRC/circuit_library.cpp index 1e45f5b7f..21466c998 100644 --- a/vpr7_x2p/libarchfpga/SRC/circuit_library.cpp +++ b/vpr7_x2p/libarchfpga/SRC/circuit_library.cpp @@ -352,6 +352,30 @@ std::vector CircuitLibrary::model_global_ports(const CircuitModel return global_ports; } +/* Recursively find all the global ports in the circuit model / sub circuit_model */ +std::vector CircuitLibrary::model_global_ports_by_type(const CircuitModelId& model_id, + const enum e_spice_model_port_type& type) const { + /* validate the model_id */ + VTR_ASSERT(valid_model_id(model_id)); + + /* Search all the ports */ + std::vector global_ports; + for (auto port : model_ports(model_id)) { + /* By pass non-global ports*/ + if (false == port_is_global(port)) { + continue; + } + /* We skip unmatched ports */ + if ( type != port_type(port) ) { + continue; + } + /* This is a global port, update global_ports */ + global_ports.push_back(port); + } + + return global_ports; +} + /* Find the ports of a circuit model by a given type, return a list of qualified ports */ std::vector CircuitLibrary::model_ports_by_type(const CircuitModelId& model_id, const enum e_spice_model_port_type& type) const { @@ -371,7 +395,7 @@ std::vector CircuitLibrary::model_ports_by_type(const CircuitMode */ std::vector CircuitLibrary::model_ports_by_type(const CircuitModelId& model_id, const enum e_spice_model_port_type& type, - const bool& include_global_port) const { + const bool& ignore_global_port) const { std::vector port_ids; for (const auto& port_id : model_port_lookup_[model_id][type]) { /* We skip unmatched ports */ @@ -379,7 +403,7 @@ std::vector CircuitLibrary::model_ports_by_type(const CircuitMode continue; } /* We skip global ports if specified */ - if ( (false == include_global_port) + if ( (true == ignore_global_port) && (true == port_is_global(port_id)) ) { continue; } @@ -388,7 +412,6 @@ std::vector CircuitLibrary::model_ports_by_type(const CircuitMode return port_ids; } - /* Create a vector for all the ports whose directionality is input * This includes all the ports other than whose types are OUPUT or INOUT */ diff --git a/vpr7_x2p/libarchfpga/SRC/circuit_library.h b/vpr7_x2p/libarchfpga/SRC/circuit_library.h index 72172bf30..2c4aa42d5 100644 --- a/vpr7_x2p/libarchfpga/SRC/circuit_library.h +++ b/vpr7_x2p/libarchfpga/SRC/circuit_library.h @@ -233,6 +233,8 @@ class CircuitLibrary { size_t num_model_ports_by_type(const CircuitModelId& model_id, const enum e_spice_model_port_type& port_type, const bool& include_global_port) const; std::vector model_ports(const CircuitModelId& model_id) const; std::vector model_global_ports(const CircuitModelId& model_id) const; + std::vector model_global_ports_by_type(const CircuitModelId& model_id, + const enum e_spice_model_port_type& type) const; std::vector model_ports_by_type(const CircuitModelId& model_id, const enum e_spice_model_port_type& port_type) const; std::vector model_ports_by_type(const CircuitModelId& model_id, const enum e_spice_model_port_type& port_type, const bool& include_global_port) const; std::vector model_input_ports(const CircuitModelId& model_id) const; diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_naming.cpp b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_naming.cpp new file mode 100644 index 000000000..0881d5221 --- /dev/null +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_naming.cpp @@ -0,0 +1,43 @@ +/************************************************ + * This file includes functions to + * generate module/port names for Verilog + * and SPICE netlists + ***********************************************/ +#include "vtr_assert.h" + +#include "fpga_x2p_naming.h" + +/************************************************ + * Generate the module name for a multiplexer in Verilog format + ***********************************************/ +std::string generate_verilog_mux_subckt_name(const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model, + const size_t& mux_size, + const std::string& postfix) { + std::string module_name = circuit_lib.model_name(circuit_model); + module_name += "_size"; + module_name += std::to_string(mux_size); + module_name += postfix; + + return module_name; +} + +/************************************************ + * Generate the module name of a branch for a + * multiplexer in Verilog format + ***********************************************/ +std::string generate_verilog_mux_branch_subckt_name(const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model, + const size_t& mux_size, + const std::string& postfix) { + /* If the tgate spice model of this MUX is a MUX2 standard cell, + * the mux_subckt name will be the name of the standard cell + */ + CircuitModelId subckt_model = circuit_lib.pass_gate_logic_model(circuit_model); + if (SPICE_MODEL_GATE == circuit_lib.model_type(subckt_model)) { + VTR_ASSERT (SPICE_MODEL_GATE_MUX2 == circuit_lib.gate_type(subckt_model)); + return circuit_lib.model_name(subckt_model); + } + + return generate_verilog_mux_subckt_name(circuit_lib, circuit_model, mux_size, postfix); +} diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_naming.h b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_naming.h new file mode 100644 index 000000000..ff91f4854 --- /dev/null +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_naming.h @@ -0,0 +1,24 @@ +/************************************************ + * Header file for fpga_x2p_naming.cpp + * Include functions to generate module/port names + * for Verilog and SPICE netlists + ***********************************************/ + +#ifndef FPGA_X2P_NAMING_H +#define FPGA_X2P_NAMING_H + +#include + +#include "circuit_library.h" + +std::string generate_verilog_mux_subckt_name(const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model, + const size_t& mux_size, + const std::string& posfix) ; + +std::string generate_verilog_mux_branch_subckt_name(const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model, + const size_t& mux_size, + const std::string& posfix); + +#endif diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_utils.c b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_utils.c index a3611a7a4..53faf3ad7 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_utils.c +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_utils.c @@ -12,6 +12,7 @@ #include #include #include +#include /* Include vpr structs*/ #include "util.h" @@ -63,6 +64,7 @@ char* my_gettime() { return c_time_string; } + char* format_dir_path(char* dir_path) { int len = strlen(dir_path); /* String length without the last "\0"*/ int i; @@ -82,6 +84,26 @@ char* format_dir_path(char* dir_path) { return ret; } +/************************************************ + * Format a path of directory: + * 1. Replace "\" with "/" + * 2. add a "/" if the string does not end with a "/" + ***********************************************/ +std::string format_dir_path(const std::string& dir_path) { + std::string ret = dir_path; + + /* Replace "\" with "/" */ + std::replace(ret.begin(), ret.end(), '\\', '/'); + + /* Complete the string with a "/" if it does not end with that */ + if ('/' != ret.back()) { + ret.push_back('/'); + } + + return ret; +} + + int try_access_file(char* file_path) { /* F_OK checks existence and also R_OK, W_OK, X_OK, * for readable, writable, excutable @@ -3228,7 +3250,7 @@ int count_cb_info_num_ipin_rr_nodes(t_cb cur_cb_info) { /* Add a subckt file name to a linked list */ t_llist* add_one_subckt_file_name_to_llist(t_llist* cur_head, - char* subckt_file_path) { + const char* subckt_file_path) { t_llist* new_head = NULL; if (NULL == cur_head) { diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_utils.h b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_utils.h index 1f7fc9c4e..1a518f439 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_utils.h +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_utils.h @@ -10,7 +10,8 @@ void check_file_handler(std::fstream& fp); char* my_gettime(); -char* format_dir_path(char* dir_path); +char* format_dir_path(char* dir_path); /* TODO: TO BE REMOVED !!! */ +std::string format_dir_path(const std::string& dir_path); int try_access_file(char* file_path); @@ -380,7 +381,7 @@ boolean is_cb_exist(t_rr_type cb_type, int count_cb_info_num_ipin_rr_nodes(t_cb cur_cb_info); t_llist* add_one_subckt_file_name_to_llist(t_llist* cur_head, - char* subckt_file_path); + const char* subckt_file_path); boolean check_subckt_file_exist_in_llist(t_llist* subckt_llist_head, char* subckt_file_name); diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_submodule_essential.cpp b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_submodule_essential.cpp index f291690bb..c04dcd042 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_submodule_essential.cpp +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_submodule_essential.cpp @@ -16,12 +16,253 @@ /* FPGA-Verilog context header files */ #include "verilog_global.h" +#include "verilog_writer_utils.h" #include "verilog_submodule_essential.h" -void dump_verilog_submodule_essentials(const std::string& verilog_dir, - const std::string& submodule_dir, - const CircuitLibrary& circuit_lib) { - std::string verilog_fname = submodule_dir + essentials_verilog_file_name; + +/************************************************ + * Print a Verilog module of inverter or buffer + * or tapered buffer to a file + ***********************************************/ +static +void print_verilog_invbuf_module(std::fstream& fp, + const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model) { + /* Ensure a valid file handler*/ + check_file_handler(fp); + + fp << "//----- Verilog module for " << circuit_lib.model_name(circuit_model) << " -----" << std::endl; + + /* Find the input port, output port and global inputs*/ + std::vector input_ports = circuit_lib.model_ports_by_type(circuit_model, SPICE_MODEL_PORT_INPUT, true); + std::vector output_ports = circuit_lib.model_ports_by_type(circuit_model, SPICE_MODEL_PORT_OUTPUT, true); + std::vector global_ports = circuit_lib.model_global_ports_by_type(circuit_model, SPICE_MODEL_PORT_INPUT); + + /* Make sure: + * There is only 1 input port and 1 output port, + * each size of which is 1 + */ + VTR_ASSERT( (1 == input_ports.size()) && (1 == circuit_lib.port_size(input_ports[0])) ); + VTR_ASSERT( (1 == output_ports.size()) && (1 == circuit_lib.port_size(output_ports[0])) ); + + /* TODO: move the check codes to check_circuit_library.h */ + /* If the circuit model is power-gated, we need to find at least one global config_enable signals */ + if (true == circuit_lib.is_power_gated(circuit_model)) { + /* Check all the ports we have are good for a power-gated circuit model */ + size_t num_err = 0; + /* We need at least one global port */ + if (0 == global_ports.size()) { + num_err++; + } + /* All the global ports should be config_enable */ + for (const auto& port : global_ports) { + if (false == circuit_lib.port_is_config_enable(port)) { + num_err++; + } + } + /* Report errors if there are any */ + if (0 < num_err) { + vpr_printf(TIO_MESSAGE_ERROR, + "Inverter/buffer circuit model (name=%s) is power-gated. At least one config-enable global port is required!\n", + circuit_lib.model_name(circuit_model).c_str()); + exit(1); + } + } + + /* dump module body */ + fp << "module " << circuit_lib.model_name(circuit_model) << " (" << std::endl; + + /* TODO: print global ports */ + for (const auto& port : global_ports) { + BasicPort basic_port; + /* Configure each input port */ + basic_port.set_name(circuit_lib.port_prefix(port)); + basic_port.set_width(circuit_lib.port_size(port)); + /* Print port */ + fp << "\t" << generate_verilog_port(VERILOG_PORT_INPUT, basic_port) << "," << std::endl; + } + + /* Dump ports */ + BasicPort input_port; + /* Configure each input port */ + input_port.set_name(circuit_lib.port_lib_name(input_ports[0])); + input_port.set_width(circuit_lib.port_size(input_ports[0])); + fp << "\t" << generate_verilog_port(VERILOG_PORT_INPUT, input_port) << "," << std::endl; + + BasicPort output_port; + /* Configure each input port */ + output_port.set_name(circuit_lib.port_lib_name(output_ports[0])); + output_port.set_width(circuit_lib.port_size(output_ports[0])); + fp << "\t" << generate_verilog_port(VERILOG_PORT_OUTPUT, output_port) << "," << std::endl; + fp << ");" << std::endl; + /* Finish dumping ports */ + +// /* Assign logics : depending on topology */ +// switch (invbuf_spice_model->design_tech_info.buffer_info->type) { +// case SPICE_MODEL_BUF_INV: +// if (TRUE == invbuf_spice_model->design_tech_info.power_gated) { +// /* Create a sensitive list */ +// fprintf(fp, "reg %s_reg;\n", output_port[0]->lib_name); +// fprintf(fp, "always @("); +// /* Power-gate port first*/ +// for (iport = 0; iport < num_powergate_port; iport++) { +// fprintf(fp, "%s,", powergate_port[iport]->lib_name); +// } +// fprintf(fp, "%s) begin\n", +// input_port[0]->lib_name); +// /* Dump the case of power-gated */ +// fprintf(fp, " if ("); +// port_cnt = 0; /* Initialize the counter: decide if we need to put down '&&' */ +// for (iport = 0; iport < num_powergate_port; iport++) { +// if (0 == powergate_port[iport]->default_val) { +// for (ipin = 0; ipin < powergate_port[iport]->size; ipin++) { +// if ( 0 < port_cnt ) { +// fprintf(fp, "\n\t&&"); +// } +// /* Power-gated signal are disable during operating, enabled during configuration, +// * Therefore, we need to reverse them here +// */ +// fprintf(fp, "(~%s[%d])", +// powergate_port[iport]->lib_name, +// ipin); +// port_cnt++; /* Update port counter*/ +// } +// } else { +// assert (1 == powergate_port[iport]->default_val); +// for (ipin = 0; ipin < powergate_port[iport]->size; ipin++) { +// if ( 0 < port_cnt ) { +// fprintf(fp, "\n\t&&"); +// } +// /* Power-gated signal are disable during operating, enabled during configuration, +// * Therefore, we need to reverse them here +// */ +// fprintf(fp, "(%s[%d])", +// powergate_port[iport]->lib_name, +// ipin); +// port_cnt++; /* Update port counter*/ +// } +// } +// } +// fprintf(fp, ") begin\n"); +// fprintf(fp, "\t\tassign %s_reg = ~%s;\n", +// output_port[0]->lib_name, +// input_port[0]->lib_name); +// fprintf(fp, "\tend else begin\n"); +// fprintf(fp, "\t\tassign %s_reg = 1'bz;\n", +// output_port[0]->lib_name); +// fprintf(fp, "\tend\n"); +// fprintf(fp, "end\n"); +// fprintf(fp, "assign %s = %s_reg;\n", +// output_port[0]->lib_name, +// output_port[0]->lib_name); +// } else { +// fprintf(fp, "assign %s = (%s === 1'bz)? $random : ~%s;\n", +// output_port[0]->lib_name, +// input_port[0]->lib_name, +// input_port[0]->lib_name); +// } +// break; +// case SPICE_MODEL_BUF_BUF: +// if (TRUE == invbuf_spice_model->design_tech_info.power_gated) { +// /* Create a sensitive list */ +// fprintf(fp, "reg %s_reg;\n", output_port[0]->lib_name); +// fprintf(fp, "always @("); +// /* Power-gate port first*/ +// for (iport = 0; iport < num_powergate_port; iport++) { +// fprintf(fp, "%s,", powergate_port[iport]->lib_name); +// } +// fprintf(fp, "%s) begin\n", +// input_port[0]->lib_name); +// /* Dump the case of power-gated */ +// fprintf(fp, " if ("); +// port_cnt = 0; /* Initialize the counter: decide if we need to put down '&&' */ +// for (iport = 0; iport < num_powergate_port; iport++) { +// if (0 == powergate_port[iport]->default_val) { +// for (ipin = 0; ipin < powergate_port[iport]->size; ipin++) { +// if ( 0 < port_cnt ) { +// fprintf(fp, "\n\t&&"); +// } +// /* Power-gated signal are disable during operating, enabled during configuration, +// * Therefore, we need to reverse them here +// */ +// fprintf(fp, "(~%s[%d])", +// powergate_port[iport]->lib_name, +// ipin); +// port_cnt++; /* Update port counter*/ +// } +// } else { +// assert (1 == powergate_port[iport]->default_val); +// for (ipin = 0; ipin < powergate_port[iport]->size; ipin++) { +// if ( 0 < port_cnt ) { +// fprintf(fp, "\n\t&&"); +// } +// /* Power-gated signal are disable during operating, enabled during configuration, +// * Therefore, we need to reverse them here +// */ +// fprintf(fp, "(%s[%d])", +// powergate_port[iport]->lib_name, +// ipin); +// port_cnt++; /* Update port counter*/ +// } +// } +// } +// fprintf(fp, ") begin\n"); +// fprintf(fp, "\t\tassign %s_reg = %s;\n", +// output_port[0]->lib_name, +// input_port[0]->lib_name); +// fprintf(fp, "\tend else begin\n"); +// fprintf(fp, "\t\tassign %s_reg = 1'bz;\n", +// output_port[0]->lib_name); +// fprintf(fp, "\tend\n"); +// fprintf(fp, "end\n"); +// fprintf(fp, "assign %s = %s_reg;\n", +// output_port[0]->lib_name, +// output_port[0]->lib_name); +// +// } else if (FALSE == invbuf_spice_model->design_tech_info.buffer_info->tapered_buf) { +// fprintf(fp, "assign %s = (%s === 1'bz)? $random : %s;\n", +// output_port[0]->lib_name, +// input_port[0]->lib_name, +// input_port[0]->lib_name); +// } else { +// assert (TRUE == invbuf_spice_model->design_tech_info.buffer_info->tapered_buf); +// fprintf(fp, "assign %s = (%s === 1'bz)? $random : ", +// output_port[0]->lib_name, +// input_port[0]->lib_name); +// /* depend on the stage, we may invert the output */ +// if (1 == invbuf_spice_model->design_tech_info.buffer_info->tap_buf_level % 2) { +// fprintf(fp, "~"); +// } +// fprintf(fp, "%s;\n", +// input_port[0]->lib_name); +// } +// break; +// default: +// vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid topology for spice model (%s)!\n", +// __FILE__, __LINE__, invbuf_spice_model->name); +// exit(1); +// } +// +// /* Print timing info */ +// dump_verilog_submodule_timing(fp, invbuf_spice_model); +// +// dump_verilog_submodule_signal_init(fp, invbuf_spice_model); + + fp << "endmodule" << std::endl << std::endl; + + return; +} + +/************************************************ + * Generate the Verilog netlist for essential gates + * include inverters, buffers, transmission-gates, + * etc. + ***********************************************/ +void print_verilog_submodule_essentials(const std::string& verilog_dir, + const std::string& submodule_dir, + const CircuitLibrary& circuit_lib) { + /* TODO: remove .bak when this part is completed and tested */ + std::string verilog_fname = submodule_dir + essentials_verilog_file_name + ".bak"; std::fstream fp; /* Create the file stream */ @@ -33,9 +274,34 @@ void dump_verilog_submodule_essentials(const std::string& verilog_dir, vpr_printf(TIO_MESSAGE_INFO, "Generating Verilog netlist (%s) for essential gates...\n", __FILE__, __LINE__, essentials_verilog_file_name); + + print_verilog_file_header(fp, "Essential gates"); + + print_verilog_include_defines_preproc_file(fp, verilog_dir); + + for (const auto& circuit_model : circuit_lib.models()) { + /* By pass user-defined modules */ + if (!circuit_lib.model_verilog_netlist(circuit_model).empty()) { + continue; + } + if (SPICE_MODEL_INVBUF == circuit_lib.model_type(circuit_model)) { + print_verilog_invbuf_module(fp, circuit_lib, circuit_model); + } + /* + if (SPICE_MODEL_PASSGATE == spice_models[imodel].type) { + dump_verilog_passgate_module(fp, &(spice_models[imodel])); + } + if (SPICE_MODEL_GATE == spice_models[imodel].type) { + dump_verilog_gate_module(fp, &(spice_models[imodel])); + } + */ + } /* Close file handler*/ fp.close(); + /* Add fname to the linked list */ + submodule_verilog_subckt_file_path_head = add_one_subckt_file_name_to_llist(submodule_verilog_subckt_file_path_head, verilog_fname.c_str()); + return; } diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_submodule_essential.h b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_submodule_essential.h index 049fbfda3..648db98fd 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_submodule_essential.h +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_submodule_essential.h @@ -12,8 +12,8 @@ #include #include "circuit_library.h" -void dump_verilog_submodule_essentials(const std::string& verilog_dir, - const std::string& submodule_dir, - const CircuitLibrary& circuit_lib); +void print_verilog_submodule_essentials(const std::string& verilog_dir, + const std::string& submodule_dir, + const CircuitLibrary& circuit_lib); #endif diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_submodule_mux.cpp b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_submodule_mux.cpp index d6f50e5c3..867576bd3 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_submodule_mux.cpp +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_submodule_mux.cpp @@ -45,8 +45,9 @@ void generate_verilog_cmos_mux_branch_module_structural(std::fstream& fp, } /* Get model ports of tgate */ - std::vector tgate_input_ports = circuit_lib.model_ports_by_type(tgate_model, SPICE_MODEL_PORT_INPUT); - std::vector tgate_output_ports = circuit_lib.model_ports_by_type(tgate_model, SPICE_MODEL_PORT_OUTPUT); + std::vector tgate_input_ports = circuit_lib.model_ports_by_type(tgate_model, SPICE_MODEL_PORT_INPUT, true); + std::vector tgate_output_ports = circuit_lib.model_ports_by_type(tgate_model, SPICE_MODEL_PORT_OUTPUT, true); + std::vector tgate_global_ports = circuit_lib.model_global_ports_by_type(tgate_model, SPICE_MODEL_PORT_INPUT); VTR_ASSERT(3 == tgate_input_ports.size()); VTR_ASSERT(1 == tgate_output_ports.size()); @@ -95,7 +96,14 @@ void generate_verilog_cmos_mux_branch_module_structural(std::fstream& fp, mem_inv_port.set_width(num_mems); /* TODO: Generate global ports */ - + for (const auto& port : tgate_global_ports) { + BasicPort basic_port; + /* Configure each input port */ + basic_port.set_name(circuit_lib.port_prefix(port)); + basic_port.set_width(circuit_lib.port_size(port)); + /* Print port */ + fp << "\t" << generate_verilog_port(VERILOG_PORT_INPUT, basic_port) << "," << std::endl; + } /* TODO: add a module to the Module Manager */ @@ -116,6 +124,7 @@ void generate_verilog_cmos_mux_branch_module_structural(std::fstream& fp, /* Transmission gates are connected to each input and also the output*/ fp << "\t" << circuit_lib.model_name(tgate_model) << " " << circuit_lib.model_prefix(tgate_model) << "_0 "; /* Dump explicit port map if required */ + /* TODO: add global port support for tgate model */ if (true == circuit_lib.dump_explicit_port_map(tgate_model)) { fp << " ("; fp << " ." << circuit_lib.port_lib_name(tgate_input_ports[0]) << "(" << "in[0]" << "),"; diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_writer_utils.cpp b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_writer_utils.cpp index da8d2acc0..154fcbb47 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_writer_utils.cpp +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_writer_utils.cpp @@ -2,17 +2,64 @@ * Include functions for most frequently * used Verilog writers ***********************************************/ +#include +#include +#include +#include #include "vtr_assert.h" /* Device-level header files */ /* FPGA-X2P context header files */ #include "spice_types.h" +#include "fpga_x2p_utils.h" /* FPGA-Verilog context header files */ #include "verilog_global.h" #include "verilog_writer_utils.h" +/************************************************ + * Generate header comments for a Verilog netlist + * include the description + ***********************************************/ +void print_verilog_file_header(std::fstream& fp, + const std::string& usage) { + check_file_handler(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 Synthesizable Verilog Netlist" << std::endl; + fp << "//\tDescription: " << usage << std::endl; + fp << "//\tAuthor: Xifan TANG" << std::endl; + fp << "//\t Organization: University of Utah" << std::endl; + fp << "//\tDate: " << std::ctime(&end_time) << std::endl; + fp << "//-------------------------------------------" << std::endl; + fp << "//----- Time scale -----" << std::endl; + fp << "`timescale 1ns / 1ps" << std::endl; + fp << "\n"; +} + + +/************************************************ + * Generate include files for a Verilog netlist + ***********************************************/ +void print_verilog_include_defines_preproc_file(std::fstream& fp, + const std::string& verilog_dir) { + check_file_handler(fp); + + /* Generate the file name */ + std::string include_file_path = format_dir_path(verilog_dir); + include_file_path += defines_verilog_file_name; + + fp << "//------ Include defines: preproc flags -----" << std::endl; + fp << "`include \"" << include_file_path << "\"" << std::endl; + fp << "//------ End Include defines: preproc flags -----" << std::endl; + + return; +} + /* Generate a string of a Verilog port */ std::string generate_verilog_port(const enum e_dump_verilog_port_type& verilog_port_type, const BasicPort& port_info) { diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_writer_utils.h b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_writer_utils.h index 14f7a8e68..33a52fd69 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_writer_utils.h +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_writer_utils.h @@ -9,6 +9,12 @@ #include #include "device_port.h" +void print_verilog_file_header(std::fstream& fp, + const std::string& usage); + +void print_verilog_include_defines_preproc_file(std::fstream& fp, + const std::string& verilog_dir); + std::string generate_verilog_port(const enum e_dump_verilog_port_type& dump_port_type, const BasicPort& port_info);