diff --git a/vpr7_x2p/libarchfpga/SRC/circuit_library.cpp b/vpr7_x2p/libarchfpga/SRC/circuit_library.cpp index 41a7d61db..32e6ad2b5 100644 --- a/vpr7_x2p/libarchfpga/SRC/circuit_library.cpp +++ b/vpr7_x2p/libarchfpga/SRC/circuit_library.cpp @@ -198,6 +198,15 @@ CircuitModelId CircuitLibrary::pass_gate_logic_model(const CircuitModelId& model return pgl_model_id; } +/* Return the type of pass gate logic module, only applicable to circuit model whose type is pass-gate logic */ +enum e_spice_model_pass_gate_logic_type CircuitLibrary::pass_gate_logic_type(const CircuitModelId& model_id) const { + /* validate the model_id */ + VTR_ASSERT(valid_model_id(model_id)); + /* validate the circuit model type is PASSGATE */ + VTR_ASSERT(SPICE_MODEL_PASSGATE == model_type(model_id)); + return pass_gate_logic_types_[model_id]; +} + /* Return the multiplex structure of a circuit model */ enum e_spice_model_structure CircuitLibrary::mux_structure(const CircuitModelId& model_id) const { /* validate the model_id */ diff --git a/vpr7_x2p/libarchfpga/SRC/circuit_library.h b/vpr7_x2p/libarchfpga/SRC/circuit_library.h index d5842f049..b0f2fd210 100644 --- a/vpr7_x2p/libarchfpga/SRC/circuit_library.h +++ b/vpr7_x2p/libarchfpga/SRC/circuit_library.h @@ -225,6 +225,7 @@ class CircuitLibrary { bool is_lut_intermediate_buffered(const CircuitModelId& model_id) const; /* Pass-gate-logic information */ CircuitModelId pass_gate_logic_model(const CircuitModelId& model_id) const; + enum e_spice_model_pass_gate_logic_type pass_gate_logic_type(const CircuitModelId& model_id) const; /* Multiplexer information */ enum e_spice_model_structure mux_structure(const CircuitModelId& model_id) const; size_t mux_num_levels(const CircuitModelId& model_id) const; diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_essential_gates.cpp b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_essential_gates.cpp index cbe8d258a..25010abd2 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_essential_gates.cpp +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_essential_gates.cpp @@ -9,6 +9,7 @@ /* Device-level header files */ #include "spice_types.h" +#include "device_port.h" /* FPGA-X2P context header files */ #include "fpga_x2p_utils.h" @@ -33,7 +34,7 @@ void print_verilog_power_gated_invbuf_body(std::fstream& fp, /* Ensure a valid file handler*/ check_file_handler(fp); - fp << "//----- Verilog codes of a power-gated inverter -----" << std::endl; + print_verilog_comment(fp, std::string("----- Verilog codes of a power-gated inverter -----")); /* Create a sensitive list */ fp << "\treg " << circuit_lib.port_lib_name(output_port) << "_reg;" << std::endl; @@ -109,7 +110,7 @@ void print_verilog_invbuf_body(std::fstream& fp, /* Ensure a valid file handler*/ check_file_handler(fp); - fp << "//----- Verilog codes of a regular inverter -----" << std::endl; + print_verilog_comment(fp, std::string("----- Verilog codes of a regular inverter -----")); fp << "\tassign " << circuit_lib.port_lib_name(output_port) << " = (" << circuit_lib.port_lib_name(input_port) << " == 1'bz)? $random : "; @@ -139,8 +140,6 @@ void print_verilog_invbuf_module(std::fstream& fp, /* 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); @@ -178,14 +177,12 @@ void print_verilog_invbuf_module(std::fstream& fp, } /* dump module body */ - fp << "module " << circuit_lib.model_name(circuit_model) << " (" << std::endl; + print_verilog_module_definition(fp, circuit_lib.model_name(circuit_model)); - /* TODO: print global ports */ + /* TODO: print global ports, this should be handled by ModuleManager */ 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)); + /* Configure each global port */ + BasicPort basic_port(circuit_lib.port_lib_name(port), circuit_lib.port_size(port)); /* Print port */ fp << "\t" << generate_verilog_port(VERILOG_PORT_INPUT, basic_port) << "," << std::endl; } @@ -201,7 +198,7 @@ void print_verilog_invbuf_module(std::fstream& fp, /* 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 << "\t" << generate_verilog_port(VERILOG_PORT_OUTPUT, output_port) << std::endl; fp << ");" << std::endl; /* Finish dumping ports */ @@ -226,15 +223,114 @@ void print_verilog_invbuf_module(std::fstream& fp, /* Print timing info */ print_verilog_submodule_timing(fp, circuit_lib, circuit_model); + /* Print signal initialization */ print_verilog_submodule_signal_init(fp, circuit_lib, circuit_model); - fp << "endmodule" << std::endl << std::endl; - - fp << "//----- END Verilog module for " << circuit_lib.model_name(circuit_model) << " -----" << std::endl; + /* Put an end to the Verilog module */ + print_verilog_module_end(fp, circuit_lib.model_name(circuit_model)); return; } +/************************************************ + * Print a Verilog module of a pass-gate, + * either transmission-gate or pass-transistor + ***********************************************/ +static +void print_verilog_passgate_module(std::fstream& fp, + const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model) { + /* Ensure a valid file handler*/ + check_file_handler(fp); + + /* Find the input port, output port*/ + 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); + + switch (circuit_lib.pass_gate_logic_type(circuit_model)) { + case SPICE_MODEL_PASS_GATE_TRANSMISSION: + /* Make sure: + * There is only 3 input port (in, sel, selb), + * each size of which is 1 + */ + VTR_ASSERT( 3 == input_ports.size() ); + for (const auto& input_port : input_ports) { + VTR_ASSERT(1 == circuit_lib.port_size(input_port)); + } + break; + case SPICE_MODEL_PASS_GATE_TRANSISTOR: + /* Make sure: + * There is only 2 input port (in, sel), + * each size of which is 1 + */ + VTR_ASSERT( 2 == input_ports.size() ); + for (const auto& input_port : input_ports) { + VTR_ASSERT(1 == circuit_lib.port_size(input_port)); + } + break; + default: + vpr_printf(TIO_MESSAGE_ERROR, + "(File:%s,[LINE%d])Invalid topology for circuit model (name=%s)!\n", + __FILE__, __LINE__, circuit_lib.model_name(circuit_model)); + exit(1); + } + + /* Make sure: + * There is only 1 output port, + * each size of which is 1 + */ + VTR_ASSERT( (1 == output_ports.size()) && (1 == circuit_lib.port_size(output_ports[0])) ); + + /* Print Verilog module */ + print_verilog_module_definition(fp, circuit_lib.model_name(circuit_model)); + + /* TODO: print global ports, this should be handled by ModuleManager */ + for (const auto& port : global_ports) { + /* Configure each global port */ + BasicPort basic_port(circuit_lib.port_lib_name(port), circuit_lib.port_size(port)); + /* Print port */ + fp << "\t" << generate_verilog_port(VERILOG_PORT_INPUT, basic_port) << "," << std::endl; + } + + for (const auto& input_port : input_ports) { + /* Configure each global port */ + BasicPort basic_port(circuit_lib.port_lib_name(input_port), circuit_lib.port_size(input_port)); + /* Print port */ + fp << "\t" << generate_verilog_port(VERILOG_PORT_INPUT, basic_port) << "," << std::endl; + } + + /* Configure each global port */ + for (const auto& output_port : output_ports) { + BasicPort basic_port(circuit_lib.port_lib_name(output_port), circuit_lib.port_size(output_port)); + /* Print port */ + fp << "\t" << generate_verilog_port(VERILOG_PORT_OUTPUT, basic_port); + /* Last port does not need a comma */ + if (output_port != output_ports.back()) { + fp << "," << std::endl; + } else { + fp << std::endl; + } + } + fp << ");" << std::endl; + + /* Dump logics: we propagate input to the output when the gate is '1' + * the input is blocked from output when the gate is '0' + */ + fp << "\tassign " << circuit_lib.port_lib_name(output_ports[0]) << " = "; + fp << circuit_lib.port_lib_name(input_ports[1]) << " ? " << circuit_lib.port_lib_name(input_ports[0]); + fp << " : 1'bz;" << std::endl; + + /* Print timing info */ + print_verilog_submodule_timing(fp, circuit_lib, circuit_model); + + /* Print signal initialization */ + print_verilog_submodule_signal_init(fp, circuit_lib, circuit_model); + + /* Put an end to the Verilog module */ + print_verilog_module_end(fp, circuit_lib.model_name(circuit_model)); +} + /************************************************ * Generate the Verilog netlist for essential gates * include inverters, buffers, transmission-gates, @@ -270,10 +366,10 @@ void print_verilog_submodule_essentials(const std::string& verilog_dir, 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_PASSGATE == circuit_lib.model_type(circuit_model)) { + print_verilog_passgate_module(fp, circuit_lib, circuit_model); } + /* if (SPICE_MODEL_GATE == spice_models[imodel].type) { dump_verilog_gate_module(fp, &(spice_models[imodel])); } diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_submodule_utils.cpp b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_submodule_utils.cpp index 696c61842..e587c1096 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_submodule_utils.cpp +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_submodule_utils.cpp @@ -50,7 +50,7 @@ void print_verilog_submodule_timing(std::fstream& fp, fp << std::endl; fp << "`ifdef " << verilog_timing_preproc_flag << std::endl; - fp << "//------ BEGIN Pin-to-pin Timing constraints -----" << std::endl; + print_verilog_comment(fp, std::string("------ BEGIN Pin-to-pin Timing constraints -----")); fp << "\tspecify" << std::endl; /* Read out pin-to-pin delays by finding out all the edges belonging to a circuit model */ @@ -69,13 +69,13 @@ void print_verilog_submodule_timing(std::fstream& fp, fp << generate_verilog_port(VERILOG_PORT_CONKT, sink_port_info) << ")"; fp << " = "; fp << "(" << std::setprecision(FLOAT_PRECISION) << circuit_lib.timing_edge_delay(timing_edge, SPICE_MODEL_DELAY_RISE); - fp << " => "; + fp << " , "; fp << std::setprecision(FLOAT_PRECISION) << circuit_lib.timing_edge_delay(timing_edge, SPICE_MODEL_DELAY_RISE) << ")"; fp << ";" << std::endl; } fp << "\tendspecify" << std::endl; - fp << "//------ END Pin-to-pin Timing constraints -----" << std::endl; + print_verilog_comment(fp, std::string("------ END Pin-to-pin Timing constraints -----")); fp << "`endif" << std::endl; } @@ -88,7 +88,7 @@ void print_verilog_submodule_signal_init(std::fstream& fp, fp << std::endl; fp << "`ifdef " << verilog_signal_init_preproc_flag << std::endl; - fp << "//------ BEGIN driver initialization -----" << std::endl; + print_verilog_comment(fp, std::string("------ BEGIN driver initialization -----")); fp << "\tinitial begin" << std::endl; fp << "\t`ifdef " << verilog_formal_verification_preproc_flag << std::endl; @@ -106,7 +106,7 @@ void print_verilog_submodule_signal_init(std::fstream& fp, fp << "\t`endif\n" << std::endl; fp << "\tend" << std::endl; - fp << "//------ END driver initialization -----" << std::endl; + print_verilog_comment(fp, std::string("------ END driver initialization -----")); fp << "`endif" << std::endl; } 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 8902ce920..2743cdb6f 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 @@ -60,6 +60,39 @@ void print_verilog_include_defines_preproc_file(std::fstream& fp, return; } +/************************************************ + * Print a Verilog comment line + ***********************************************/ +void print_verilog_comment(std::fstream& fp, + const std::string& comment) { + check_file_handler(fp); + + fp << "// " << comment << std::endl; +} + +/************************************************ + * Print a Verilog module definition + ***********************************************/ +void print_verilog_module_definition(std::fstream& fp, + const std::string& module_name) { + check_file_handler(fp); + + print_verilog_comment(fp, std::string("//----- Verilog module for " + module_name + " -----")); + fp << "module " << module_name << "(" << std::endl; +} + +/************************************************ + * Print a Verilog module definition + ***********************************************/ +void print_verilog_module_end(std::fstream& fp, + const std::string& module_name) { + check_file_handler(fp); + + fp << "endmodule" << std::endl; + print_verilog_comment(fp, std::string("//----- END Verilog module for " + module_name + " -----")); + fp << std::endl; +} + /* 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 33a52fd69..2f3d73bba 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 @@ -15,6 +15,15 @@ void print_verilog_file_header(std::fstream& fp, void print_verilog_include_defines_preproc_file(std::fstream& fp, const std::string& verilog_dir); +void print_verilog_comment(std::fstream& fp, + const std::string& comment); + +void print_verilog_module_definition(std::fstream& fp, + const std::string& module_name); + +void print_verilog_module_end(std::fstream& fp, + const std::string& module_name); + std::string generate_verilog_port(const enum e_dump_verilog_port_type& dump_port_type, const BasicPort& port_info);