diff --git a/libopenfpga/libpcf/src/pin_constraints.cpp b/libopenfpga/libpcf/src/pin_constraints.cpp index 4f7a701a7..24d7571b7 100644 --- a/libopenfpga/libpcf/src/pin_constraints.cpp +++ b/libopenfpga/libpcf/src/pin_constraints.cpp @@ -38,6 +38,17 @@ std::string PinConstraints::net(const PinConstraintId& pin_constraint_id) const return pin_constraint_nets_[pin_constraint_id]; } +std::string PinConstraints::pin_net(const openfpga::BasicPort& pin) const { + std::string constrained_net_name; + for (const PinConstraintId& pin_constraint : pin_constraints()) { + if (pin == pin_constraint_pins_[pin_constraint]) { + constrained_net_name = net(pin_constraint); + break; + } + } + return constrained_net_name; +} + bool PinConstraints::empty() const { return 0 == pin_constraint_ids_.size(); } diff --git a/libopenfpga/libpcf/src/pin_constraints.h b/libopenfpga/libpcf/src/pin_constraints.h index 8b3a977c0..e0ef7fe3f 100644 --- a/libopenfpga/libpcf/src/pin_constraints.h +++ b/libopenfpga/libpcf/src/pin_constraints.h @@ -52,6 +52,11 @@ class PinConstraints { /* Get the net to be constrained */ std::string net(const PinConstraintId& pin_constraint_id) const; + /* Find the net that is constrained on a pin + * TODO: this function will only return the first net found in the constraint list + */ + std::string pin_net(const openfpga::BasicPort& pin) const; + /* Check if there are any pin constraints */ bool empty() const; diff --git a/openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp b/openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp index 542eadc2e..25b1abe5f 100644 --- a/openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp +++ b/openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp @@ -135,13 +135,7 @@ int print_verilog_preconfig_top_module_connect_global_ports(std::fstream &fp, BasicPort module_clock_pin(module_global_port.get_name(), module_global_port.pins()[pin_id], module_global_port.pins()[pin_id]); /* If the clock port name is in the pin constraints, we should wire it to the constrained pin */ - std::string constrained_net_name; - for (const PinConstraintId& pin_constraint : pin_constraints.pin_constraints()) { - if (module_clock_pin == pin_constraints.pin(pin_constraint)) { - constrained_net_name = pin_constraints.net(pin_constraint); - break; - } - } + std::string constrained_net_name = pin_constraints.pin_net(module_clock_pin); /* If constrained to an open net or there is no clock in the benchmark, we assign it to a default value */ if ( (std::string(PIN_CONSTRAINT_OPEN_NET) == constrained_net_name) @@ -173,8 +167,27 @@ int print_verilog_preconfig_top_module_connect_global_ports(std::fstream &fp, } /* For other ports, give an default value */ - std::vector default_values(module_global_port.get_width(), fabric_global_ports.global_port_default_value(global_port_id)); - print_verilog_wire_constant_values(fp, module_global_port, default_values); + for (size_t pin_id = 0; pin_id < module_global_port.pins().size(); ++pin_id) { + BasicPort module_global_pin(module_global_port.get_name(), + module_global_port.pins()[pin_id], + module_global_port.pins()[pin_id]); + + /* If the global port name is in the pin constraints, we should wire it to the constrained pin */ + std::string constrained_net_name = pin_constraints.pin_net(module_global_pin); + + /* - If constrained to a given net in the benchmark, we connect the global pin to the net + * - If constrained to an open net in the benchmark, we assign it to a default value + */ + if ( (std::string(PIN_CONSTRAINT_OPEN_NET) != constrained_net_name) + && (!constrained_net_name.empty())) { + BasicPort benchmark_pin(constrained_net_name + std::string(FORMAL_VERIFICATION_TOP_MODULE_PORT_POSTFIX), 1); + print_verilog_wire_connection(fp, module_global_pin, benchmark_pin, false); + } else { + VTR_ASSERT_SAFE(std::string(PIN_CONSTRAINT_OPEN_NET) == constrained_net_name); + std::vector default_values(module_global_pin.get_width(), fabric_global_ports.global_port_default_value(global_port_id)); + print_verilog_wire_constant_values(fp, module_global_pin, default_values); + } + } } print_verilog_comment(fp, std::string("----- End Connect Global ports of FPGA top module -----")); diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp index 08b7cd2e8..7a233de1a 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp @@ -258,21 +258,17 @@ void print_verilog_top_testbench_config_protocol_port(std::fstream& fp, } /******************************************************************** - * Wire the global ports of FPGA fabric to local wires + * Wire the global clock ports of FPGA fabric to local wires *******************************************************************/ static -void print_verilog_top_testbench_global_ports_stimuli(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& top_module, - const FabricGlobalPortInfo& fabric_global_port_info, - const SimulationSetting& simulation_parameters, - const bool& active_global_prog_reset, - const bool& active_global_prog_set) { +void print_verilog_top_testbench_global_clock_ports_stimuli(std::fstream& fp, + const ModuleManager& module_manager, + const ModuleId& top_module, + const FabricGlobalPortInfo& fabric_global_port_info, + const SimulationSetting& simulation_parameters) { /* Validate the file stream */ valid_file_stream(fp); - print_verilog_comment(fp, std::string("----- Begin connecting global ports of FPGA fabric to stimuli -----")); - /* Connect global clock ports to operating or programming clock signal */ for (const FabricGlobalPortId& fabric_global_port : fabric_global_port_info.global_ports()) { if (false == fabric_global_port_info.global_port_is_clock(fabric_global_port)) { @@ -317,6 +313,18 @@ void print_verilog_top_testbench_global_ports_stimuli(std::fstream& fp, 1 == fabric_global_port_info.global_port_default_value(fabric_global_port)); } } +} + +/******************************************************************** + * Wire the global config done ports of FPGA fabric to local wires + *******************************************************************/ +static +void print_verilog_top_testbench_global_config_done_ports_stimuli(std::fstream& fp, + const ModuleManager& module_manager, + const ModuleId& top_module, + const FabricGlobalPortInfo& fabric_global_port_info) { + /* Validate the file stream */ + valid_file_stream(fp); /* Connect global configuration done ports to configuration done signal */ for (const FabricGlobalPortId& fabric_global_port : fabric_global_port_info.global_ports()) { @@ -341,6 +349,20 @@ void print_verilog_top_testbench_global_ports_stimuli(std::fstream& fp, stimuli_config_done_port, 1 == fabric_global_port_info.global_port_default_value(fabric_global_port)); } +} + +/******************************************************************** + * Wire the global reset ports of FPGA fabric to local wires + *******************************************************************/ +static +void print_verilog_top_testbench_global_reset_ports_stimuli(std::fstream& fp, + const ModuleManager& module_manager, + const ModuleId& top_module, + const PinConstraints& pin_constraints, + const FabricGlobalPortInfo& fabric_global_port_info, + const bool& active_global_prog_reset) { + /* Validate the file stream */ + valid_file_stream(fp); /* Connect global reset ports to operating or programming reset signal */ for (const FabricGlobalPortId& fabric_global_port : fabric_global_port_info.global_ports()) { @@ -373,20 +395,58 @@ void print_verilog_top_testbench_global_ports_stimuli(std::fstream& fp, stimuli_reset_port.set_name(std::string(TOP_TB_RESET_PORT_NAME)); stimuli_reset_port.set_width(1); } - /* Wire the port to the input stimuli: - * The wiring will be inverted if the default value of the global port is 1 - * Otherwise, the wiring will not be inverted! - */ - if (true == activate) { - print_verilog_wire_connection(fp, module_manager.module_port(top_module, module_global_port), - stimuli_reset_port, - 1 == fabric_global_port_info.global_port_default_value(fabric_global_port)); - } else { - VTR_ASSERT_SAFE(false == activate); - print_verilog_wire_constant_values(fp, module_manager.module_port(top_module, module_global_port), - std::vector(1, fabric_global_port_info.global_port_default_value(fabric_global_port))); + + BasicPort module_global_port_info = module_manager.module_port(top_module, module_global_port); + + for (size_t pin_id = 0; pin_id < module_global_port_info.pins().size(); ++pin_id) { + BasicPort module_global_pin(module_global_port_info.get_name(), + module_global_port_info.pins()[pin_id], + module_global_port_info.pins()[pin_id]); + + /* Regular reset port can be mapped by a net from user design */ + if (false == fabric_global_port_info.global_port_is_prog(fabric_global_port)) { + /* If the global port name is in the pin constraints, we should wire it to the constrained pin */ + std::string constrained_net_name = pin_constraints.pin_net(module_global_pin); + + /* - If constrained to a given net in the benchmark, we connect the global pin to the net */ + if ( (std::string(PIN_CONSTRAINT_OPEN_NET) != constrained_net_name) + && (!constrained_net_name.empty())) { + BasicPort benchmark_pin(constrained_net_name, 1); + print_verilog_wire_connection(fp, module_global_pin, + benchmark_pin, + false); + continue; /* Finish the net assignment for this reset pin */ + } + } + + /* Wire the port to the input stimuli: + * The wiring will be inverted if the default value of the global port is 1 + * Otherwise, the wiring will not be inverted! + */ + if (true == activate) { + print_verilog_wire_connection(fp, module_global_pin, + stimuli_reset_port, + 1 == fabric_global_port_info.global_port_default_value(fabric_global_port)); + } else { + VTR_ASSERT_SAFE(false == activate); + print_verilog_wire_constant_values(fp, module_global_pin, + std::vector(1, fabric_global_port_info.global_port_default_value(fabric_global_port))); + } } } +} + +/******************************************************************** + * Wire the global set ports of FPGA fabric to local wires + *******************************************************************/ +static +void print_verilog_top_testbench_global_set_ports_stimuli(std::fstream& fp, + const ModuleManager& module_manager, + const ModuleId& top_module, + const FabricGlobalPortInfo& fabric_global_port_info, + const bool& active_global_prog_set) { + /* Validate the file stream */ + valid_file_stream(fp); /* Connect global set ports to operating or programming set signal */ for (const FabricGlobalPortId& fabric_global_port : fabric_global_port_info.global_ports()) { @@ -438,6 +498,18 @@ void print_verilog_top_testbench_global_ports_stimuli(std::fstream& fp, std::vector(1, fabric_global_port_info.global_port_default_value(fabric_global_port))); } } +} + +/******************************************************************** + * Wire the regular global ports of FPGA fabric to local wires + *******************************************************************/ +static +void print_verilog_top_testbench_regular_global_ports_stimuli(std::fstream& fp, + const ModuleManager& module_manager, + const ModuleId& top_module, + const FabricGlobalPortInfo& fabric_global_port_info) { + /* Validate the file stream */ + valid_file_stream(fp); /* For the rest of global ports, wire them to constant signals */ for (const FabricGlobalPortId& fabric_global_port : fabric_global_port_info.global_ports()) { @@ -478,6 +550,55 @@ void print_verilog_top_testbench_global_ports_stimuli(std::fstream& fp, std::vector default_values(module_port.get_width(), fabric_global_port_info.global_port_default_value(fabric_global_port)); print_verilog_wire_constant_values(fp, module_port, default_values); } +} + +/******************************************************************** + * Wire the global ports of FPGA fabric to local wires + *******************************************************************/ +static +void print_verilog_top_testbench_global_ports_stimuli(std::fstream& fp, + const ModuleManager& module_manager, + const ModuleId& top_module, + const PinConstraints& pin_constraints, + const FabricGlobalPortInfo& fabric_global_port_info, + const SimulationSetting& simulation_parameters, + const bool& active_global_prog_reset, + const bool& active_global_prog_set) { + /* Validate the file stream */ + valid_file_stream(fp); + + print_verilog_comment(fp, std::string("----- Begin connecting global ports of FPGA fabric to stimuli -----")); + + print_verilog_top_testbench_global_clock_ports_stimuli(fp, + module_manager, + top_module, + fabric_global_port_info, + simulation_parameters); + + print_verilog_top_testbench_global_config_done_ports_stimuli(fp, + module_manager, + top_module, + fabric_global_port_info); + + + print_verilog_top_testbench_global_reset_ports_stimuli(fp, + module_manager, + top_module, + pin_constraints, + fabric_global_port_info, + active_global_prog_reset); + + print_verilog_top_testbench_global_set_ports_stimuli(fp, + module_manager, + top_module, + fabric_global_port_info, + active_global_prog_set); + + + print_verilog_top_testbench_regular_global_ports_stimuli(fp, + module_manager, + top_module, + fabric_global_port_info); print_verilog_comment(fp, std::string("----- End connecting global ports of FPGA fabric to stimuli -----")); } @@ -1994,6 +2115,7 @@ void print_verilog_top_testbench(const ModuleManager& module_manager, /* Generate stimuli for global ports or connect them to existed signals */ print_verilog_top_testbench_global_ports_stimuli(fp, module_manager, top_module, + pin_constraints, global_ports, simulation_parameters, active_global_prog_reset, diff --git a/openfpga_flow/openfpga_shell_scripts/example_without_ace_script.openfpga b/openfpga_flow/openfpga_shell_scripts/example_without_ace_script.openfpga index f694b3c03..3c1be9114 100644 --- a/openfpga_flow/openfpga_shell_scripts/example_without_ace_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/example_without_ace_script.openfpga @@ -55,7 +55,7 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --pri # - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA # - Enable pre-configured top-level testbench which is a fast verification skipping programming phase # - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts -write_verilog_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --print_top_testbench --print_preconfig_top_testbench --print_simulation_ini ./SimulationDeck/simulation_deck.ini --include_signal_init --support_icarus_simulator +write_verilog_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --print_top_testbench --print_preconfig_top_testbench --print_simulation_ini ./SimulationDeck/simulation_deck.ini --include_signal_init --support_icarus_simulator --pin_constraints_file ${OPENFPGA_PIN_CONSTRAINTS_FILE} # Write the SDC files for PnR backend # - Turn on every options here diff --git a/openfpga_flow/tasks/basic_tests/k4_series/k4n4_fracff/config/pin_constraints.xml b/openfpga_flow/tasks/basic_tests/k4_series/k4n4_fracff/config/pin_constraints.xml new file mode 100644 index 000000000..abcf209f6 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/k4_series/k4n4_fracff/config/pin_constraints.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/openfpga_flow/tasks/basic_tests/k4_series/k4n4_fracff/config/task.conf b/openfpga_flow/tasks/basic_tests/k4_series/k4n4_fracff/config/task.conf index 58be5a2bb..07e326a1e 100644 --- a/openfpga_flow/tasks/basic_tests/k4_series/k4n4_fracff/config/task.conf +++ b/openfpga_flow/tasks/basic_tests/k4_series/k4n4_fracff/config/task.conf @@ -19,6 +19,7 @@ fpga_flow=yosys_vpr openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/example_without_ace_script.openfpga openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_frac_N4_fracff_40nm_cc_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/fixed_sim_openfpga.xml +openfpga_pin_constraints_file=${PATH:OPENFPGA_PATH}/openfpga_flow/tasks/basic_tests/k4_series/k4n4_fracff/config/pin_constraints.xml # Yosys script parameters yosys_cell_sim_verilog=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/openfpga_dff_sim.v yosys_dff_map_verilog=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/openfpga_dff_map.v