From 592765af48ef170c8eddf807e6d3ad648266996f Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 23 Apr 2023 13:57:37 +0800 Subject: [PATCH] [core] code complete for upgrading netlist generator w.r.t. ccff v2 --- libs/libarchopenfpga/src/config_protocol.cpp | 40 ++++++++++++---- .../src/read_xml_config_protocol.cpp | 30 +++++++++++- .../fabric/build_top_module_connection.cpp | 46 +++++++++++++++++++ .../src/fabric/build_top_module_connection.h | 2 + 4 files changed, 107 insertions(+), 11 deletions(-) diff --git a/libs/libarchopenfpga/src/config_protocol.cpp b/libs/libarchopenfpga/src/config_protocol.cpp index 7a3d59cf4..cc6031b0f 100644 --- a/libs/libarchopenfpga/src/config_protocol.cpp +++ b/libs/libarchopenfpga/src/config_protocol.cpp @@ -26,10 +26,14 @@ CircuitModelId ConfigProtocol::memory_model() const { return memory_model_; } int ConfigProtocol::num_regions() const { return num_regions_; } -std::vector ConfigProtocol::prog_clock_ports() const { +std::vector ConfigProtocol::prog_clock_port_info() const { + return prog_clk_port_; +} + +std::vector ConfigProtocol::prog_clock_pins() const { std::vector keys; - for (const auto& [k, v] : prog_clk_ccff_head_indices_) { - keys.push_back(k); + for (auto pin : prog_clk_port_.pins()) { + keys.push_back(openfpga::BasicPort(prog_clk_port_.get_name(), pin, pin)); } return keys; } @@ -52,11 +56,15 @@ std::string ConfigProtocol::prog_clock_port_ccff_head_indices_str( std::vector ConfigProtocol::prog_clock_port_ccff_head_indices( const openfpga::BasicPort& port) const { std::vector ret; - auto result = prog_clk_ccff_head_indices_.find(port); - if (result != prog_clk_ccff_head_indices_.end()) { - return result->second; + if (port.get_width() != 1) { + VTR_LOG_ERROR("The programming clock pin must have a width of 1 while the width specified is %ld!\n", port.get_width()); } - return ret; + VTR_ASSERT(port.get_width == 1); + if (!prog_clk_port_.contained(port)) { + VTR_LOG_ERROR("The programming clock pin '%s[%ld]' is not out of the range [%ld, %ld]!\n", port.get_name().c_str(), port.get_lsb(), prog_clk_port_.get_lsb(), prog_clk_port_.get_msb()); + } + VTR_ASSERT(prog_clk_port_.contained(port)); + return prog_clk_ccff_head_indices_[port.get_lsb()]; } e_blwl_protocol_type ConfigProtocol::bl_protocol_type() const { @@ -107,6 +115,11 @@ void ConfigProtocol::set_num_regions(const int& num_regions) { num_regions_ = num_regions; } +void ConfigProtocol::set_prog_clock(const openfpga::BasicPort& port) { + prog_clk_port_ = port; + prog_clk_ccff_head_indices_.resize(prog_clk_port_.get_width()); +} + void ConfigProtocol::set_prog_clock_port_ccff_head_indices_pair( const openfpga::BasicPort& port, const std::string& indices_str) { openfpga::StringToken tokenizer(indices_str); @@ -115,15 +128,22 @@ void ConfigProtocol::set_prog_clock_port_ccff_head_indices_pair( for (std::string token : tokenizer.split(INDICE_STRING_DELIM_)) { token_int.push_back(std::stoi(token)); } - auto result = prog_clk_ccff_head_indices_.find(port); - if (result != prog_clk_ccff_head_indices_.end()) { + if (port.get_width() != 1) { + VTR_LOG_ERROR("The programming clock pin must have a width of 1 while the width specified is %ld!\n", port.get_width()); + } + VTR_ASSERT(port.get_width == 1); + if (!prog_clk_port_.contained(port)) { + VTR_LOG_ERROR("The programming clock pin '%s[%ld]' is not out of the range [%ld, %ld]!\n", port.get_name().c_str(), port.get_lsb(), prog_clk_port_.get_lsb(), prog_clk_port_.get_msb()); + } + VTR_ASSERT(prog_clk_port_.contained(port)); + if (!prog_clk_ccff_head_indices_[port.get_lsb()].empty()) { VTR_LOG_WARN( "Overwrite the pair between programming clock port '%s[%d:%d]' and ccff " "head indices (previous: '%s', current: '%s')!\n", port.get_name().c_str(), port.get_lsb(), port.get_msb(), prog_clock_port_ccff_head_indices_str(port).c_str(), indices_str.c_str()); } - prog_clk_ccff_head_indices_[port] = token_int; + prog_clk_ccff_head_indices_[port.get_lsb()] = token_int; } void ConfigProtocol::set_bl_protocol_type(const e_blwl_protocol_type& type) { diff --git a/libs/libarchopenfpga/src/read_xml_config_protocol.cpp b/libs/libarchopenfpga/src/read_xml_config_protocol.cpp index 29580d123..3ac930bad 100644 --- a/libs/libarchopenfpga/src/read_xml_config_protocol.cpp +++ b/libs/libarchopenfpga/src/read_xml_config_protocol.cpp @@ -181,11 +181,39 @@ static void read_xml_config_organization(pugi::xml_node& xml_config_orgz, /* Parse Configuration chain protocols */ if (config_protocol.type() == CONFIG_MEM_SCAN_CHAIN) { + /* First pass: Get the programming clock port size */ + openfpga::BasicPort prog_clk_port; for (pugi::xml_node xml_progclk : xml_config_orgz.children()) { /* Error out if the XML child has an invalid name! */ if (xml_progclk.name() != std::string(XML_CONFIG_PROTOCOL_CCFF_PROG_CLOCK_NODE_NAME)) { - bad_tag(xml_progclk, loc_data, xml_config_orgz, {"programming_clock"}); + bad_tag(xml_progclk, loc_data, xml_config_orgz, {XML_CONFIG_PROTOCOL_CCFF_PROG_CLOCK_NODE_NAME}); + } + std::string port_attr = + get_attribute(xml_progclk, XML_CONFIG_PROTOCOL_CCFF_PROG_CLOCK_PORT_ATTR, + loc_data) + .as_string(); + openfpga::BasicPort port = openfpga::PortParser(port_attr).port(); + if (prog_clk_port.get_name().empty()) { + prog_clk_port.set_name(port.get_name()); + prog_clk_port.set_width(port.get_lsb(), port.get_msb()); + } else { + if (prog_clk_port.get_name() != port.get_name()) { + archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_progclk), + "Expect same name for all the programming clocks (This: %s, Others: %s)!\n", port.get_name().c_str(), prog_clk_port.get_name().c_str()); + } + if (prog_clk_port.get_msb() < port.get_msb()) { + prog_clk_port.set_msb(port.get_msb()); + } + } + } + + /* Second pass: fill the clock detailed connections */ + for (pugi::xml_node xml_progclk : xml_config_orgz.children()) { + /* Error out if the XML child has an invalid name! */ + if (xml_progclk.name() != + std::string(XML_CONFIG_PROTOCOL_CCFF_PROG_CLOCK_NODE_NAME)) { + bad_tag(xml_progclk, loc_data, xml_config_orgz, {XML_CONFIG_PROTOCOL_CCFF_PROG_CLOCK_NODE_NAME}); } read_xml_ccff_prog_clock(xml_progclk, loc_data, config_protocol); } diff --git a/openfpga/src/fabric/build_top_module_connection.cpp b/openfpga/src/fabric/build_top_module_connection.cpp index 18b4f2ee9..0b51e7f06 100644 --- a/openfpga/src/fabric/build_top_module_connection.cpp +++ b/openfpga/src/fabric/build_top_module_connection.cpp @@ -1269,4 +1269,50 @@ int add_top_module_global_ports_from_grid_modules( return status; } +/******************************************************************** + * Build the connection between the programming clock port at the top module and each configurable children + * Note that each programming clock pin drive one or more configuration regions + * For example: + * - pin[0] -> region 0, 1 + * - pin[1] -> region 2, 3 + *******************************************************************/ +void add_top_module_nets_prog_clock(ModuleManager& module_manager, + const ModuleId& top_module, + const ModulePortId& src_port, + const ConfigProtocol& config_protocol) { + BasicPort src_port_info = module_manager.module_port(top_module, src_port); + for (size_t pin : src_port_info.pins()) { + /* Create the net */ + ModuleNetId net = create_module_source_pin_net( + module_manager, top_module, top_module, 0, + src_port, src_port_info.pins()[pin_id]); + /* Find all the sink nodes and build the connection one by one */ + for (size_t iregion : config_protocol.prog_clock_port_ccff_head_indices(BasicPort(src_port_info.get_name(), pin, pin))) { + ConfigRegionId config_region = ConfigRegionId(iregion); + for (size_t mem_index = 0; mem_index < module_manager + .region_configurable_children( + top_module, config_region) + .size(); + ++mem_index) { + ModuleId net_sink_module_id = module_manager.region_configurable_children( + top_module, config_region)[mem_index]; + size_t net_sink_instance_id = + module_manager.region_configurable_child_instances( + top_module, config_region)[mem_index]; + ModulePortId net_sink_port_id = + module_manager.find_module_port(net_sink_module_id, src_port_info.get_name()); + BasicPort net_sink_port = + module_manager.module_port(net_sink_module_id, net_sink_port_id); + VTR_ASSERT(1 == net_sink_port.get_width()); + for (size_t net_sink_pin_id : net_sink_port.pins()) { + /* Add net sink */ + module_manager.add_module_net_sink(top_module, net, net_sink_module_id, + net_sink_instance_id, net_sink_port_id, + net_sink_port.pins()[net_sink_pin_id]) + } + } + } + } +} + } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/build_top_module_connection.h b/openfpga/src/fabric/build_top_module_connection.h index 908e6cfdc..66b96abab 100644 --- a/openfpga/src/fabric/build_top_module_connection.h +++ b/openfpga/src/fabric/build_top_module_connection.h @@ -41,6 +41,8 @@ int add_top_module_global_ports_from_grid_modules( const vtr::Matrix& grid_instance_ids, const ClockNetwork& clk_ntwk, const RRClockSpatialLookup& rr_clock_lookup); +void add_top_module_nets_prog_clock(ModuleManager& module_manager, const ModuleId& top_module, const ModulePortId& src_port, const ConfigProtocol& config_protocol); + } /* end namespace openfpga */ #endif