diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/backend_assistant/pnr_sdc_writer.cpp b/vpr7_x2p/vpr/SRC/fpga_x2p/backend_assistant/pnr_sdc_writer.cpp index 042efac5e..1fb4ebeaa 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/backend_assistant/pnr_sdc_writer.cpp +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/backend_assistant/pnr_sdc_writer.cpp @@ -16,6 +16,7 @@ #include "device_port.h" #include "util.h" +#include "mux_utils.h" #include "fpga_x2p_naming.h" #include "fpga_x2p_utils.h" @@ -194,11 +195,9 @@ void rec_print_pnr_sdc_disable_configurable_memory_module_output(std::fstream& f } /******************************************************************** - * Break combinational loops in FPGA fabric, which mainly come from: - * 1. Configurable memory cells. - * To handle this, we disable the outputs of memory cells - * 2. Loops of multiplexers. - * To handle this, we disable the outputs of routing multiplexers + * Break combinational loops in FPGA fabric, which mainly come from + * configurable memory cells. + * To handle this, we disable the outputs of memory cells *******************************************************************/ static void print_pnr_sdc_constrain_configurable_memory_outputs(const std::string& sdc_dir, @@ -240,6 +239,72 @@ void print_pnr_sdc_constrain_configurable_memory_outputs(const std::string& sdc_ run_time_sec); } +/******************************************************************** + * Break combinational loops in FPGA fabric, which mainly come from + * loops of multiplexers. + * To handle this, we disable the timing at outputs of routing multiplexers + *******************************************************************/ +static +void print_sdc_disable_routing_multiplexer_outputs(const std::string& sdc_dir, + const MuxLibrary& mux_lib, + const CircuitLibrary& circuit_lib, + const ModuleManager& module_manager) { + /* Create the file name for Verilog netlist */ + std::string sdc_fname(sdc_dir + std::string(SDC_DISABLE_MUX_OUTPUTS_FILE_NAME)); + + vpr_printf(TIO_MESSAGE_INFO, + "Generating SDC for disable routing multiplexer outputs for P&R flow: %s ...", + sdc_fname.c_str()); + + /* Start time count */ + clock_t t_start = clock(); + + /* Create the file stream */ + std::fstream fp; + fp.open(sdc_fname, std::fstream::out | std::fstream::trunc); + + check_file_handler(fp); + + /* Generate the descriptions*/ + print_sdc_file_header(fp, std::string("Disable routing multiplexer outputs for PnR")); + + /* Iterate over the MUX modules */ + for (const MuxId& mux_id : mux_lib.muxes()) { + const CircuitModelId& mux_model = mux_lib.mux_circuit_model(mux_id); + + /* Skip LUTs, we only care about multiplexers here */ + if (SPICE_MODEL_MUX != circuit_lib.model_type(mux_model)) { + continue; + } + + const MuxGraph& mux_graph = mux_lib.mux_graph(mux_id); + std::string mux_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("")); + /* Find the module name in module manager */ + ModuleId mux_module = module_manager.find_module(mux_module_name); + VTR_ASSERT(true == module_manager.valid_module_id(mux_module)); + + /* Disable the timing for the output ports */ + for (const BasicPort& output_port : module_manager.module_ports_by_type(mux_module, ModuleManager::MODULE_OUTPUT_PORT)) { + fp << "set_disable_timing [get_pins -filter \"name =~ " << output_port.get_name() << "*\" "; + fp << "-of [get_cells -hier -filter \"ref_lib_cell_name == " << mux_module_name << "\"]]" << std::endl; + fp << std::endl; + } + } + + /* Close file handler */ + fp.close(); + + /* End time count */ + clock_t t_end = clock(); + + float run_time_sec = (float)(t_end - t_start) / CLOCKS_PER_SEC; + vpr_printf(TIO_MESSAGE_INFO, + "took %g seconds\n", + run_time_sec); +} + /******************************************************************** * Top-level function to print a number of SDC files in different purpose * This function will generate files upon the options provided by users @@ -250,6 +315,7 @@ void print_pnr_sdc_constrain_configurable_memory_outputs(const std::string& sdc_ *******************************************************************/ void print_pnr_sdc(const SdcOption& sdc_options, const float& critical_path_delay, + const MuxLibrary& mux_lib, const CircuitLibrary& circuit_lib, const ModuleManager& module_manager, const std::vector& global_ports) { @@ -259,20 +325,21 @@ void print_pnr_sdc(const SdcOption& sdc_options, print_pnr_sdc_global_ports(sdc_options.sdc_dir(), critical_path_delay, circuit_lib, global_ports); } + std::string top_module_name = generate_fpga_top_module_name(); + ModuleId top_module = module_manager.find_module(top_module_name); + VTR_ASSERT(true == module_manager.valid_module_id(top_module)); + /* Part 2. Output Design Constraints to disable outputs of memory cells */ if (true == sdc_options.constrain_configurable_memory_outputs()) { - std::string top_module_name = generate_fpga_top_module_name(); - ModuleId top_module = module_manager.find_module(top_module_name); - VTR_ASSERT(true == module_manager.valid_module_id(top_module)); print_pnr_sdc_constrain_configurable_memory_outputs(sdc_options.sdc_dir(), module_manager, top_module); } /* 2. Break loops from Multiplexer Output */ - /* - if (TRUE == sdc_opts.break_loops_mux) { - verilog_generate_sdc_break_loop_mux(fp, num_switch, switches, spice, routing_arch); + if (true == sdc_options.constrain_routing_multiplexer_outputs()) { + print_sdc_disable_routing_multiplexer_outputs(sdc_options.sdc_dir(), + mux_lib, circuit_lib, + module_manager); } - */ /* TODO: 3. Break loops from any SB output */ /* diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/backend_assistant/pnr_sdc_writer.h b/vpr7_x2p/vpr/SRC/fpga_x2p/backend_assistant/pnr_sdc_writer.h index 492a18873..6923320a6 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/backend_assistant/pnr_sdc_writer.h +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/backend_assistant/pnr_sdc_writer.h @@ -6,10 +6,13 @@ #include "vpr_types.h" #include "rr_blocks.h" #include "module_manager.h" +#include "mux_library.h" +#include "circuit_library.h" #include "sdc_option.h" void print_pnr_sdc(const SdcOption& sdc_options, const float& critical_path_delay, + const MuxLibrary& mux_lib, const CircuitLibrary& circuit_lib, const ModuleManager& module_manager, const std::vector& global_ports); diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/backend_assistant/sdc_api.cpp b/vpr7_x2p/vpr/SRC/fpga_x2p/backend_assistant/sdc_api.cpp index f6d46561b..99a981df8 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/backend_assistant/sdc_api.cpp +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/backend_assistant/sdc_api.cpp @@ -11,6 +11,7 @@ *******************************************************************/ void fpga_sdc_generator(const SdcOption& sdc_options, const float& critical_path_delay, + const MuxLibrary& mux_lib, const CircuitLibrary& circuit_lib, const ModuleManager& module_manager, const std::vector& global_ports) { @@ -21,7 +22,7 @@ void fpga_sdc_generator(const SdcOption& sdc_options, clock_t t_start = clock(); if (true == sdc_options.generate_sdc_pnr()) { - print_pnr_sdc(sdc_options, critical_path_delay, circuit_lib, module_manager, global_ports); + print_pnr_sdc(sdc_options, critical_path_delay, mux_lib, circuit_lib, module_manager, global_ports); } /* End time count */ diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/backend_assistant/sdc_api.h b/vpr7_x2p/vpr/SRC/fpga_x2p/backend_assistant/sdc_api.h index fbd9960d8..e0f64fafd 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/backend_assistant/sdc_api.h +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/backend_assistant/sdc_api.h @@ -4,10 +4,12 @@ #include #include "sdc_option.h" #include "circuit_library.h" +#include "mux_library.h" #include "module_manager.h" void fpga_sdc_generator(const SdcOption& sdc_options, const float& critical_path_delay, + const MuxLibrary& mux_lib, const CircuitLibrary& circuit_lib, const ModuleManager& module_manager, const std::vector& global_ports); diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/backend_assistant/sdc_writer_naming.h b/vpr7_x2p/vpr/SRC/fpga_x2p/backend_assistant/sdc_writer_naming.h index 7b9df4804..7371835a8 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/backend_assistant/sdc_writer_naming.h +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/backend_assistant/sdc_writer_naming.h @@ -4,6 +4,7 @@ constexpr char* SDC_GLOBAL_PORTS_FILE_NAME = "global_ports.sdc"; constexpr char* SDC_BENCHMARK_ANALYSIS_FILE_NAME= "fpga_top_analysis.sdc"; constexpr char* SDC_DISABLE_CONFIG_MEM_OUTPUTS_FILE_NAME = "disable_configurable_memory_outputs.sdc"; +constexpr char* SDC_DISABLE_MUX_OUTPUTS_FILE_NAME = "disable_routing_multiplexer_outputs.sdc"; constexpr char* SDC_CB_FILE_NAME = "cb.sdc"; constexpr char* SDC_SB_FILE_NAME = "sb.sdc"; diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_api.c b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_api.c index ccecccabd..8c1f6b5e2 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_api.c +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_api.c @@ -159,6 +159,7 @@ void vpr_fpga_x2p_tool_suites(t_vpr_setup vpr_setup, /* TODO: the critical path delay unit should be explicit! */ fpga_sdc_generator(sdc_options, Arch.spice->spice_params.stimulate_params.vpr_crit_path_delay / 1e-9, + mux_lib, Arch.spice->circuit_lib, module_manager, global_ports); }