From 1ca28298687c4f74c697f7cecf188de45706651a Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 17 Aug 2020 13:54:26 -0600 Subject: [PATCH 01/31] update readme for vpr architecture naming --- openfpga_flow/vpr_arch/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/openfpga_flow/vpr_arch/README.md b/openfpga_flow/vpr_arch/README.md index e56ccca4b..aad2c1421 100644 --- a/openfpga_flow/vpr_arch/README.md +++ b/openfpga_flow/vpr_arch/README.md @@ -1,17 +1,17 @@ # Naming convention for VPR architecture files Please reveal the following architecture features in the names to help quickly spot architecture files. -- k: Look-Up Table (LUT) size of FPGA. If you have fracturable LUTs or multiple LUT circuits, this should be largest input size. -- frac: If fracturable LUT is used or not. +- k\_: Look-Up Table (LUT) size of FPGA. If you have fracturable LUTs or multiple LUT circuits, this should be largest input size. The keyword 'frac' is to specify if fracturable LUT is used or not. - N: Number of logic elements for a CLB. If you have multiple CLB architectures, this should be largest number. - tileable: If the routing architecture is tileable or not. - adder\_chain: If hard adder/carry chain is used inside CLBs - register\_chain: If shift register chain is used inside CLBs - scan\_chain: If scan chain testing infrastructure is used inside CLBs -- \_mem: If block RAM (BRAM) is used or not. If used, the memory size should be clarified here. The keyword wide is to specify if the BRAM spanns more than 1 column. +- \_\_mem: If block RAM (BRAM) is used or not. If used, the memory size should be clarified here. The keyword 'wide' is to specify if the BRAM spans more than 1 column. The keyword 'frac' is to specify if the BRAM is fracturable to operate in different modes. +- \_\_dsp: If Digital Signal Processor (DSP) is used or not. If used, the input size should be clarified here. The keyword 'wide' is to specify if the DSP spans more than 1 column. The keyword 'frac' is to specify if the DSP is fracturable to operate in different modes. - aib: If the Advanced Interface Bus (AIB) is used in place of some I/Os. - multi\_io\_capacity: If I/O capacity is different on each side of FPGAs. - reduced\_io: If I/Os only appear a certain or multiple sides of FPGAs -- : The technology node which the delay numbers are extracted from. +- : The technology node which the delay numbers are extracted from. Other features are used in naming should be listed here. From cfd035bf8f3a0c65634c02ffeff4373ef8012656 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 17 Aug 2020 14:33:51 -0600 Subject: [PATCH 02/31] update tutorials about the verilog-to-verification --- docs/source/tutorials/design_flow/index.rst | 4 ++-- .../design_flow/{verilog_to_gds2.rst => verilog2gds2.rst} | 0 .../{blif_to_verification.rst => verilog2verification.rst} | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) rename docs/source/tutorials/design_flow/{verilog_to_gds2.rst => verilog2gds2.rst} (100%) rename docs/source/tutorials/design_flow/{blif_to_verification.rst => verilog2verification.rst} (98%) diff --git a/docs/source/tutorials/design_flow/index.rst b/docs/source/tutorials/design_flow/index.rst index e854a08c6..82a9ed3e4 100644 --- a/docs/source/tutorials/design_flow/index.rst +++ b/docs/source/tutorials/design_flow/index.rst @@ -7,6 +7,6 @@ Design Flows .. toctree:: :maxdepth: 2 - blif_to_verification + verilog2verification - verilog_to_gds2 + verilog2gds2 diff --git a/docs/source/tutorials/design_flow/verilog_to_gds2.rst b/docs/source/tutorials/design_flow/verilog2gds2.rst similarity index 100% rename from docs/source/tutorials/design_flow/verilog_to_gds2.rst rename to docs/source/tutorials/design_flow/verilog2gds2.rst diff --git a/docs/source/tutorials/design_flow/blif_to_verification.rst b/docs/source/tutorials/design_flow/verilog2verification.rst similarity index 98% rename from docs/source/tutorials/design_flow/blif_to_verification.rst rename to docs/source/tutorials/design_flow/verilog2verification.rst index 26a0b87cf..505aa39c7 100644 --- a/docs/source/tutorials/design_flow/blif_to_verification.rst +++ b/docs/source/tutorials/design_flow/verilog2verification.rst @@ -1,7 +1,7 @@ -.. _from_blif_to_verification: +.. _from_verilog_to_verification: -From BLIF to Verification -------------------------- +From Verilog to Verification +---------------------------- This tutorial will show an example how to - generate Verilog netlists for a FPGA fabric From f833e0ec66df540ea108108dfb9e1e17b34e453b Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 17 Aug 2020 17:49:51 -0600 Subject: [PATCH 03/31] add a flagship architecture using fracturable memory and dsp --- ...n_frac_mem32K_frac_dsp36_40nm_openfpga.xml | 451 +++++ ...dder_chain_frac_mem32K_frac_dsp36_40nm.xml | 1578 +++++++++++++++++ 2 files changed, 2029 insertions(+) create mode 100644 openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_frac_mem32K_frac_dsp36_40nm_openfpga.xml create mode 100644 openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_frac_mem32K_frac_dsp36_40nm.xml diff --git a/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_frac_mem32K_frac_dsp36_40nm_openfpga.xml b/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_frac_mem32K_frac_dsp36_40nm_openfpga.xml new file mode 100644 index 000000000..d47e396ee --- /dev/null +++ b/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_frac_mem32K_frac_dsp36_40nm_openfpga.xml @@ -0,0 +1,451 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + + + + 10e-12 5e-12 + + + 10e-12 5e-12 + + + + + + + + + + + + + 10e-12 5e-12 5e-12 + + + 10e-12 5e-12 5e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_frac_mem32K_frac_dsp36_40nm.xml b/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_frac_mem32K_frac_dsp36_40nm.xml new file mode 100644 index 000000000..6acc37ba2 --- /dev/null +++ b/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_frac_mem32K_frac_dsp36_40nm.xml @@ -0,0 +1,1578 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + io.outpad io.inpad + io.outpad io.inpad + io.outpad io.inpad + io.outpad io.inpad + + + + + + + + + + + + + + + + + + + clb.clk + clb.cin + clb.O[9:0] clb.I[19:0] + clb.cout clb.O[19:10] clb.I[39:20] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 1 1 1 1 + 1 1 1 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 235e-12 + 235e-12 + 235e-12 + 235e-12 + 235e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 195e-12 + 195e-12 + 195e-12 + 195e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 261e-12 + 261e-12 + 261e-12 + 261e-12 + 261e-12 + 261e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 2712c354a9ea80e194932c53341a54c221d480ec Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 18 Aug 2020 12:38:56 -0600 Subject: [PATCH 04/31] now physical pb_port binding support multiple ports --- .../src/pb_type_annotation.cpp | 63 ++++++------ .../libarchopenfpga/src/pb_type_annotation.h | 13 ++- .../src/read_xml_pb_type_annotation.cpp | 38 +++++++- .../src/write_xml_pb_type_annotation.cpp | 21 +++- .../libopenfpgautil/src/openfpga_port.cpp | 10 ++ .../libopenfpgautil/src/openfpga_port.h | 1 + openfpga/src/annotation/annotate_pb_graph.cpp | 58 +++++------ openfpga/src/annotation/annotate_pb_types.cpp | 50 +++++----- .../annotation/check_pb_type_annotation.cpp | 2 +- .../src/annotation/vpr_device_annotation.cpp | 97 +++++++++++-------- .../src/annotation/vpr_device_annotation.h | 30 +++--- 11 files changed, 239 insertions(+), 144 deletions(-) diff --git a/libopenfpga/libarchopenfpga/src/pb_type_annotation.cpp b/libopenfpga/libarchopenfpga/src/pb_type_annotation.cpp index b38796c9c..133ee000c 100644 --- a/libopenfpga/libarchopenfpga/src/pb_type_annotation.cpp +++ b/libopenfpga/libarchopenfpga/src/pb_type_annotation.cpp @@ -1,6 +1,7 @@ /************************************************************************ * Member functions for class PbTypeAnnotation ***********************************************************************/ +#include #include "vtr_log.h" #include "vtr_assert.h" #include "pb_type_annotation.h" @@ -85,24 +86,15 @@ std::vector PbTypeAnnotation::port_names() const { return keys; } -BasicPort PbTypeAnnotation::physical_pb_type_port(const std::string& port_name) const { - std::map::const_iterator it = operating_pb_type_ports_.find(port_name); +std::map PbTypeAnnotation::physical_pb_type_port(const std::string& port_name) const { + std::map>::const_iterator it = operating_pb_type_ports_.find(port_name); if (it == operating_pb_type_ports_.end()) { /* Return an empty port */ - return BasicPort(); + return std::map(); } return operating_pb_type_ports_.at(port_name); } -int PbTypeAnnotation::physical_pin_rotate_offset(const std::string& port_name) const { - std::map::const_iterator it = physical_pin_rotate_offsets_.find(port_name); - if (it == physical_pin_rotate_offsets_.end()) { - /* Return a zero offset which is default */ - return 0; - } - return physical_pin_rotate_offsets_.at(port_name); -} - std::vector PbTypeAnnotation::interconnect_names() const { std::vector keys; for (auto const& element : interconnect_circuit_model_names_) { @@ -177,27 +169,42 @@ void PbTypeAnnotation::set_physical_pb_type_index_offset(const int& value) { void PbTypeAnnotation::add_pb_type_port_pair(const std::string& operating_pb_port_name, const BasicPort& physical_pb_port) { /* Give a warning if the operating_pb_port_name already exist */ - std::map::const_iterator it = operating_pb_type_ports_.find(operating_pb_port_name); - /* Give a warning if the interconnection name already exist */ - if (it != operating_pb_type_ports_.end()) { - VTR_LOG_WARN("Redefine operating pb type port '%s' with physical pb type port '%s'\n", - operating_pb_port_name.c_str(), physical_pb_port.get_name().c_str()); - } + std::map>::const_iterator it = operating_pb_type_ports_.find(operating_pb_port_name); - operating_pb_type_ports_[operating_pb_port_name] = physical_pb_port; -} - -void PbTypeAnnotation::set_physical_pin_rotate_offset(const std::string& operating_pb_port_name, - const int& physical_pin_rotate_offset) { - std::map::const_iterator it = operating_pb_type_ports_.find(operating_pb_port_name); - /* Give a warning if the interconnection name already exist */ + /* If not exist, initialize and set a default value */ if (it == operating_pb_type_ports_.end()) { - VTR_LOG_ERROR("Operating pb type port '%s' does not exist! Ignore physical pin rotate offset '%d'\n", - operating_pb_port_name.c_str(), physical_pin_rotate_offset); + operating_pb_type_ports_[operating_pb_port_name][physical_pb_port] = 0; + /* We can return early */ return; } - physical_pin_rotate_offsets_[operating_pb_port_name] = physical_pin_rotate_offset; + /* If the physical port is not in the list, we create one and set a default value */ + if (0 == operating_pb_type_ports_[operating_pb_port_name].count(physical_pb_port)) { + operating_pb_type_ports_[operating_pb_port_name][physical_pb_port] = 0; + } +} + +void PbTypeAnnotation::set_physical_pin_rotate_offset(const std::string& operating_pb_port_name, + const BasicPort& physical_pb_port, + const int& physical_pin_rotate_offset) { + std::map>::const_iterator it = operating_pb_type_ports_.find(operating_pb_port_name); + + if (it == operating_pb_type_ports_.end()) { + VTR_LOG_ERROR("The operating pb_type port '%s' is not valid!\n", + operating_pb_port_name.c_str()); + exit(1); + } + + if (operating_pb_type_ports_[operating_pb_port_name].end() == operating_pb_type_ports_[operating_pb_port_name].find(physical_pb_port)) { + VTR_LOG_ERROR("The physical pb_type port '%s[%lu:%lu]' definition for operating pb_type port '%s' is not valid!\n", + physical_pb_port.get_name().c_str(), + physical_pb_port.get_lsb(), + physical_pb_port.get_msb(), + operating_pb_port_name.c_str()); + exit(1); + } + + operating_pb_type_ports_[operating_pb_port_name][physical_pb_port] = physical_pin_rotate_offset; } void PbTypeAnnotation::add_interconnect_circuit_model_pair(const std::string& interc_name, diff --git a/libopenfpga/libarchopenfpga/src/pb_type_annotation.h b/libopenfpga/libarchopenfpga/src/pb_type_annotation.h index e80acc3dc..4e1d4e8a2 100644 --- a/libopenfpga/libarchopenfpga/src/pb_type_annotation.h +++ b/libopenfpga/libarchopenfpga/src/pb_type_annotation.h @@ -48,8 +48,7 @@ class PbTypeAnnotation { float physical_pb_type_index_factor() const; int physical_pb_type_index_offset() const; std::vector port_names() const; - BasicPort physical_pb_type_port(const std::string& port_name) const; - int physical_pin_rotate_offset(const std::string& port_name) const; + std::map physical_pb_type_port(const std::string& port_name) const; std::vector interconnect_names() const; std::string interconnect_circuit_model_name(const std::string& interc_name) const; public: /* Public mutators */ @@ -68,6 +67,7 @@ class PbTypeAnnotation { void add_pb_type_port_pair(const std::string& operating_pb_port_name, const BasicPort& physical_pb_port); void set_physical_pin_rotate_offset(const std::string& operating_pb_port_name, + const BasicPort& physical_pb_port, const int& physical_pin_rotate_offset); void add_interconnect_circuit_model_pair(const std::string& interc_name, const std::string& circuit_model_name); @@ -133,10 +133,9 @@ class PbTypeAnnotation { */ int physical_pb_type_index_offset_; - /* Link from the pins under an operating pb_type to physical pb_type */ - std::map operating_pb_type_ports_; - - /* The offset aims to align the pin indices for port of pb_type + /* Link from the pins under an operating pb_type to pairs of + * its physical pb_type and its pin rotating offset + * The offset aims to align the pin indices for port of pb_type * between operating and physical modes, especially when an operating * mode contains multiple pb_type (num_pb>1) that are linked to * the same physical pb_type. @@ -148,7 +147,7 @@ class PbTypeAnnotation { * operating pb_type adder[0].pin[0] with a full path clb.fle[arith].adder[0] * to physical pb_type adder[0].pin[1] with a full path clb.fle[physical].adder[0] */ - std::map physical_pin_rotate_offsets_; + std::map> operating_pb_type_ports_; /* Link between the interconnects under this pb_type and circuit model names */ std::map interconnect_circuit_model_names_; diff --git a/libopenfpga/libarchopenfpga/src/read_xml_pb_type_annotation.cpp b/libopenfpga/libarchopenfpga/src/read_xml_pb_type_annotation.cpp index 743e23741..a4d25e1cf 100644 --- a/libopenfpga/libarchopenfpga/src/read_xml_pb_type_annotation.cpp +++ b/libopenfpga/libarchopenfpga/src/read_xml_pb_type_annotation.cpp @@ -55,12 +55,40 @@ void read_xml_pb_port_annotation(pugi::xml_node& xml_port, const std::string& name_attr = get_attribute(xml_port, "name", loc_data).as_string(); const std::string& physical_mode_port_attr = get_attribute(xml_port, "physical_mode_port", loc_data).as_string(); - /* Parse the mode port using openfpga port parser */ - openfpga::PortParser port_parser(physical_mode_port_attr); - pb_type_annotation.add_pb_type_port_pair(name_attr, port_parser.port()); + /* Split the physical mode port attributes with space */ + openfpga::StringToken port_tokenizer(physical_mode_port_attr); + const std::vector physical_mode_ports = port_tokenizer.split(); - /* We have an optional attribute: physical_mode_pin_rotate_offset */ - pb_type_annotation.set_physical_pin_rotate_offset(name_attr, get_attribute(xml_port, "physical_mode_pin_rotate_offset", loc_data, pugiutil::ReqOpt::OPTIONAL).as_int(0)); + /* Parse the mode port using openfpga port parser */ + for (const auto& physical_mode_port : physical_mode_ports) { + openfpga::PortParser port_parser(physical_mode_port); + pb_type_annotation.add_pb_type_port_pair(name_attr, port_parser.port()); + } + + /* We have an optional attribute: physical_mode_pin_rotate_offset + * Split based on the number of physical pb_type ports that have been defined + */ + const std::string& physical_pin_rotate_offset_attr = get_attribute(xml_port, "physical_mode_pin_rotate_offset", loc_data, pugiutil::ReqOpt::OPTIONAL).as_string(); + + if (false == physical_pin_rotate_offset_attr.empty()) { + /* Split the physical mode port attributes with space */ + openfpga::StringToken offset_tokenizer(physical_pin_rotate_offset_attr); + const std::vector rotate_offsets = offset_tokenizer.split(); + + /* Error out if the offset does not match the port definition */ + if (physical_mode_ports.size() != rotate_offsets.size()) { + archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_port), + "Defined %lu physical mode ports but only %lu physical pin rotate offset are defined! Expect size matching.\n", + physical_mode_ports.size(), rotate_offsets.size()); + } + + for (size_t iport = 0; iport < physical_mode_ports.size(); ++iport) { + openfpga::PortParser port_parser(physical_mode_ports[iport]); + pb_type_annotation.set_physical_pin_rotate_offset(name_attr, + port_parser.port(), + std::stoi(rotate_offsets[iport])); + } + } } /******************************************************************** diff --git a/libopenfpga/libarchopenfpga/src/write_xml_pb_type_annotation.cpp b/libopenfpga/libarchopenfpga/src/write_xml_pb_type_annotation.cpp index 531e117f1..b013e5801 100644 --- a/libopenfpga/libarchopenfpga/src/write_xml_pb_type_annotation.cpp +++ b/libopenfpga/libarchopenfpga/src/write_xml_pb_type_annotation.cpp @@ -116,8 +116,25 @@ void write_xml_pb_port_annotation(std::fstream& fp, fp << "\t\t\t" << "" << "\n"; } diff --git a/libopenfpga/libopenfpgautil/src/openfpga_port.cpp b/libopenfpga/libopenfpgautil/src/openfpga_port.cpp index 7e7cc4007..023af7618 100644 --- a/libopenfpga/libopenfpgautil/src/openfpga_port.cpp +++ b/libopenfpga/libopenfpgautil/src/openfpga_port.cpp @@ -124,6 +124,16 @@ bool BasicPort::operator== (const BasicPort& portA) const { return false; } +bool BasicPort::operator< (const BasicPort& portA) const { + if ( (0 == this->get_name().compare(portA.get_name())) + && (this->get_lsb() < portA.get_lsb()) + && (this->get_msb() < portA.get_msb()) ) { + return true; + } + return false; +} + + /************************************************************************ * Mutators ***********************************************************************/ diff --git a/libopenfpga/libopenfpgautil/src/openfpga_port.h b/libopenfpga/libopenfpgautil/src/openfpga_port.h index d870e94fc..ca1afb4a5 100644 --- a/libopenfpga/libopenfpgautil/src/openfpga_port.h +++ b/libopenfpga/libopenfpgautil/src/openfpga_port.h @@ -21,6 +21,7 @@ class BasicPort { BasicPort(const BasicPort& basic_port); /* Copy constructor */ public: /* Overloaded operators */ bool operator== (const BasicPort& portA) const; + bool operator< (const BasicPort& portA) const; public: /* Accessors */ size_t get_width() const; /* get the port width */ size_t get_msb() const; /* get the LSB */ diff --git a/openfpga/src/annotation/annotate_pb_graph.cpp b/openfpga/src/annotation/annotate_pb_graph.cpp index 081acf900..93a154222 100644 --- a/openfpga/src/annotation/annotate_pb_graph.cpp +++ b/openfpga/src/annotation/annotate_pb_graph.cpp @@ -306,35 +306,37 @@ bool try_match_pb_graph_pin(t_pb_graph_pin* operating_pb_graph_pin, t_pb_graph_pin* physical_pb_graph_pin, const VprDeviceAnnotation& vpr_device_annotation) { /* If the parent ports of the two pins are not paired, fail */ - if (physical_pb_graph_pin->port != vpr_device_annotation.physical_pb_port(operating_pb_graph_pin->port)) { - return false; - } - /* Check the pin number of physical pb_graph_pin matches the pin number of - * operating pb_graph_pin plus a rotation offset - * operating port physical port - * LSB port_range.lsb() pin_number pin_number MSB - * | | | - * Operating port | | +------ | - * | |<----offset--->| - * Physical port | + + + - * - * Note: - * - accumulated offset is NOT the pin rotate offset specified by users - * It is an aggregation of the offset during pin pairing - * Each time, we manage to pair two pins, the accumulated offset will be incremented - * by the pin rotate offset value - * The accumulated offset will be reset to 0 when it exceeds the msb() of the physical port - */ - int acc_offset = vpr_device_annotation.physical_pb_pin_offset(operating_pb_graph_pin->port); - const BasicPort& physical_port_range = vpr_device_annotation.physical_pb_port_range(operating_pb_graph_pin->port); - if (physical_pb_graph_pin->pin_number != operating_pb_graph_pin->pin_number - + (int)physical_port_range.get_lsb() - + acc_offset) { - return false; - } + for (t_port* candidate_port : vpr_device_annotation.physical_pb_port(operating_pb_graph_pin->port)) { + if (physical_pb_graph_pin->port != candidate_port) { + return false; + } + /* Check the pin number of physical pb_graph_pin matches the pin number of + * operating pb_graph_pin plus a rotation offset + * operating port physical port + * LSB port_range.lsb() pin_number pin_number MSB + * | | | + * Operating port | | +------ | + * | |<----offset--->| + * Physical port | + + + + * + * Note: + * - accumulated offset is NOT the pin rotate offset specified by users + * It is an aggregation of the offset during pin pairing + * Each time, we manage to pair two pins, the accumulated offset will be incremented + * by the pin rotate offset value + * The accumulated offset will be reset to 0 when it exceeds the msb() of the physical port + */ + int acc_offset = vpr_device_annotation.physical_pb_pin_offset(operating_pb_graph_pin->port, candidate_port); + const BasicPort& physical_port_range = vpr_device_annotation.physical_pb_port_range(operating_pb_graph_pin->port, candidate_port); + if (physical_pb_graph_pin->pin_number != operating_pb_graph_pin->pin_number + + (int)physical_port_range.get_lsb() + + acc_offset) { + return false; + } - /* Reach here, it means all the requirements have been met */ - return true; + /* Reach here, it means all the requirements have been met */ + return true; + } } /******************************************************************** diff --git a/openfpga/src/annotation/annotate_pb_types.cpp b/openfpga/src/annotation/annotate_pb_types.cpp index d8701be78..cb6c9e9b3 100644 --- a/openfpga/src/annotation/annotate_pb_types.cpp +++ b/openfpga/src/annotation/annotate_pb_types.cpp @@ -211,32 +211,38 @@ bool pair_operating_and_physical_pb_types(t_pb_type* operating_pb_type, * if not found, we assume that the physical port is the same as the operating pb_port */ for (t_port* operating_pb_port : pb_type_ports(operating_pb_type)) { - /* Try to find the port in the pb_type_annotation */ - BasicPort expected_physical_pb_port = pb_type_annotation.physical_pb_type_port(std::string(operating_pb_port->name)); - if (true == expected_physical_pb_port.get_name().empty()) { - /* Not found, we reset the port information to be consistent as the operating pb_port */ + std::map expected_physical_pb_ports = pb_type_annotation.physical_pb_type_port(std::string(operating_pb_port->name)); + + /* If not defined in the annotation, set the default pair: + * rotate_offset is 0 by default! + */ + if (true == expected_physical_pb_ports.empty()) { + BasicPort expected_physical_pb_port; expected_physical_pb_port.set_name(std::string(operating_pb_port->name)); expected_physical_pb_port.set_width(operating_pb_port->num_pins); + expected_physical_pb_ports[expected_physical_pb_port] = 0; } - /* Try to find the expected port in the physical pb_type */ - t_port* physical_pb_port = find_pb_type_port(physical_pb_type, expected_physical_pb_port.get_name()); - /* Not found, mapping fails */ - if (nullptr == physical_pb_port) { - return false; + for (const auto& expected_physical_pb_port : expected_physical_pb_ports) { + /* Try to find the expected port in the physical pb_type */ + t_port* physical_pb_port = find_pb_type_port(physical_pb_type, expected_physical_pb_port.first.get_name()); + /* Not found, mapping fails */ + if (nullptr == physical_pb_port) { + return false; + } + /* If the port range does not match, mapping fails */ + if (false == BasicPort(physical_pb_port->name, physical_pb_port->num_pins).contained(expected_physical_pb_port.first)) { + return false; + } + /* Now, port mapping should succeed, we update the vpr_device_annotation + * - port binding + * - port range + * - port pin rotate offset + */ + vpr_device_annotation.add_physical_pb_port(operating_pb_port, physical_pb_port); + vpr_device_annotation.add_physical_pb_port_range(operating_pb_port, physical_pb_port, expected_physical_pb_port.first); + vpr_device_annotation.add_physical_pb_pin_rotate_offset(operating_pb_port, physical_pb_port, expected_physical_pb_port.second); } - /* If the port range does not match, mapping fails */ - if (false == BasicPort(physical_pb_port->name, physical_pb_port->num_pins).contained(expected_physical_pb_port)) { - return false; - } - /* Now, port mapping should succeed, we update the vpr_device_annotation - * - port binding - * - port range - * - port pin rotate offset - */ - vpr_device_annotation.add_physical_pb_port(operating_pb_port, physical_pb_port); - vpr_device_annotation.add_physical_pb_port_range(operating_pb_port, expected_physical_pb_port); - vpr_device_annotation.add_physical_pb_pin_rotate_offset(operating_pb_port, pb_type_annotation.physical_pin_rotate_offset(std::string(operating_pb_port->name))); } /* Now, pb_type mapping should succeed, we update the vpr_device_annotation @@ -365,7 +371,7 @@ bool self_pair_physical_pb_types(t_pb_type* physical_pb_type, for (t_port* physical_pb_port : pb_type_ports(physical_pb_type)) { BasicPort physical_port_range(physical_pb_port->name, physical_pb_port->num_pins); vpr_device_annotation.add_physical_pb_port(physical_pb_port, physical_pb_port); - vpr_device_annotation.add_physical_pb_port_range(physical_pb_port, physical_port_range); + vpr_device_annotation.add_physical_pb_port_range(physical_pb_port, physical_pb_port, physical_port_range); } /* Now, pb_type mapping should succeed, we update the vpr_device_annotation */ diff --git a/openfpga/src/annotation/check_pb_type_annotation.cpp b/openfpga/src/annotation/check_pb_type_annotation.cpp index 5159ec064..d0709c81c 100644 --- a/openfpga/src/annotation/check_pb_type_annotation.cpp +++ b/openfpga/src/annotation/check_pb_type_annotation.cpp @@ -114,7 +114,7 @@ void check_vpr_physical_primitive_pb_type_annotation(t_pb_type* cur_pb_type, /* Now we need to check each port of the pb_type */ for (t_port* pb_port : pb_type_ports(cur_pb_type)) { - if (nullptr == vpr_device_annotation.physical_pb_port(pb_port)) { + if (0 == vpr_device_annotation.physical_pb_port(pb_port).size()) { VTR_LOG_ERROR("Find a port '%s' of pb_type '%s' which has not been mapped to any physical port!\n", pb_port->name, cur_pb_type->name); VTR_LOG_ERROR("Please specify in the OpenFPGA architecture\n"); diff --git a/openfpga/src/annotation/vpr_device_annotation.cpp b/openfpga/src/annotation/vpr_device_annotation.cpp index 0787e0225..71b3baf63 100644 --- a/openfpga/src/annotation/vpr_device_annotation.cpp +++ b/openfpga/src/annotation/vpr_device_annotation.cpp @@ -48,23 +48,28 @@ t_pb_type* VprDeviceAnnotation::physical_pb_type(t_pb_type* pb_type) const { return physical_pb_types_.at(pb_type); } -t_port* VprDeviceAnnotation::physical_pb_port(t_port* pb_port) const { +std::vector VprDeviceAnnotation::physical_pb_port(t_port* pb_port) const { /* Ensure that the pb_type is in the list */ - std::map::const_iterator it = physical_pb_ports_.find(pb_port); + std::map>::const_iterator it = physical_pb_ports_.find(pb_port); if (it == physical_pb_ports_.end()) { - return nullptr; + return std::vector(); } return physical_pb_ports_.at(pb_port); } -BasicPort VprDeviceAnnotation::physical_pb_port_range(t_port* pb_port) const { +BasicPort VprDeviceAnnotation::physical_pb_port_range(t_port* operating_pb_port, + t_port* physical_pb_port) const { /* Ensure that the pb_type is in the list */ - std::map::const_iterator it = physical_pb_port_ranges_.find(pb_port); + std::map>::const_iterator it = physical_pb_port_ranges_.find(operating_pb_port); if (it == physical_pb_port_ranges_.end()) { /* Return an invalid port. As such the port width will be 0, which is an invalid value */ return BasicPort(); } - return physical_pb_port_ranges_.at(pb_port); + if (0 == physical_pb_port_ranges_.at(operating_pb_port).count(physical_pb_port)) { + /* Return an invalid port. As such the port width will be 0, which is an invalid value */ + return BasicPort(); + } + return physical_pb_port_ranges_.at(operating_pb_port).at(physical_pb_port); } CircuitModelId VprDeviceAnnotation::pb_type_circuit_model(t_pb_type* physical_pb_type) const { @@ -185,24 +190,34 @@ int VprDeviceAnnotation::physical_pb_type_index_offset(t_pb_type* pb_type) const return physical_pb_type_index_offsets_.at(pb_type); } -int VprDeviceAnnotation::physical_pb_pin_rotate_offset(t_port* pb_port) const { +int VprDeviceAnnotation::physical_pb_pin_rotate_offset(t_port* operating_pb_port, + t_port* physical_pb_port) const { /* Ensure that the pb_type is in the list */ - std::map::const_iterator it = physical_pb_pin_rotate_offsets_.find(pb_port); + std::map>::const_iterator it = physical_pb_pin_rotate_offsets_.find(operating_pb_port); if (it == physical_pb_pin_rotate_offsets_.end()) { /* Default value is 0 */ return 0; } - return physical_pb_pin_rotate_offsets_.at(pb_port); + if (0 == physical_pb_pin_rotate_offsets_.at(operating_pb_port).count(physical_pb_port)) { + /* Default value is 0 */ + return 0; + } + return physical_pb_pin_rotate_offsets_.at(operating_pb_port).at(physical_pb_port); } -int VprDeviceAnnotation::physical_pb_pin_offset(t_port* pb_port) const { +int VprDeviceAnnotation::physical_pb_pin_offset(t_port* operating_pb_port, + t_port* physical_pb_port) const { /* Ensure that the pb_type is in the list */ - std::map::const_iterator it = physical_pb_pin_offsets_.find(pb_port); + std::map>::const_iterator it = physical_pb_pin_offsets_.find(operating_pb_port); if (it == physical_pb_pin_offsets_.end()) { /* Default value is 0 */ return 0; } - return physical_pb_pin_offsets_.at(pb_port); + if (0 == physical_pb_pin_offsets_.at(operating_pb_port).count(physical_pb_port)) { + /* Default value is 0 */ + return 0; + } + return physical_pb_pin_offsets_.at(operating_pb_port).at(physical_pb_port); } @@ -274,29 +289,28 @@ void VprDeviceAnnotation::add_physical_pb_type(t_pb_type* operating_pb_type, t_p physical_pb_types_[operating_pb_type] = physical_pb_type; } -void VprDeviceAnnotation::add_physical_pb_port(t_port* operating_pb_port, t_port* physical_pb_port) { - /* Warn any override attempt */ - std::map::const_iterator it = physical_pb_ports_.find(operating_pb_port); - if (it != physical_pb_ports_.end()) { - VTR_LOG_WARN("Override the annotation between operating pb_port '%s' and it physical pb_port '%s'!\n", - operating_pb_port->name, physical_pb_port->name); - } - - physical_pb_ports_[operating_pb_port] = physical_pb_port; +void VprDeviceAnnotation::add_physical_pb_port(t_port* operating_pb_port, + t_port* physical_pb_port) { + physical_pb_ports_[operating_pb_port].push_back(physical_pb_port); } -void VprDeviceAnnotation::add_physical_pb_port_range(t_port* operating_pb_port, const BasicPort& port_range) { +void VprDeviceAnnotation::add_physical_pb_port_range(t_port* operating_pb_port, + t_port* physical_pb_port, + const BasicPort& port_range) { /* The port range must satify the port width*/ VTR_ASSERT((size_t)operating_pb_port->num_pins == port_range.get_width()); /* Warn any override attempt */ - std::map::const_iterator it = physical_pb_port_ranges_.find(operating_pb_port); - if (it != physical_pb_port_ranges_.end()) { - VTR_LOG_WARN("Override the annotation between operating pb_port '%s' and it physical pb_port range '[%ld:%ld]'!\n", - operating_pb_port->name, port_range.get_lsb(), port_range.get_msb()); + std::map>::const_iterator it = physical_pb_port_ranges_.find(operating_pb_port); + if ( (it != physical_pb_port_ranges_.end()) + && (0 < physical_pb_port_ranges_[operating_pb_port].count(physical_pb_port)) ) { + VTR_LOG_WARN("Override the annotation between operating pb_port '%s' and it physical pb_port range '%s[%ld:%ld]'!\n", + operating_pb_port->name, + physical_pb_port->name, + port_range.get_lsb(), port_range.get_msb()); } - physical_pb_port_ranges_[operating_pb_port] = port_range; + physical_pb_port_ranges_[operating_pb_port][physical_pb_port] = port_range; } void VprDeviceAnnotation::add_pb_type_circuit_model(t_pb_type* physical_pb_type, const CircuitModelId& circuit_model) { @@ -396,17 +410,20 @@ void VprDeviceAnnotation::add_physical_pb_type_index_offset(t_pb_type* pb_type, physical_pb_type_index_offsets_[pb_type] = offset; } -void VprDeviceAnnotation::add_physical_pb_pin_rotate_offset(t_port* pb_port, const int& offset) { +void VprDeviceAnnotation::add_physical_pb_pin_rotate_offset(t_port* operating_pb_port, + t_port* physical_pb_port, + const int& offset) { /* Warn any override attempt */ - std::map::const_iterator it = physical_pb_pin_rotate_offsets_.find(pb_port); - if (it != physical_pb_pin_rotate_offsets_.end()) { - VTR_LOG_WARN("Override the annotation between operating pb_port '%s' and it physical pb_port pin rotate offset '%d'!\n", - pb_port->name, offset); + std::map>::const_iterator it = physical_pb_pin_rotate_offsets_.find(operating_pb_port); + if ( (it != physical_pb_pin_rotate_offsets_.end()) + && (0 < physical_pb_pin_rotate_offsets_[operating_pb_port].count(physical_pb_port)) ) { + VTR_LOG_WARN("Override the annotation between operating pb_port '%s' and it physical pb_port '%s' pin rotate offset '%d'!\n", + operating_pb_port->name, offset); } - physical_pb_pin_rotate_offsets_[pb_port] = offset; + physical_pb_pin_rotate_offsets_[operating_pb_port][physical_pb_port] = offset; /* We initialize the accumulated offset to 0 */ - physical_pb_pin_offsets_[pb_port] = 0; + physical_pb_pin_offsets_[operating_pb_port][physical_pb_port] = 0; } void VprDeviceAnnotation::add_physical_pb_graph_pin(const t_pb_graph_pin* operating_pb_graph_pin, @@ -432,17 +449,17 @@ void VprDeviceAnnotation::add_physical_pb_graph_pin(const t_pb_graph_pin* operat * Physical port | + + + * */ - if (0 == physical_pb_pin_rotate_offset(operating_pb_graph_pin->port)) { + if (0 == physical_pb_pin_rotate_offset(operating_pb_graph_pin->port, physical_pb_graph_pin->port)) { return; } - physical_pb_pin_offsets_[operating_pb_graph_pin->port] += physical_pb_pin_rotate_offset(operating_pb_graph_pin->port); + physical_pb_pin_offsets_[operating_pb_graph_pin->port][physical_pb_graph_pin->port] += physical_pb_pin_rotate_offset(operating_pb_graph_pin->port, physical_pb_graph_pin->port); - if ((size_t)physical_pb_port(operating_pb_graph_pin->port)->num_pins - 1 + if ((size_t)physical_pb_graph_pin->port->num_pins - 1 < operating_pb_graph_pin->pin_number - + physical_pb_port_range(operating_pb_graph_pin->port).get_lsb() - + physical_pb_pin_offsets_[operating_pb_graph_pin->port]) { - physical_pb_pin_offsets_[operating_pb_graph_pin->port] = 0; + + physical_pb_port_range(operating_pb_graph_pin->port, physical_pb_graph_pin->port).get_lsb() + + physical_pb_pin_offsets_[operating_pb_graph_pin->port][physical_pb_graph_pin->port]) { + physical_pb_pin_offsets_[operating_pb_graph_pin->port][physical_pb_graph_pin->port] = 0; } } diff --git a/openfpga/src/annotation/vpr_device_annotation.h b/openfpga/src/annotation/vpr_device_annotation.h index 00209df5c..6ac9ab4b5 100644 --- a/openfpga/src/annotation/vpr_device_annotation.h +++ b/openfpga/src/annotation/vpr_device_annotation.h @@ -45,8 +45,9 @@ class VprDeviceAnnotation { bool is_physical_pb_type(t_pb_type* pb_type) const; t_mode* physical_mode(t_pb_type* pb_type) const; t_pb_type* physical_pb_type(t_pb_type* pb_type) const; - t_port* physical_pb_port(t_port* pb_port) const; - BasicPort physical_pb_port_range(t_port* pb_port) const; + std::vector physical_pb_port(t_port* pb_port) const; + BasicPort physical_pb_port_range(t_port* operating_pb_port, + t_port* physical_pb_port) const; CircuitModelId pb_type_circuit_model(t_pb_type* physical_pb_type) const; CircuitModelId interconnect_circuit_model(t_interconnect* pb_interconnect) const; e_interconnect interconnect_physical_type(t_interconnect* pb_interconnect) const; @@ -60,7 +61,8 @@ class VprDeviceAnnotation { float physical_pb_type_index_factor(t_pb_type* pb_type) const; int physical_pb_type_index_offset(t_pb_type* pb_type) const; - int physical_pb_pin_rotate_offset(t_port* pb_port) const; + int physical_pb_pin_rotate_offset(t_port* operating_pb_port, + t_port* physical_pb_port) const; /**This function returns an accumulated offset. Note that the * accumulated offset is NOT the pin rotate offset specified by users @@ -69,7 +71,8 @@ class VprDeviceAnnotation { * by the pin rotate offset value * The accumulated offset will be reset to 0 when it exceeds the msb() of the physical port */ - int physical_pb_pin_offset(t_port* pb_port) const; + int physical_pb_pin_offset(t_port* operating_pb_port, + t_port* physical_pb_port) const; t_pb_graph_pin* physical_pb_graph_pin(const t_pb_graph_pin* pb_graph_pin) const; CircuitModelId rr_switch_circuit_model(const RRSwitchId& rr_switch) const; CircuitModelId rr_segment_circuit_model(const RRSegmentId& rr_segment) const; @@ -78,8 +81,11 @@ class VprDeviceAnnotation { public: /* Public mutators */ void add_pb_type_physical_mode(t_pb_type* pb_type, t_mode* physical_mode); void add_physical_pb_type(t_pb_type* operating_pb_type, t_pb_type* physical_pb_type); - void add_physical_pb_port(t_port* operating_pb_port, t_port* physical_pb_port); - void add_physical_pb_port_range(t_port* operating_pb_port, const BasicPort& port_range); + void add_physical_pb_port(t_port* operating_pb_port, + t_port* physical_pb_port); + void add_physical_pb_port_range(t_port* operating_pb_port, + t_port* physical_pb_port, + const BasicPort& port_range); void add_pb_type_circuit_model(t_pb_type* physical_pb_type, const CircuitModelId& circuit_model); void add_interconnect_circuit_model(t_interconnect* pb_interconnect, const CircuitModelId& circuit_model); void add_interconnect_physical_type(t_interconnect* pb_interconnect, const e_interconnect& physical_type); @@ -90,7 +96,9 @@ class VprDeviceAnnotation { t_pb_graph_node* physical_pb_graph_node); void add_physical_pb_type_index_factor(t_pb_type* pb_type, const float& factor); void add_physical_pb_type_index_offset(t_pb_type* pb_type, const int& offset); - void add_physical_pb_pin_rotate_offset(t_port* pb_port, const int& offset); + void add_physical_pb_pin_rotate_offset(t_port* operating_pb_port, + t_port* physical_pb_port, + const int& offset); void add_physical_pb_graph_pin(const t_pb_graph_pin* operating_pb_graph_pin, t_pb_graph_pin* physical_pb_graph_pin); void add_rr_switch_circuit_model(const RRSwitchId& rr_switch, const CircuitModelId& circuit_model); void add_rr_segment_circuit_model(const RRSegmentId& rr_segment, const CircuitModelId& circuit_model); @@ -139,17 +147,17 @@ class VprDeviceAnnotation { * Note: * - the parent of physical pb_port MUST be a physical pb_type */ - std::map physical_pb_ports_; - std::map physical_pb_pin_rotate_offsets_; + std::map> physical_pb_ports_; + std::map> physical_pb_pin_rotate_offsets_; /* Accumulated offsets for a physical pb_type port, just for internal usage */ - std::map physical_pb_pin_offsets_; + std::map> physical_pb_pin_offsets_; /* Pair a pb_port to its LSB and MSB of a physical pb_port * Note: * - the LSB and MSB MUST be in range of the physical pb_port */ - std::map physical_pb_port_ranges_; + std::map> physical_pb_port_ranges_; /* Pair a pb_port to a circuit port in circuit model * Note: From 53f87f44b47ec19cc06cae2a92ed9d66376df1db Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 18 Aug 2020 12:44:38 -0600 Subject: [PATCH 05/31] update documentation for the multi-port support in physical pb_pin --- docs/source/manual/arch_lang/annotate_vpr_arch.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/source/manual/arch_lang/annotate_vpr_arch.rst b/docs/source/manual/arch_lang/annotate_vpr_arch.rst index 39e02269c..5a6d77b14 100644 --- a/docs/source/manual/arch_lang/annotate_vpr_arch.rst +++ b/docs/source/manual/arch_lang/annotate_vpr_arch.rst @@ -136,8 +136,12 @@ The ``circuit_model_name`` should match the given name of a ``circuit_model`` de - ``physical_mode_pin="" creates the link of ``port`` of ``pb_type`` between operating and physical modes. This syntax is mandatory for every primitive ``pb_type`` in an operating mode ``pb_type``. It should be a valid ``port`` name of leaf ``pb_type`` in physical mode and the port size should also match. + .. note:: Users can define multiple ports. For example: ``physical_mode_pin="a[0:1] b[2:2]"``. When multiple ports are used, the ``physical_mode_pin_rotate_offset`` should also be adapt. For example: ``physical_mode_pin_rotate_offset="1 0"``) + - ``physical_mode_pin_rotate_offset=""`` aims to align the pin indices for ``port`` of ``pb_type`` between operating and physical modes, especially when an operating mode contains multiple ``pb_type`` (``num_pb``>1) that are linked to the same physical ``pb_type``. When ``physical_mode_pin_rotate_offset`` is larger than zero, the pin index of ``pb_type`` (whose index is large than 1) will be shifted by the given offset. + .. note:: If not defined, the default value of ``physical_mode_pin_rotate_offset`` is set to ``0``. + .. note:: It is highly recommended that only one physical mode is defined for a multi-mode configurable block. Try not to use nested physical mode definition. This will ease the debugging and lead to clean XML description. From 21c7eaa9cff380c45266cf0653961ed1018625c2 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 18 Aug 2020 14:06:08 -0600 Subject: [PATCH 06/31] add 36-bit fracturable multiplier Verilog --- openfpga_flow/VerilogNetlists/mult_36x36.v | 35 ++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 openfpga_flow/VerilogNetlists/mult_36x36.v diff --git a/openfpga_flow/VerilogNetlists/mult_36x36.v b/openfpga_flow/VerilogNetlists/mult_36x36.v new file mode 100644 index 000000000..6fda49dd9 --- /dev/null +++ b/openfpga_flow/VerilogNetlists/mult_36x36.v @@ -0,0 +1,35 @@ +//----------------------------------------------------- +// Design Name : mult_36x36 +// File Name : mult_36x36.v +// Function : A 36-bit multiplier which can operate in fracturable modes: +// 1. four 9-bit multipliers +// 2. two 18-bit multipliers +// 3. one 36-bit multipliers +// Coder : Xifan Tang +//----------------------------------------------------- + +module mult_36x36 ( + input [0:35] a, + input [0:35] b, + output [0:71] out, + input [0:1] mode); + + reg [0:71] out_reg; + + always @(mode, a, b) begin + if (2'b01 == mode) begin + out_reg[0:17] <= a[0:8] * b[0:8]; + out_reg[18:35] <= a[9:17] * b[9:17]; + out_reg[36:53] <= a[18:26] * b[18:26]; + out_reg[54:71] <= a[27:35] * b[27:35]; + end else if (2'b10 == mode) begin + out_reg[0:35] <= a[0:17] * b[0:17]; + out_reg[36:71] <= a[18:35] * b[18:35]; + end else begin + out_reg <= a * b; + end + end + + assign out = out_reg; + +endmodule From 098859fe0671510fcb70e479c5fed75a49ac9e63 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 18 Aug 2020 15:05:51 -0600 Subject: [PATCH 07/31] bug fix in the frac memory & DSP architecture --- ...n_frac_mem32K_frac_dsp36_40nm_openfpga.xml | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_frac_mem32K_frac_dsp36_40nm_openfpga.xml b/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_frac_mem32K_frac_dsp36_40nm_openfpga.xml index d47e396ee..328ff7b57 100644 --- a/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_frac_mem32K_frac_dsp36_40nm_openfpga.xml +++ b/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_frac_mem32K_frac_dsp36_40nm_openfpga.xml @@ -315,7 +315,7 @@ - + @@ -323,7 +323,7 @@ - + @@ -331,7 +331,7 @@ - + @@ -339,7 +339,7 @@ - + @@ -347,7 +347,7 @@ - + @@ -355,7 +355,7 @@ - + @@ -363,18 +363,6 @@ - - - - - - - - - - - - @@ -386,8 +374,20 @@ + + + + + + + + + + + + - + @@ -399,7 +399,7 @@ - + @@ -411,7 +411,7 @@ - + @@ -423,7 +423,7 @@ - + @@ -435,7 +435,7 @@ - + From 3ee4e10aa8b475aa9bb0831f8ec9a30b092dd139 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 18 Aug 2020 17:25:45 -0600 Subject: [PATCH 08/31] bug fix in the frac mem & DSP vpr arch --- ...dder_chain_frac_mem32K_frac_dsp36_40nm.xml | 33 ++++++++++++++----- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_frac_mem32K_frac_dsp36_40nm.xml b/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_frac_mem32K_frac_dsp36_40nm.xml index 6acc37ba2..d34f3bba7 100644 --- a/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_frac_mem32K_frac_dsp36_40nm.xml +++ b/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_frac_mem32K_frac_dsp36_40nm.xml @@ -939,15 +939,30 @@ - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + From 42b5ea2cb10795c3771c53cf476996a088227bbd Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 18 Aug 2020 20:42:36 -0600 Subject: [PATCH 09/31] bug fix in openfpga arch for frac mem and dsp --- ...n_frac_mem32K_frac_dsp36_40nm_openfpga.xml | 22 +++++-------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_frac_mem32K_frac_dsp36_40nm_openfpga.xml b/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_frac_mem32K_frac_dsp36_40nm_openfpga.xml index 328ff7b57..228271ce7 100644 --- a/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_frac_mem32K_frac_dsp36_40nm_openfpga.xml +++ b/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_frac_mem32K_frac_dsp36_40nm_openfpga.xml @@ -374,20 +374,8 @@ - - - - - - - - - - - - - + @@ -399,7 +387,7 @@ - + @@ -411,7 +399,7 @@ - + @@ -423,7 +411,7 @@ - + @@ -435,7 +423,7 @@ - + From 743167521a200c11e2ab32c711062c696a047f90 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 18 Aug 2020 21:13:46 -0600 Subject: [PATCH 10/31] add Verilog design for fracturable 32k memory --- openfpga_flow/VerilogNetlists/frac_mem_32k.v | 371 +++++++++++++++++++ 1 file changed, 371 insertions(+) create mode 100644 openfpga_flow/VerilogNetlists/frac_mem_32k.v diff --git a/openfpga_flow/VerilogNetlists/frac_mem_32k.v b/openfpga_flow/VerilogNetlists/frac_mem_32k.v new file mode 100644 index 000000000..2d0b8fd26 --- /dev/null +++ b/openfpga_flow/VerilogNetlists/frac_mem_32k.v @@ -0,0 +1,371 @@ +//----------------------------------------------------- +// Design Name : frac_mem_32k +// File Name : frac_mem_32k.v +// Function : A fracturable BRAM which can operate in 13 modes +// - Single port RAM 512x64 bit +// - Single port RAM 1024x32 bit +// - Single port RAM 2048x16 bit +// - Single port RAM 4096x8 bit +// - Single port RAM 8192x4 bit +// - Single port RAM 16384x2 bit +// - Single port RAM 32768x1 bit +// - Dual port RAM 1024x32 +// - Dual port RAM 2048x16 bit +// - Dual port RAM 4096x8 bit +// - Dual port RAM 8192x4 bit +// - Dual port RAM 16384x2 bit +// - Dual port RAM 32768x1 bit +// Inspired by the dual port ram Verilog from +// https://www.intel.com/content/www/us/en/programmable/support/support-resources/design-examples/design-software/vhdl/vhd-true-dual-port-ram-sclk.html +// Coder : Xifan Tang +//----------------------------------------------------- + +module frac_mem_32k ( + input [0:14] addr_a, + input [0:14] addr_b, + input [0:31] data_a, + input [0:31] data_b, + input we_a, + input we_b, + output reg [0:31] q_a, + output reg [0:31] q_b, + input clk, + input [0:3] mode); + + reg [0:9] ram_a [0:31]; + reg [0:9] ram_b [0:31]; + + always @(posedge clk) begin + // Operating mode: single port RAM 512 x 64 + if (4'b0000 == mode) begin + if (we_a) begin + ram_a[addr_a[0:8]] <= data_a; + ram_b[addr_a[0:8]] <= data_b; + q_a <= data_a; + q_b <= data_b; + end else begin + q_a <= ram_a[addr_a[0:8]]; + q_b <= ram_b[addr_a[0:8]]; + end + // Operating mode: single port RAM 1024 x 32 + end else if (4'b0001 == mode) begin + if (we_a) begin + ram_a[addr_a[0:9]] <= data_a; + end else begin + q_a <= ram_a[addr_a[0:9]]; + end + // Operating mode: single port RAM 2048 x 16 + end else if (4'b0010 == mode) begin + if (we_a) begin + case (addr_a[10:10]) + 1'b0 : ram_a[addr_a[0:9]][0:15] <= data_a[0:15]; + 1'b1 : ram_a[addr_a[0:9]][16:31] <= data_a[0:15]; + endcase + end else begin + case (addr_a[10:10]) + 1'b0 : q_a <= ram_a[addr_a[0:9]][0:15]; + 1'b1 : q_a <= ram_a[addr_a[0:9]][16:31]; + endcase + end + // Operating mode: single port RAM 4096 x 8 + end else if (4'b0011 == mode) begin + if (we_a) begin + case (addr_a[10:11]) + 2'b00 : ram_a[addr_a[0:9]][0:7] <= data_a[0:7]; + 2'b01 : ram_a[addr_a[0:9]][8:15] <= data_a[0:7]; + 2'b10 : ram_a[addr_a[0:9]][16:23] <= data_a[0:7]; + 2'b11 : ram_a[addr_a[0:9]][24:31] <= data_a[0:7]; + endcase + end else begin + case (addr_a[10:11]) + 2'b00 : q_a <= ram_a[addr_a[0:9]][0:7]; + 2'b01 : q_a <= ram_a[addr_a[0:9]][8:15]; + 2'b10 : q_a <= ram_a[addr_a[0:9]][16:23]; + 2'b11 : q_a <= ram_a[addr_a[0:9]][24:31]; + endcase + end + // Operating mode: single port RAM 8192 x 4 + end else if (4'b0100 == mode) begin + if (we_a) begin + case (addr_a[10:12]) + 3'b000 : ram_a[addr_a[0:9]][0:3] <= data_a[0:3]; + 3'b001 : ram_a[addr_a[0:9]][4:7] <= data_a[0:3]; + 3'b010 : ram_a[addr_a[0:9]][8:11] <= data_a[0:3]; + 3'b011 : ram_a[addr_a[0:9]][12:15] <= data_a[0:3]; + 3'b100 : ram_a[addr_a[0:9]][16:19] <= data_a[0:3]; + 3'b101 : ram_a[addr_a[0:9]][20:23] <= data_a[0:3]; + 3'b110 : ram_a[addr_a[0:9]][24:27] <= data_a[0:3]; + 3'b111 : ram_a[addr_a[0:9]][28:31] <= data_a[0:3]; + endcase + end else begin + case (addr_a[10:12]) + 3'b000 : q_a <= ram_a[addr_a[0:9]][0:3]; + 3'b001 : q_a <= ram_a[addr_a[0:9]][4:7]; + 3'b010 : q_a <= ram_a[addr_a[0:9]][8:11]; + 3'b011 : q_a <= ram_a[addr_a[0:9]][12:15]; + 3'b100 : q_a <= ram_a[addr_a[0:9]][16:19]; + 3'b101 : q_a <= ram_a[addr_a[0:9]][20:23]; + 3'b110 : q_a <= ram_a[addr_a[0:9]][24:27]; + 3'b111 : q_a <= ram_a[addr_a[0:9]][28:31]; + endcase + end + // Operating mode: single port RAM 16384 x 2 + end else if (4'b0101 == mode) begin + if (we_a) begin + case (addr_a[10:13]) + 4'b0000 : ram_a[addr_a[0:9]][0:1] <= data_a[0:1]; + 4'b0001 : ram_a[addr_a[0:9]][2:3] <= data_a[0:1]; + 4'b0010 : ram_a[addr_a[0:9]][4:5] <= data_a[0:1]; + 4'b0011 : ram_a[addr_a[0:9]][6:7] <= data_a[0:1]; + 4'b0100 : ram_a[addr_a[0:9]][8:9] <= data_a[0:1]; + 4'b0101 : ram_a[addr_a[0:9]][10:11] <= data_a[0:1]; + 4'b0110 : ram_a[addr_a[0:9]][12:13] <= data_a[0:1]; + 4'b0111 : ram_a[addr_a[0:9]][14:15] <= data_a[0:1]; + 4'b1000 : ram_a[addr_a[0:9]][16:17] <= data_a[0:1]; + 4'b1001 : ram_a[addr_a[0:9]][18:19] <= data_a[0:1]; + 4'b1010 : ram_a[addr_a[0:9]][20:21] <= data_a[0:1]; + 4'b1011 : ram_a[addr_a[0:9]][22:23] <= data_a[0:1]; + 4'b1100 : ram_a[addr_a[0:9]][24:25] <= data_a[0:1]; + 4'b1101 : ram_a[addr_a[0:9]][26:27] <= data_a[0:1]; + 4'b1110 : ram_a[addr_a[0:9]][28:29] <= data_a[0:1]; + 4'b1111 : ram_a[addr_a[0:9]][30:31] <= data_a[0:1]; + endcase + end else begin + case (addr_a[10:13]) + 4'b0000 : q_a <= ram_a[addr_a[0:9]][0:1]; + 4'b0001 : q_a <= ram_a[addr_a[0:9]][2:3]; + 4'b0010 : q_a <= ram_a[addr_a[0:9]][4:5]; + 4'b0011 : q_a <= ram_a[addr_a[0:9]][6:7]; + 4'b0100 : q_a <= ram_a[addr_a[0:9]][8:9]; + 4'b0101 : q_a <= ram_a[addr_a[0:9]][10:11]; + 4'b0110 : q_a <= ram_a[addr_a[0:9]][12:13]; + 4'b0111 : q_a <= ram_a[addr_a[0:9]][14:15]; + 4'b1000 : q_a <= ram_a[addr_a[0:9]][16:17]; + 4'b1001 : q_a <= ram_a[addr_a[0:9]][18:19]; + 4'b1010 : q_a <= ram_a[addr_a[0:9]][20:21]; + 4'b1011 : q_a <= ram_a[addr_a[0:9]][22:23]; + 4'b1100 : q_a <= ram_a[addr_a[0:9]][24:25]; + 4'b1101 : q_a <= ram_a[addr_a[0:9]][26:27]; + 4'b1110 : q_a <= ram_a[addr_a[0:9]][28:29]; + 4'b1111 : q_a <= ram_a[addr_a[0:9]][30:31]; + endcase + end + // Operating mode: single port RAM 32768 x 1 + end else if (4'b0110 == mode) begin + if (we_a) begin + ram_a[addr_a[0:9]][addr_a[10:14]] = data_a[0:0]; + end else begin + q_a <= ram_a[addr_a[0:9]][addr_a[10:14]]; + end + // Operating mode: dual port RAM 1024 x 32 + end else if (4'b0111 == mode) begin + if (we_a) begin + ram_a[addr_a[0:9]] <= data_a; + ram_b[addr_b[0:9]] <= data_b; + q_a <= data_a; + q_b <= data_b; + end else begin + q_a <= ram_a[addr_a[0:9]]; + q_b <= ram_b[addr_b[0:9]]; + end + // Operating mode: dual port RAM 2048 x 16 + end else if (4'b1000 == mode) begin + if (we_a) begin + case (addr_a[10:10]) + 1'b0 : ram_a[addr_a[0:9]][0:15] <= data_a; + 1'b1 : ram_a[addr_a[0:9]][16:31] <= data_a; + endcase + end else begin + case (addr_a[10:10]) + 1'b0 : q_a <= ram_a[addr_a[0:9]][0:15]; + 1'b1 : q_a <= ram_a[addr_a[0:9]][16:31]; + endcase + end + + if (we_b) begin + case (addr_b[10:10]) + 1'b0 : ram_b[addr_b[0:9]][0:15] <= data_b; + 1'b1 : ram_b[addr_b[0:9]][16:31] <= data_b; + endcase + end else begin + case (addr_b[10:10]) + 1'b0 : q_b <= ram_b[addr_b[0:9]][0:15]; + 1'b1 : q_b <= ram_b[addr_b[0:9]][16:31]; + endcase + end + // Operating mode: dual port RAM 4096 x 8 + end else if (4'b1001 == mode) begin + if (we_a) begin + case (addr_a[10:11]) + 2'b00 : ram_a[addr_a[0:9]][0:7] <= data_a[0:7]; + 2'b01 : ram_a[addr_a[0:9]][8:15] <= data_a[0:7]; + 2'b10 : ram_a[addr_a[0:9]][16:23] <= data_a[0:7]; + 2'b11 : ram_a[addr_a[0:9]][24:31] <= data_a[0:7]; + endcase + end else begin + case (addr_a[10:11]) + 2'b00 : q_a <= ram_a[addr_a[0:9]][0:7]; + 2'b01 : q_a <= ram_a[addr_a[0:9]][8:15]; + 2'b10 : q_a <= ram_a[addr_a[0:9]][16:23]; + 2'b11 : q_a <= ram_a[addr_a[0:9]][24:31]; + endcase + end + + if (we_b) begin + case (addr_b[10:11]) + 2'b00 : ram_b[addr_b[0:9]][0:7] <= data_b[0:7]; + 2'b01 : ram_b[addr_b[0:9]][8:15] <= data_b[0:7]; + 2'b10 : ram_b[addr_b[0:9]][16:23] <= data_b[0:7]; + 2'b11 : ram_b[addr_b[0:9]][24:31] <= data_b[0:7]; + endcase + end else begin + case (addr_b[10:11]) + 2'b00 : q_b <= ram_b[addr_b[0:9]][0:7]; + 2'b01 : q_b <= ram_b[addr_b[0:9]][8:15]; + 2'b10 : q_b <= ram_b[addr_b[0:9]][16:23]; + 2'b11 : q_b <= ram_b[addr_b[0:9]][24:31]; + endcase + end + // Operating mode: dual port RAM 8192 x 4 + end else if (4'b1011 == mode) begin + if (we_a) begin + case (addr_a[10:12]) + 3'b000 : ram_a[addr_a[0:9]][0:3] <= data_a[0:3]; + 3'b001 : ram_a[addr_a[0:9]][4:7] <= data_a[0:3]; + 3'b010 : ram_a[addr_a[0:9]][8:11] <= data_a[0:3]; + 3'b011 : ram_a[addr_a[0:9]][12:15] <= data_a[0:3]; + 3'b100 : ram_a[addr_a[0:9]][16:19] <= data_a[0:3]; + 3'b101 : ram_a[addr_a[0:9]][20:23] <= data_a[0:3]; + 3'b110 : ram_a[addr_a[0:9]][24:27] <= data_a[0:3]; + 3'b111 : ram_a[addr_a[0:9]][28:31] <= data_a[0:3]; + endcase + end else begin + case (addr_a[10:12]) + 3'b000 : q_a <= ram_a[addr_a[0:9]][0:3]; + 3'b001 : q_a <= ram_a[addr_a[0:9]][4:7]; + 3'b010 : q_a <= ram_a[addr_a[0:9]][8:11]; + 3'b011 : q_a <= ram_a[addr_a[0:9]][12:15]; + 3'b100 : q_a <= ram_a[addr_a[0:9]][16:19]; + 3'b101 : q_a <= ram_a[addr_a[0:9]][20:23]; + 3'b110 : q_a <= ram_a[addr_a[0:9]][24:27]; + 3'b111 : q_a <= ram_a[addr_a[0:9]][28:31]; + endcase + end + if (we_b) begin + case (addr_b[10:12]) + 3'b000 : ram_b[addr_b[0:9]][0:3] <= data_b[0:3]; + 3'b001 : ram_b[addr_b[0:9]][4:7] <= data_b[0:3]; + 3'b010 : ram_b[addr_b[0:9]][8:11] <= data_b[0:3]; + 3'b011 : ram_b[addr_b[0:9]][12:15] <= data_b[0:3]; + 3'b100 : ram_b[addr_b[0:9]][16:19] <= data_b[0:3]; + 3'b101 : ram_b[addr_b[0:9]][20:23] <= data_b[0:3]; + 3'b110 : ram_b[addr_b[0:9]][24:27] <= data_b[0:3]; + 3'b111 : ram_b[addr_b[0:9]][28:31] <= data_b[0:3]; + endcase + end else begin + case (addr_b[10:12]) + 3'b000 : q_b <= ram_b[addr_b[0:9]][0:3]; + 3'b001 : q_b <= ram_b[addr_b[0:9]][4:7]; + 3'b010 : q_b <= ram_b[addr_b[0:9]][8:11]; + 3'b011 : q_b <= ram_b[addr_b[0:9]][12:15]; + 3'b100 : q_b <= ram_b[addr_b[0:9]][16:19]; + 3'b101 : q_b <= ram_b[addr_b[0:9]][20:23]; + 3'b110 : q_b <= ram_b[addr_b[0:9]][24:27]; + 3'b111 : q_b <= ram_b[addr_b[0:9]][28:31]; + endcase + end + // Operating mode: dual port RAM 16384 x 2 + end else if (4'b1100 == mode) begin + if (we_a) begin + case (addr_a[10:13]) + 4'b0000 : ram_a[addr_a[0:9]][0:1] <= data_a[0:1]; + 4'b0001 : ram_a[addr_a[0:9]][2:3] <= data_a[0:1]; + 4'b0010 : ram_a[addr_a[0:9]][4:5] <= data_a[0:1]; + 4'b0011 : ram_a[addr_a[0:9]][6:7] <= data_a[0:1]; + 4'b0100 : ram_a[addr_a[0:9]][8:9] <= data_a[0:1]; + 4'b0101 : ram_a[addr_a[0:9]][10:11] <= data_a[0:1]; + 4'b0110 : ram_a[addr_a[0:9]][12:13] <= data_a[0:1]; + 4'b0111 : ram_a[addr_a[0:9]][14:15] <= data_a[0:1]; + 4'b1000 : ram_a[addr_a[0:9]][16:17] <= data_a[0:1]; + 4'b1001 : ram_a[addr_a[0:9]][18:19] <= data_a[0:1]; + 4'b1010 : ram_a[addr_a[0:9]][20:21] <= data_a[0:1]; + 4'b1011 : ram_a[addr_a[0:9]][22:23] <= data_a[0:1]; + 4'b1100 : ram_a[addr_a[0:9]][24:25] <= data_a[0:1]; + 4'b1101 : ram_a[addr_a[0:9]][26:27] <= data_a[0:1]; + 4'b1110 : ram_a[addr_a[0:9]][28:29] <= data_a[0:1]; + 4'b1111 : ram_a[addr_a[0:9]][30:31] <= data_a[0:1]; + endcase + end else begin + case (addr_a[10:13]) + 4'b0000 : q_a <= ram_a[addr_a[0:9]][0:1]; + 4'b0001 : q_a <= ram_a[addr_a[0:9]][2:3]; + 4'b0010 : q_a <= ram_a[addr_a[0:9]][4:5]; + 4'b0011 : q_a <= ram_a[addr_a[0:9]][6:7]; + 4'b0100 : q_a <= ram_a[addr_a[0:9]][8:9]; + 4'b0101 : q_a <= ram_a[addr_a[0:9]][10:11]; + 4'b0110 : q_a <= ram_a[addr_a[0:9]][12:13]; + 4'b0111 : q_a <= ram_a[addr_a[0:9]][14:15]; + 4'b1000 : q_a <= ram_a[addr_a[0:9]][16:17]; + 4'b1001 : q_a <= ram_a[addr_a[0:9]][18:19]; + 4'b1010 : q_a <= ram_a[addr_a[0:9]][20:21]; + 4'b1011 : q_a <= ram_a[addr_a[0:9]][22:23]; + 4'b1100 : q_a <= ram_a[addr_a[0:9]][24:25]; + 4'b1101 : q_a <= ram_a[addr_a[0:9]][26:27]; + 4'b1110 : q_a <= ram_a[addr_a[0:9]][28:29]; + 4'b1111 : q_a <= ram_a[addr_a[0:9]][30:31]; + endcase + end + if (we_b) begin + case (addr_b[10:13]) + 4'b0000 : ram_b[addr_b[0:9]][0:1] <= data_b[0:1]; + 4'b0001 : ram_b[addr_b[0:9]][2:3] <= data_b[0:1]; + 4'b0010 : ram_b[addr_b[0:9]][4:5] <= data_b[0:1]; + 4'b0011 : ram_b[addr_b[0:9]][6:7] <= data_b[0:1]; + 4'b0100 : ram_b[addr_b[0:9]][8:9] <= data_b[0:1]; + 4'b0101 : ram_b[addr_b[0:9]][10:11] <= data_b[0:1]; + 4'b0110 : ram_b[addr_b[0:9]][12:13] <= data_b[0:1]; + 4'b0111 : ram_b[addr_b[0:9]][14:15] <= data_b[0:1]; + 4'b1000 : ram_b[addr_b[0:9]][16:17] <= data_b[0:1]; + 4'b1001 : ram_b[addr_b[0:9]][18:19] <= data_b[0:1]; + 4'b1010 : ram_b[addr_b[0:9]][20:21] <= data_b[0:1]; + 4'b1011 : ram_b[addr_b[0:9]][22:23] <= data_b[0:1]; + 4'b1100 : ram_b[addr_b[0:9]][24:25] <= data_b[0:1]; + 4'b1101 : ram_b[addr_b[0:9]][26:27] <= data_b[0:1]; + 4'b1110 : ram_b[addr_b[0:9]][28:29] <= data_b[0:1]; + 4'b1111 : ram_b[addr_b[0:9]][30:31] <= data_b[0:1]; + endcase + end else begin + case (addr_b[10:13]) + 4'b0000 : q_b <= ram_b[addr_b[0:9]][0:1]; + 4'b0001 : q_b <= ram_b[addr_b[0:9]][2:3]; + 4'b0010 : q_b <= ram_b[addr_b[0:9]][4:5]; + 4'b0011 : q_b <= ram_b[addr_b[0:9]][6:7]; + 4'b0100 : q_b <= ram_b[addr_b[0:9]][8:9]; + 4'b0101 : q_b <= ram_b[addr_b[0:9]][10:11]; + 4'b0110 : q_b <= ram_b[addr_b[0:9]][12:13]; + 4'b0111 : q_b <= ram_b[addr_b[0:9]][14:15]; + 4'b1000 : q_b <= ram_b[addr_b[0:9]][16:17]; + 4'b1001 : q_b <= ram_b[addr_b[0:9]][18:19]; + 4'b1010 : q_b <= ram_b[addr_b[0:9]][20:21]; + 4'b1011 : q_b <= ram_b[addr_b[0:9]][22:23]; + 4'b1100 : q_b <= ram_b[addr_b[0:9]][24:25]; + 4'b1101 : q_b <= ram_b[addr_b[0:9]][26:27]; + 4'b1110 : q_b <= ram_b[addr_b[0:9]][28:29]; + 4'b1111 : q_b <= ram_b[addr_b[0:9]][30:31]; + endcase + end + // Operating mode: dual port RAM 32768 x 1 + end else if (4'b1101 == mode) begin + if (we_a) begin + ram_a[addr_a[0:9]][addr_a[10:14]] = data_a[0:0]; + end else begin + q_a <= ram_a[addr_a[0:9]][addr_a[10:14]]; + end + if (we_b) begin + ram_b[addr_b[0:9]][addr_b[10:14]] = data_b[0:0]; + end else begin + q_b <= ram_b[addr_b[0:9]][addr_b[10:14]]; + end + end + end +endmodule From dbd93e429d699d6509687669a425d7bf9a02c230 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 19 Aug 2020 09:43:44 -0600 Subject: [PATCH 11/31] now pro_blif.pl can accept customized clock name --- openfpga_flow/scripts/pro_blif.pl | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/openfpga_flow/scripts/pro_blif.pl b/openfpga_flow/scripts/pro_blif.pl index 40203e136..f3cb0e99b 100755 --- a/openfpga_flow/scripts/pro_blif.pl +++ b/openfpga_flow/scripts/pro_blif.pl @@ -25,8 +25,9 @@ sub print_usage() print " -i \n"; print " -o \n"; print " Options: (Optional)\n"; - print " -remove_buffers\n"; - print " -add_default_clk\n"; + print " -remove_buffers: remove buffers in the blif\n"; + print " -add_default_clk: add a default clock using the default clock name 'clk', or set by users through the option '-default clk'\n"; + print " -default_clk : set the default clk name to be used by .latch\n"; print " -initial_blif \n"; print "\n"; return 0; @@ -46,6 +47,8 @@ sub opts_read() $frpt = $ARGV[$iargv+1]; } elsif ("-add_default_clk" eq $ARGV[$iargv]) { $add_default_clk = "on"; + } elsif ("-default_clk" eq $ARGV[$iargv]) { + $default_clk_name = $ARGV[$iargv+1]; } elsif ("-initial_blif" eq $ARGV[$iargv]) { $finitial = $ARGV[$iargv+1]; } elsif ("-remove_buffers" eq $ARGV[$iargv]) { @@ -219,7 +222,7 @@ sub scan_blif() my ($line_no) = (0); if (!defined($finitial)) { - $latch_token = "re clk"; + $latch_token = "re $default_clk_name"; } else { my $latch_token_found = 0; my $count = 0; From d7efdf35b62b77a784c68935fdb69e4305222dca Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 19 Aug 2020 11:15:25 -0600 Subject: [PATCH 12/31] add custom pin location to the flagship vpr arch with frac mem and dsp --- ...adder_chain_frac_mem32K_frac_dsp36_40nm.xml | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_frac_mem32K_frac_dsp36_40nm.xml b/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_frac_mem32K_frac_dsp36_40nm.xml index d34f3bba7..c56ce6041 100644 --- a/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_frac_mem32K_frac_dsp36_40nm.xml +++ b/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_frac_mem32K_frac_dsp36_40nm.xml @@ -223,7 +223,14 @@ - + + + + + + mult_36.a[0:17] mult_36.b[0:17] mult_36.out[0:35] + mult_36.a[18:35] mult_36.b[18:35] mult_36.out[36:71] + @@ -237,7 +244,14 @@ - + + + + + memory.clk + memory.addr1[0:14] memory.data[0:31] memory.we1 memory.out[0:31] + memory.addr2[0:14] memory.data[32:63] memory.we2 memory.out[32:63] + From af1c7c6f29900f2d02aee74d5ff6815808933e7b Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 19 Aug 2020 12:18:35 -0600 Subject: [PATCH 13/31] start fixing the bug in thru channels --- .../rr_graph_builder_utils.cpp | 35 +++++++++++++++++-- .../rr_graph_builder_utils.h | 6 ++-- .../tileable_rr_graph_node_builder.cpp | 13 ++++--- 3 files changed, 46 insertions(+), 8 deletions(-) diff --git a/vpr/src/tileable_rr_graph/rr_graph_builder_utils.cpp b/vpr/src/tileable_rr_graph/rr_graph_builder_utils.cpp index a599c8194..3bf54a6d5 100644 --- a/vpr/src/tileable_rr_graph/rr_graph_builder_utils.cpp +++ b/vpr/src/tileable_rr_graph/rr_graph_builder_utils.cpp @@ -172,7 +172,21 @@ size_t get_grid_num_classes(const t_grid_tile& cur_grid, * When height_offset == height - 1, it means that the grid is at the top side of this multi-width and multi-height block ***********************************************************************/ bool is_chanx_exist(const DeviceGrid& grids, - const vtr::Point& chanx_coord) { + const vtr::Point& chanx_coord, + const bool& through_channel) { + + if ((1 > chanx_coord.x()) || (chanx_coord.x() > grids.width() - 2)) { + return false; + } + + if (chanx_coord.y() > grids.height() - 2) { + return false; + } + + if (true == through_channel) { + return true; + } + return (grids[chanx_coord.x()][chanx_coord.y()].height_offset == grids[chanx_coord.x()][chanx_coord.y()].type->height - 1); } @@ -192,9 +206,26 @@ bool is_chanx_exist(const DeviceGrid& grids, * If the CHANY is in the middle of a multi-width and multi-height grid * it should locate at a grid whose width_offset is lower than the its width defined in physical_tile * When height_offset == height - 1, it means that the grid is at the top side of this multi-width and multi-height block + * + * If through channel is allowed, the chany will always exists + * unless it falls out of the grid array ***********************************************************************/ bool is_chany_exist(const DeviceGrid& grids, - const vtr::Point& chany_coord) { + const vtr::Point& chany_coord, + const bool& through_channel) { + + if (chany_coord.x() > grids.width() - 2) { + return false; + } + + if ((1 > chany_coord.y()) || (chany_coord.y() > grids.height() - 2)) { + return false; + } + + if (true == through_channel) { + return true; + } + return (grids[chany_coord.x()][chany_coord.y()].width_offset == grids[chany_coord.x()][chany_coord.y()].type->width - 1); } diff --git a/vpr/src/tileable_rr_graph/rr_graph_builder_utils.h b/vpr/src/tileable_rr_graph/rr_graph_builder_utils.h index 23e030d9b..6ff78412f 100644 --- a/vpr/src/tileable_rr_graph/rr_graph_builder_utils.h +++ b/vpr/src/tileable_rr_graph/rr_graph_builder_utils.h @@ -40,10 +40,12 @@ size_t get_grid_num_classes(const t_grid_tile& cur_grid, const e_pin_type& pin_type); bool is_chanx_exist(const DeviceGrid& grids, - const vtr::Point& chanx_coord); + const vtr::Point& chanx_coord, + const bool& through_channel=false); bool is_chany_exist(const DeviceGrid& grids, - const vtr::Point& chany_coord); + const vtr::Point& chany_coord, + const bool& through_channel=false); bool is_chanx_right_to_multi_height_grid(const DeviceGrid& grids, const vtr::Point& chanx_coord, diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp index 753c455ff..4107d4538 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp @@ -186,7 +186,8 @@ size_t estimate_num_chanx_rr_nodes(const DeviceGrid& grids, vtr::Point chanx_coord(ix, iy); /* Bypass if the routing channel does not exist when through channels are not allowed */ - if (false == is_chanx_exist(grids, chanx_coord)) { + if ( (false == through_channel) + && (false == is_chanx_exist(grids, chanx_coord))) { continue; } @@ -237,11 +238,13 @@ size_t estimate_num_chany_rr_nodes(const DeviceGrid& grids, for (size_t iy = 1; iy < grids.height() - 1; ++iy) { vtr::Point chany_coord(ix, iy); - /* Bypass if the routing channel does not exist when through channels are not allowed */ - if (false == is_chany_exist(grids, chany_coord)) { + /* Bypass if the routing channel does not exist when through channel are not allowed */ + if ( (false == through_channel) + && (false == is_chany_exist(grids, chany_coord))) { continue; } + bool force_start = false; bool force_end = false; @@ -922,7 +925,9 @@ void load_chany_rr_nodes_basic_info(RRGraph& rr_graph, ChanNodeDetails chany_details = build_unidir_chan_node_details(chan_width, grids.height() - 2, force_start, force_end, segment_infs); - /* Force node_ids from the previous chanx */ + /* Force node_ids from the previous chany + * This will not be applied when the routing channel is cut off (force to start) + */ if (0 < track_node_ids.size()) { /* Rotate should be done based on a typical case of routing tracks. * Tracks on the borders are not regularly started and ended, From f64079641d1ee4954a91572726af06434e795336 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 19 Aug 2020 12:43:58 -0600 Subject: [PATCH 14/31] bug fix in flagship vpr arch with frac mem and dsp --- ...c_N10_adder_chain_frac_mem32K_frac_dsp36_40nm_openfpga.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_frac_mem32K_frac_dsp36_40nm_openfpga.xml b/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_frac_mem32K_frac_dsp36_40nm_openfpga.xml index 228271ce7..b2fa706af 100644 --- a/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_frac_mem32K_frac_dsp36_40nm_openfpga.xml +++ b/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_frac_mem32K_frac_dsp36_40nm_openfpga.xml @@ -287,7 +287,7 @@ There are four 9x9 multipliers, each of which occupies part of the input/output of the 36x36 multiplier --> - + @@ -296,7 +296,7 @@ There are two 18x18 multipliers, each of which occupies part of the input/output of the 36x36 multiplier --> - + From 79b6ff3cb08b1c20612bf5c6d6755fb0966ad0b4 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 19 Aug 2020 12:44:51 -0600 Subject: [PATCH 15/31] relax checking for device annotation as we support multi-port during physical mode pin mapping --- openfpga/src/annotation/vpr_device_annotation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openfpga/src/annotation/vpr_device_annotation.cpp b/openfpga/src/annotation/vpr_device_annotation.cpp index 71b3baf63..f196f50da 100644 --- a/openfpga/src/annotation/vpr_device_annotation.cpp +++ b/openfpga/src/annotation/vpr_device_annotation.cpp @@ -298,7 +298,7 @@ void VprDeviceAnnotation::add_physical_pb_port_range(t_port* operating_pb_port, t_port* physical_pb_port, const BasicPort& port_range) { /* The port range must satify the port width*/ - VTR_ASSERT((size_t)operating_pb_port->num_pins == port_range.get_width()); + VTR_ASSERT((size_t)operating_pb_port->num_pins >= port_range.get_width()); /* Warn any override attempt */ std::map>::const_iterator it = physical_pb_port_ranges_.find(operating_pb_port); From f631245b2b85f79376a475b668ee767ca82057fe Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 19 Aug 2020 13:41:04 -0600 Subject: [PATCH 16/31] bug fix and enriched debugging info print out --- openfpga/src/annotation/annotate_pb_graph.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/openfpga/src/annotation/annotate_pb_graph.cpp b/openfpga/src/annotation/annotate_pb_graph.cpp index 93a154222..249cb5632 100644 --- a/openfpga/src/annotation/annotate_pb_graph.cpp +++ b/openfpga/src/annotation/annotate_pb_graph.cpp @@ -337,6 +337,9 @@ bool try_match_pb_graph_pin(t_pb_graph_pin* operating_pb_graph_pin, /* Reach here, it means all the requirements have been met */ return true; } + + /* If we reach here, we failed */ + return false; } /******************************************************************** @@ -426,7 +429,7 @@ void annotate_physical_pb_graph_pin(t_pb_graph_pin* operating_pb_graph_pin, /* If we reach here, it means that pin pairing fails, error out! */ VTR_LOG_ERROR("Fail to match a physical pin for '%s' from pb_graph_node '%s'!\n", - operating_pb_graph_pin->port->name, + operating_pb_graph_pin->to_string().c_str(), physical_pb_graph_node->hierarchical_type_name().c_str()); } From 3eea12ceaed12df0e6693310058d97dd3cce00d1 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 19 Aug 2020 14:43:44 -0600 Subject: [PATCH 17/31] added a new XML syntax: initial offset for physical mode pin mapping --- .../src/pb_type_annotation.cpp | 45 ++++++++++++++----- .../libarchopenfpga/src/pb_type_annotation.h | 32 ++++++++++--- .../src/read_xml_pb_type_annotation.cpp | 25 +++++++++++ .../src/write_xml_pb_type_annotation.cpp | 10 ++++- openfpga/src/annotation/annotate_pb_graph.cpp | 28 ++++++++---- openfpga/src/annotation/annotate_pb_types.cpp | 7 +-- .../src/annotation/vpr_device_annotation.cpp | 30 ++++++++++++- .../src/annotation/vpr_device_annotation.h | 7 +++ 8 files changed, 152 insertions(+), 32 deletions(-) diff --git a/libopenfpga/libarchopenfpga/src/pb_type_annotation.cpp b/libopenfpga/libarchopenfpga/src/pb_type_annotation.cpp index 133ee000c..9a369e742 100644 --- a/libopenfpga/libarchopenfpga/src/pb_type_annotation.cpp +++ b/libopenfpga/libarchopenfpga/src/pb_type_annotation.cpp @@ -86,11 +86,11 @@ std::vector PbTypeAnnotation::port_names() const { return keys; } -std::map PbTypeAnnotation::physical_pb_type_port(const std::string& port_name) const { - std::map>::const_iterator it = operating_pb_type_ports_.find(port_name); +std::map> PbTypeAnnotation::physical_pb_type_port(const std::string& port_name) const { + std::map>>::const_iterator it = operating_pb_type_ports_.find(port_name); if (it == operating_pb_type_ports_.end()) { /* Return an empty port */ - return std::map(); + return std::map>(); } return operating_pb_type_ports_.at(port_name); } @@ -169,25 +169,25 @@ void PbTypeAnnotation::set_physical_pb_type_index_offset(const int& value) { void PbTypeAnnotation::add_pb_type_port_pair(const std::string& operating_pb_port_name, const BasicPort& physical_pb_port) { /* Give a warning if the operating_pb_port_name already exist */ - std::map>::const_iterator it = operating_pb_type_ports_.find(operating_pb_port_name); + std::map>>::const_iterator it = operating_pb_type_ports_.find(operating_pb_port_name); /* If not exist, initialize and set a default value */ if (it == operating_pb_type_ports_.end()) { - operating_pb_type_ports_[operating_pb_port_name][physical_pb_port] = 0; + operating_pb_type_ports_[operating_pb_port_name][physical_pb_port] = {0, 0}; /* We can return early */ return; } /* If the physical port is not in the list, we create one and set a default value */ if (0 == operating_pb_type_ports_[operating_pb_port_name].count(physical_pb_port)) { - operating_pb_type_ports_[operating_pb_port_name][physical_pb_port] = 0; + operating_pb_type_ports_[operating_pb_port_name][physical_pb_port] = {0, 0}; } } -void PbTypeAnnotation::set_physical_pin_rotate_offset(const std::string& operating_pb_port_name, - const BasicPort& physical_pb_port, - const int& physical_pin_rotate_offset) { - std::map>::const_iterator it = operating_pb_type_ports_.find(operating_pb_port_name); +void PbTypeAnnotation::set_physical_pin_initial_offset(const std::string& operating_pb_port_name, + const BasicPort& physical_pb_port, + const int& physical_pin_initial_offset) { + std::map>>::const_iterator it = operating_pb_type_ports_.find(operating_pb_port_name); if (it == operating_pb_type_ports_.end()) { VTR_LOG_ERROR("The operating pb_type port '%s' is not valid!\n", @@ -204,7 +204,30 @@ void PbTypeAnnotation::set_physical_pin_rotate_offset(const std::string& operati exit(1); } - operating_pb_type_ports_[operating_pb_port_name][physical_pb_port] = physical_pin_rotate_offset; + operating_pb_type_ports_[operating_pb_port_name][physical_pb_port][0] = physical_pin_initial_offset; +} + +void PbTypeAnnotation::set_physical_pin_rotate_offset(const std::string& operating_pb_port_name, + const BasicPort& physical_pb_port, + const int& physical_pin_rotate_offset) { + std::map>>::const_iterator it = operating_pb_type_ports_.find(operating_pb_port_name); + + if (it == operating_pb_type_ports_.end()) { + VTR_LOG_ERROR("The operating pb_type port '%s' is not valid!\n", + operating_pb_port_name.c_str()); + exit(1); + } + + if (operating_pb_type_ports_[operating_pb_port_name].end() == operating_pb_type_ports_[operating_pb_port_name].find(physical_pb_port)) { + VTR_LOG_ERROR("The physical pb_type port '%s[%lu:%lu]' definition for operating pb_type port '%s' is not valid!\n", + physical_pb_port.get_name().c_str(), + physical_pb_port.get_lsb(), + physical_pb_port.get_msb(), + operating_pb_port_name.c_str()); + exit(1); + } + + operating_pb_type_ports_[operating_pb_port_name][physical_pb_port][1] = physical_pin_rotate_offset; } void PbTypeAnnotation::add_interconnect_circuit_model_pair(const std::string& interc_name, diff --git a/libopenfpga/libarchopenfpga/src/pb_type_annotation.h b/libopenfpga/libarchopenfpga/src/pb_type_annotation.h index 4e1d4e8a2..33941bce3 100644 --- a/libopenfpga/libarchopenfpga/src/pb_type_annotation.h +++ b/libopenfpga/libarchopenfpga/src/pb_type_annotation.h @@ -6,6 +6,7 @@ *******************************************************************/ #include #include +#include #include "openfpga_port.h" @@ -48,7 +49,7 @@ class PbTypeAnnotation { float physical_pb_type_index_factor() const; int physical_pb_type_index_offset() const; std::vector port_names() const; - std::map physical_pb_type_port(const std::string& port_name) const; + std::map> physical_pb_type_port(const std::string& port_name) const; std::vector interconnect_names() const; std::string interconnect_circuit_model_name(const std::string& interc_name) const; public: /* Public mutators */ @@ -66,6 +67,9 @@ class PbTypeAnnotation { void set_physical_pb_type_index_offset(const int& value); void add_pb_type_port_pair(const std::string& operating_pb_port_name, const BasicPort& physical_pb_port); + void set_physical_pin_initial_offset(const std::string& operating_pb_port_name, + const BasicPort& physical_pb_port, + const int& physical_pin_initial_offset); void set_physical_pin_rotate_offset(const std::string& operating_pb_port_name, const BasicPort& physical_pb_port, const int& physical_pin_rotate_offset); @@ -134,8 +138,12 @@ class PbTypeAnnotation { int physical_pb_type_index_offset_; /* Link from the pins under an operating pb_type to pairs of - * its physical pb_type and its pin rotating offset - * The offset aims to align the pin indices for port of pb_type + * its physical pb_type and its pin initial & rotating offset + * + * Note that initial offset is the first element of the std::array + * Note that rotating offset is the second element of the std::array + * + * The offsets aim to align the pin indices for port of pb_type * between operating and physical modes, especially when an operating * mode contains multiple pb_type (num_pb>1) that are linked to * the same physical pb_type. @@ -143,11 +151,21 @@ class PbTypeAnnotation { * the pin index of pb_type (whose index is large than 1) * will be shifted by the given offset. * - * For example, an offset of 1 is used to map - * operating pb_type adder[0].pin[0] with a full path clb.fle[arith].adder[0] - * to physical pb_type adder[0].pin[1] with a full path clb.fle[physical].adder[0] + * For example, an initial offset of -32 is used to map + * operating pb_type bram[0].dout[32] with a full path memory[dual_port].bram[0] + * operating pb_type bram[0].dout[33] with a full path memory[dual_port].bram[0] + * to + * physical pb_type bram[0].dout_a[0] with a full path memory[physical].bram[0] + * physical pb_type bram[0].dout_a[1] with a full path memory[physical].bram[0] + * + * For example, a rotating offset of 1 is used to map + * operating pb_type mult_9x9[0].a[0:8] with a full path mult[frac].mult_9x9[0] + * operating pb_type mult_9x9[1].a[0:8] with a full path mult[frac].mult_9x9[1] + * to + * physical pb_type mult_36x36.a[0:8] with a full path mult[physical].mult_36x36[0] + * physical pb_type mult_36x36.a[9:17] with a full path mult[physical].mult_36x36[0] */ - std::map> operating_pb_type_ports_; + std::map>> operating_pb_type_ports_; /* Link between the interconnects under this pb_type and circuit model names */ std::map interconnect_circuit_model_names_; diff --git a/libopenfpga/libarchopenfpga/src/read_xml_pb_type_annotation.cpp b/libopenfpga/libarchopenfpga/src/read_xml_pb_type_annotation.cpp index a4d25e1cf..9831f6e23 100644 --- a/libopenfpga/libarchopenfpga/src/read_xml_pb_type_annotation.cpp +++ b/libopenfpga/libarchopenfpga/src/read_xml_pb_type_annotation.cpp @@ -65,6 +65,31 @@ void read_xml_pb_port_annotation(pugi::xml_node& xml_port, pb_type_annotation.add_pb_type_port_pair(name_attr, port_parser.port()); } + /* We have an optional attribute: physical_mode_pin_initial_offset + * Split based on the number of physical pb_type ports that have been defined + */ + const std::string& physical_pin_initial_offset_attr = get_attribute(xml_port, "physical_mode_pin_initial_offset", loc_data, pugiutil::ReqOpt::OPTIONAL).as_string(); + + if (false == physical_pin_initial_offset_attr.empty()) { + /* Split the physical mode port attributes with space */ + openfpga::StringToken offset_tokenizer(physical_pin_initial_offset_attr); + const std::vector initial_offsets = offset_tokenizer.split(); + + /* Error out if the offset does not match the port definition */ + if (physical_mode_ports.size() != initial_offsets.size()) { + archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_port), + "Defined %lu physical mode ports but only %lu physical pin initial offset are defined! Expect size matching.\n", + physical_mode_ports.size(), initial_offsets.size()); + } + + for (size_t iport = 0; iport < physical_mode_ports.size(); ++iport) { + openfpga::PortParser port_parser(physical_mode_ports[iport]); + pb_type_annotation.set_physical_pin_initial_offset(name_attr, + port_parser.port(), + std::stoi(initial_offsets[iport])); + } + } + /* We have an optional attribute: physical_mode_pin_rotate_offset * Split based on the number of physical pb_type ports that have been defined */ diff --git a/libopenfpga/libarchopenfpga/src/write_xml_pb_type_annotation.cpp b/libopenfpga/libarchopenfpga/src/write_xml_pb_type_annotation.cpp index b013e5801..2bc512d85 100644 --- a/libopenfpga/libarchopenfpga/src/write_xml_pb_type_annotation.cpp +++ b/libopenfpga/libarchopenfpga/src/write_xml_pb_type_annotation.cpp @@ -126,13 +126,21 @@ void write_xml_pb_port_annotation(std::fstream& fp, } write_xml_attribute(fp, "physical_mode_port", physical_mode_port_attr.c_str()); + std::string physical_mode_pin_initial_offset_attr; + for (const auto& physical_pb_port_pair : pb_type_annotation.physical_pb_type_port(port_name)) { + if (false == physical_mode_pin_initial_offset_attr.empty()) { + physical_mode_pin_initial_offset_attr += " "; + } + physical_mode_pin_initial_offset_attr += std::to_string(physical_pb_port_pair.second[0]); + } + write_xml_attribute(fp, "physical_mode_pin_initial_offset", physical_mode_pin_initial_offset_attr.c_str()); std::string physical_mode_pin_rotate_offset_attr; for (const auto& physical_pb_port_pair : pb_type_annotation.physical_pb_type_port(port_name)) { if (false == physical_mode_pin_rotate_offset_attr.empty()) { physical_mode_pin_rotate_offset_attr += " "; } - physical_mode_pin_rotate_offset_attr += std::to_string(physical_pb_port_pair.second); + physical_mode_pin_rotate_offset_attr += std::to_string(physical_pb_port_pair.second[1]); } write_xml_attribute(fp, "physical_mode_pin_rotate_offset", physical_mode_pin_rotate_offset_attr.c_str()); diff --git a/openfpga/src/annotation/annotate_pb_graph.cpp b/openfpga/src/annotation/annotate_pb_graph.cpp index 249cb5632..67a1baba8 100644 --- a/openfpga/src/annotation/annotate_pb_graph.cpp +++ b/openfpga/src/annotation/annotate_pb_graph.cpp @@ -308,16 +308,23 @@ bool try_match_pb_graph_pin(t_pb_graph_pin* operating_pb_graph_pin, /* If the parent ports of the two pins are not paired, fail */ for (t_port* candidate_port : vpr_device_annotation.physical_pb_port(operating_pb_graph_pin->port)) { if (physical_pb_graph_pin->port != candidate_port) { - return false; + /* Not the one we want, try the next candidate */ + continue; } /* Check the pin number of physical pb_graph_pin matches the pin number of - * operating pb_graph_pin plus a rotation offset - * operating port physical port - * LSB port_range.lsb() pin_number pin_number MSB - * | | | - * Operating port | | +------ | - * | |<----offset--->| - * Physical port | + + + + * operating pb_graph_pin plus a rotation offset with an initial offset, + * which is to align the lsb between operating and physical ports + * + * For example: + * We can align the operating_port[32] to physical_port[0] with an initial offset + * which is -32 + * + * operating port physical port + * LSB port_range.lsb() pin_number pin_number MSB + * | | init_offset | + * Operating port | | +------ + | + * | |<----acc_offset--->| + * Physical port | + + + * * Note: * - accumulated offset is NOT the pin rotate offset specified by users @@ -327,11 +334,14 @@ bool try_match_pb_graph_pin(t_pb_graph_pin* operating_pb_graph_pin, * The accumulated offset will be reset to 0 when it exceeds the msb() of the physical port */ int acc_offset = vpr_device_annotation.physical_pb_pin_offset(operating_pb_graph_pin->port, candidate_port); + int init_offset = vpr_device_annotation.physical_pb_pin_initial_offset(operating_pb_graph_pin->port, candidate_port); const BasicPort& physical_port_range = vpr_device_annotation.physical_pb_port_range(operating_pb_graph_pin->port, candidate_port); if (physical_pb_graph_pin->pin_number != operating_pb_graph_pin->pin_number + (int)physical_port_range.get_lsb() + + init_offset + acc_offset) { - return false; + /* Not the one we want, try the next candidate */ + continue; } /* Reach here, it means all the requirements have been met */ diff --git a/openfpga/src/annotation/annotate_pb_types.cpp b/openfpga/src/annotation/annotate_pb_types.cpp index cb6c9e9b3..92a6f6560 100644 --- a/openfpga/src/annotation/annotate_pb_types.cpp +++ b/openfpga/src/annotation/annotate_pb_types.cpp @@ -211,7 +211,7 @@ bool pair_operating_and_physical_pb_types(t_pb_type* operating_pb_type, * if not found, we assume that the physical port is the same as the operating pb_port */ for (t_port* operating_pb_port : pb_type_ports(operating_pb_type)) { - std::map expected_physical_pb_ports = pb_type_annotation.physical_pb_type_port(std::string(operating_pb_port->name)); + std::map> expected_physical_pb_ports = pb_type_annotation.physical_pb_type_port(std::string(operating_pb_port->name)); /* If not defined in the annotation, set the default pair: * rotate_offset is 0 by default! @@ -220,7 +220,7 @@ bool pair_operating_and_physical_pb_types(t_pb_type* operating_pb_type, BasicPort expected_physical_pb_port; expected_physical_pb_port.set_name(std::string(operating_pb_port->name)); expected_physical_pb_port.set_width(operating_pb_port->num_pins); - expected_physical_pb_ports[expected_physical_pb_port] = 0; + expected_physical_pb_ports[expected_physical_pb_port] = {0, 0}; } for (const auto& expected_physical_pb_port : expected_physical_pb_ports) { @@ -241,7 +241,8 @@ bool pair_operating_and_physical_pb_types(t_pb_type* operating_pb_type, */ vpr_device_annotation.add_physical_pb_port(operating_pb_port, physical_pb_port); vpr_device_annotation.add_physical_pb_port_range(operating_pb_port, physical_pb_port, expected_physical_pb_port.first); - vpr_device_annotation.add_physical_pb_pin_rotate_offset(operating_pb_port, physical_pb_port, expected_physical_pb_port.second); + vpr_device_annotation.add_physical_pb_pin_initial_offset(operating_pb_port, physical_pb_port, expected_physical_pb_port.second[0]); + vpr_device_annotation.add_physical_pb_pin_rotate_offset(operating_pb_port, physical_pb_port, expected_physical_pb_port.second[1]); } } diff --git a/openfpga/src/annotation/vpr_device_annotation.cpp b/openfpga/src/annotation/vpr_device_annotation.cpp index f196f50da..f07378634 100644 --- a/openfpga/src/annotation/vpr_device_annotation.cpp +++ b/openfpga/src/annotation/vpr_device_annotation.cpp @@ -190,6 +190,21 @@ int VprDeviceAnnotation::physical_pb_type_index_offset(t_pb_type* pb_type) const return physical_pb_type_index_offsets_.at(pb_type); } +int VprDeviceAnnotation::physical_pb_pin_initial_offset(t_port* operating_pb_port, + t_port* physical_pb_port) const { + /* Ensure that the pb_type is in the list */ + std::map>::const_iterator it = physical_pb_pin_initial_offsets_.find(operating_pb_port); + if (it == physical_pb_pin_initial_offsets_.end()) { + /* Default value is 0 */ + return 0; + } + if (0 == physical_pb_pin_initial_offsets_.at(operating_pb_port).count(physical_pb_port)) { + /* Default value is 0 */ + return 0; + } + return physical_pb_pin_initial_offsets_.at(operating_pb_port).at(physical_pb_port); +} + int VprDeviceAnnotation::physical_pb_pin_rotate_offset(t_port* operating_pb_port, t_port* physical_pb_port) const { /* Ensure that the pb_type is in the list */ @@ -220,7 +235,6 @@ int VprDeviceAnnotation::physical_pb_pin_offset(t_port* operating_pb_port, return physical_pb_pin_offsets_.at(operating_pb_port).at(physical_pb_port); } - t_pb_graph_pin* VprDeviceAnnotation::physical_pb_graph_pin(const t_pb_graph_pin* pb_graph_pin) const { /* Ensure that the pb_type is in the list */ std::map::const_iterator it = physical_pb_graph_pins_.find(pb_graph_pin); @@ -410,6 +424,20 @@ void VprDeviceAnnotation::add_physical_pb_type_index_offset(t_pb_type* pb_type, physical_pb_type_index_offsets_[pb_type] = offset; } +void VprDeviceAnnotation::add_physical_pb_pin_initial_offset(t_port* operating_pb_port, + t_port* physical_pb_port, + const int& offset) { + /* Warn any override attempt */ + std::map>::const_iterator it = physical_pb_pin_initial_offsets_.find(operating_pb_port); + if ( (it != physical_pb_pin_initial_offsets_.end()) + && (0 < physical_pb_pin_initial_offsets_[operating_pb_port].count(physical_pb_port)) ) { + VTR_LOG_WARN("Override the annotation between operating pb_port '%s' and it physical pb_port '%s' pin rotate offset '%d'!\n", + operating_pb_port->name, offset); + } + + physical_pb_pin_initial_offsets_[operating_pb_port][physical_pb_port] = offset; +} + void VprDeviceAnnotation::add_physical_pb_pin_rotate_offset(t_port* operating_pb_port, t_port* physical_pb_port, const int& offset) { diff --git a/openfpga/src/annotation/vpr_device_annotation.h b/openfpga/src/annotation/vpr_device_annotation.h index 6ac9ab4b5..0e290f18e 100644 --- a/openfpga/src/annotation/vpr_device_annotation.h +++ b/openfpga/src/annotation/vpr_device_annotation.h @@ -61,6 +61,9 @@ class VprDeviceAnnotation { float physical_pb_type_index_factor(t_pb_type* pb_type) const; int physical_pb_type_index_offset(t_pb_type* pb_type) const; + int physical_pb_pin_initial_offset(t_port* operating_pb_port, + t_port* physical_pb_port) const; + int physical_pb_pin_rotate_offset(t_port* operating_pb_port, t_port* physical_pb_port) const; @@ -96,6 +99,9 @@ class VprDeviceAnnotation { t_pb_graph_node* physical_pb_graph_node); void add_physical_pb_type_index_factor(t_pb_type* pb_type, const float& factor); void add_physical_pb_type_index_offset(t_pb_type* pb_type, const int& offset); + void add_physical_pb_pin_initial_offset(t_port* operating_pb_port, + t_port* physical_pb_port, + const int& offset); void add_physical_pb_pin_rotate_offset(t_port* operating_pb_port, t_port* physical_pb_port, const int& offset); @@ -148,6 +154,7 @@ class VprDeviceAnnotation { * - the parent of physical pb_port MUST be a physical pb_type */ std::map> physical_pb_ports_; + std::map> physical_pb_pin_initial_offsets_; std::map> physical_pb_pin_rotate_offsets_; /* Accumulated offsets for a physical pb_type port, just for internal usage */ From 161d66083719415b381f6bc25f6f8cd426090395 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 19 Aug 2020 15:00:46 -0600 Subject: [PATCH 18/31] update documentation for the initial offset when mapping physical pins --- .../manual/arch_lang/annotate_vpr_arch.rst | 39 ++++++++++++++++--- .../libarchopenfpga/src/pb_type_annotation.h | 2 +- 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/docs/source/manual/arch_lang/annotate_vpr_arch.rst b/docs/source/manual/arch_lang/annotate_vpr_arch.rst index 5a6d77b14..e2f22ae37 100644 --- a/docs/source/manual/arch_lang/annotate_vpr_arch.rst +++ b/docs/source/manual/arch_lang/annotate_vpr_arch.rst @@ -103,8 +103,9 @@ The ``circuit_model_name`` should match the given name of a ``circuit_model`` de .. note:: OpenFPGA will infer the physical mode for a single-mode ``pb_type`` defined in VPR architecture -.. option:: +.. option:: Specify the physical implementation for a primitive ``pb_type`` in VPR architecture @@ -128,7 +129,8 @@ The ``circuit_model_name`` should match the given name of a ``circuit_model`` de - ``circuit_model_name=""`` For the interconnection type direct, the type of the linked circuit model should be wire. For multiplexers, the type of linked circuit model should be ``mux``. For complete, the type of the linked circuit model can be either ``mux`` or ``wire``, depending on the case. -.. option:: +.. option:: Link a port of an operating ``pb_type`` to a port of a physical ``pb_type`` @@ -136,9 +138,36 @@ The ``circuit_model_name`` should match the given name of a ``circuit_model`` de - ``physical_mode_pin="" creates the link of ``port`` of ``pb_type`` between operating and physical modes. This syntax is mandatory for every primitive ``pb_type`` in an operating mode ``pb_type``. It should be a valid ``port`` name of leaf ``pb_type`` in physical mode and the port size should also match. - .. note:: Users can define multiple ports. For example: ``physical_mode_pin="a[0:1] b[2:2]"``. When multiple ports are used, the ``physical_mode_pin_rotate_offset`` should also be adapt. For example: ``physical_mode_pin_rotate_offset="1 0"``) + .. note:: Users can define multiple ports. For example: ``physical_mode_pin="a[0:1] b[2:2]"``. When multiple ports are used, the ``physical_mode_pin_initial_offset`` and ``physical_mode_pin_rotate_offset`` should also be adapt. For example: ``physical_mode_pin_rotate_offset="1 0"``) - - ``physical_mode_pin_rotate_offset=""`` aims to align the pin indices for ``port`` of ``pb_type`` between operating and physical modes, especially when an operating mode contains multiple ``pb_type`` (``num_pb``>1) that are linked to the same physical ``pb_type``. When ``physical_mode_pin_rotate_offset`` is larger than zero, the pin index of ``pb_type`` (whose index is large than 1) will be shifted by the given offset. + + - ``physical_mode_pin_initial_offset=""`` aims to align the pin indices for ``port`` of ``pb_type`` between operating and physical modes, especially when part of port of operating mode is mapped to a port in physical ``pb_type``. When ``physical_mode_pin_initial_offset`` is larger than zero, the pin index of ``pb_type`` (whose index is large than 1) will be shifted by the given offset. + + .. note:: A quick example to understand the initial offset + For example, an initial offset of -32 is used to map + + - operating pb_type ``bram[0].dout[32]`` with a full path ``memory[dual_port].bram[0]`` + - operating pb_type ``bram[0].dout[33]`` with a full path ``memory[dual_port].bram[0]`` + + to + + - physical pb_type ``bram[0].dout_a[0]`` with a full path ``memory[physical].bram[0]`` + - physical pb_type ``bram[0].dout_a[1]`` with a full path ``memory[physical].bram[0]`` + + .. note:: If not defined, the default value of ``physical_mode_pin_initial_offset`` is set to ``0``. + + - ``physical_mode_pin_rotate_offset=""`` aims to align the pin indices for ``port`` of ``pb_type`` between operating and physical modes, especially when an operating mode contains multiple ``pb_type`` (``num_pb``>1) that are linked to the same physical ``pb_type``. When ``physical_mode_pin_rotate_offset`` is larger than zero, the pin index of ``pb_type`` (whose index is large than 1) will be shifted by the given offset. + + .. note:: A quick example to understand the rotate offset + For example, a rotating offset of 9 is used to map + + - operating pb_type ``mult_9x9[0].a[0:8]`` with a full path ``mult[frac].mult_9x9[0]`` + - operating pb_type ``mult_9x9[1].a[0:8]`` with a full path ``mult[frac].mult_9x9[1]`` + + to + + - physical pb_type ``mult_36x36.a[0:8]`` with a full path ``mult[physical].mult_36x36[0]`` + - physical pb_type ``mult_36x36.a[9:17]`` with a full path ``mult[physical].mult_36x36[0]`` .. note:: If not defined, the default value of ``physical_mode_pin_rotate_offset`` is set to ``0``. diff --git a/libopenfpga/libarchopenfpga/src/pb_type_annotation.h b/libopenfpga/libarchopenfpga/src/pb_type_annotation.h index 33941bce3..96383679d 100644 --- a/libopenfpga/libarchopenfpga/src/pb_type_annotation.h +++ b/libopenfpga/libarchopenfpga/src/pb_type_annotation.h @@ -158,7 +158,7 @@ class PbTypeAnnotation { * physical pb_type bram[0].dout_a[0] with a full path memory[physical].bram[0] * physical pb_type bram[0].dout_a[1] with a full path memory[physical].bram[0] * - * For example, a rotating offset of 1 is used to map + * For example, a rotating offset of 9 is used to map * operating pb_type mult_9x9[0].a[0:8] with a full path mult[frac].mult_9x9[0] * operating pb_type mult_9x9[1].a[0:8] with a full path mult[frac].mult_9x9[1] * to From aa4a9b28cce77a3f4ec7825c9bcb831d0601ec9b Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 19 Aug 2020 15:03:46 -0600 Subject: [PATCH 19/31] start testing the initial offset in the flagship architecture --- ...c_N10_adder_chain_frac_mem32K_frac_dsp36_40nm_openfpga.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_frac_mem32K_frac_dsp36_40nm_openfpga.xml b/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_frac_mem32K_frac_dsp36_40nm_openfpga.xml index b2fa706af..1eddefe25 100644 --- a/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_frac_mem32K_frac_dsp36_40nm_openfpga.xml +++ b/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_frac_mem32K_frac_dsp36_40nm_openfpga.xml @@ -309,9 +309,9 @@ - + - + From 3273f441fe4bd36cf3e83c5f8a696ef3c6aebdfb Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 19 Aug 2020 15:23:20 -0600 Subject: [PATCH 20/31] bug fix in the flagship vpr arch --- ...rac_N10_tileable_adder_chain_frac_mem32K_frac_dsp36_40nm.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_frac_mem32K_frac_dsp36_40nm.xml b/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_frac_mem32K_frac_dsp36_40nm.xml index c56ce6041..2f14a7c2f 100644 --- a/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_frac_mem32K_frac_dsp36_40nm.xml +++ b/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_frac_mem32K_frac_dsp36_40nm.xml @@ -321,7 +321,7 @@ - + 1 1 1 1 1 1 1 1 1 From 18735894f9ef167c2f30e7c927cdd29a83e08a22 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 19 Aug 2020 15:27:30 -0600 Subject: [PATCH 21/31] bug fix in openfpga arch: data1 and out1 should have the same offset as the data2 and out2 --- ...c_N10_adder_chain_frac_mem32K_frac_dsp36_40nm_openfpga.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_frac_mem32K_frac_dsp36_40nm_openfpga.xml b/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_frac_mem32K_frac_dsp36_40nm_openfpga.xml index 1eddefe25..ef872ccbf 100644 --- a/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_frac_mem32K_frac_dsp36_40nm_openfpga.xml +++ b/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_frac_mem32K_frac_dsp36_40nm_openfpga.xml @@ -309,9 +309,9 @@ - + - + From f0bc6f83f1b0943fef95c81166196762c01974e6 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 19 Aug 2020 15:34:59 -0600 Subject: [PATCH 22/31] disable buffer absorbing in the template script for bitstream generation. This is applicable to a wide range of benchmarks --- .../generate_bitstream_example_script.openfpga | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openfpga_flow/OpenFPGAShellScripts/generate_bitstream_example_script.openfpga b/openfpga_flow/OpenFPGAShellScripts/generate_bitstream_example_script.openfpga index ab79ce90a..d1b8b4ada 100644 --- a/openfpga_flow/OpenFPGAShellScripts/generate_bitstream_example_script.openfpga +++ b/openfpga_flow/OpenFPGAShellScripts/generate_bitstream_example_script.openfpga @@ -1,6 +1,6 @@ # Run VPR for the 'and' design #--write_rr_graph example_rr_graph.xml -vpr ${VPR_ARCH_FILE} ${VPR_TESTBENCH_BLIF} --clock_modeling route +vpr ${VPR_ARCH_FILE} ${VPR_TESTBENCH_BLIF} --clock_modeling route --absorb_buffer_luts off # Read OpenFPGA architecture definition read_openfpga_arch -f ${OPENFPGA_ARCH_FILE} From f3ca1c0973237fe845476704c76879e47ece4ec8 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 19 Aug 2020 17:28:25 -0600 Subject: [PATCH 23/31] fix rr_graph on thru routing channel support --- vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp index 4107d4538..3e9004175 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp @@ -840,7 +840,7 @@ void load_chanx_rr_nodes_basic_info(RRGraph& rr_graph, * track0 ----->+-----------------------------+----> track0 * | | */ - if (true == is_chanx_exist(grids, chanx_coord)) { + if (true == is_chanx_exist(grids, chanx_coord, through_channel)) { /* Rotate the chanx_details by an offset of ix - 1, the distance to the most left channel */ /* For INC_DIRECTION, we use clockwise rotation * node_id A ----> -----> node_id D @@ -951,7 +951,7 @@ void load_chany_rr_nodes_basic_info(RRGraph& rr_graph, * | | * we should rotate only once at the bottom side of a grid */ - if (true == is_chany_exist(grids, chany_coord)) { + if (true == is_chany_exist(grids, chany_coord, through_channel)) { /* Rotate the chany_details by an offset of 1*/ /* For INC_DIRECTION, we use clockwise rotation * node_id A ----> -----> node_id D From bf08e1841caed464f7efc8ea5bdd95adf59562cd Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 19 Aug 2020 17:58:34 -0600 Subject: [PATCH 24/31] add new test case using thru channels --- .../thru_channel/config/task.conf | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 openfpga_flow/tasks/fpga_verilog/thru_channel/config/task.conf diff --git a/openfpga_flow/tasks/fpga_verilog/thru_channel/config/task.conf b/openfpga_flow/tasks/fpga_verilog/thru_channel/config/task.conf new file mode 100644 index 000000000..1e2941de1 --- /dev/null +++ b/openfpga_flow/tasks/fpga_verilog/thru_channel/config/task.conf @@ -0,0 +1,36 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = true +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=vpr_blif + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/OpenFPGAShellScripts/example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_mem16K_40nm_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k6_frac_N10_tileable_thru_channel_adder_chain_mem16K_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.blif + +[SYNTHESIS_PARAM] +bench0_top = and2 +bench0_act = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.act +bench0_verilog = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= +vpr_fpga_verilog_formal_verification_top_netlist= From d6d17675e26cf62bd9ef17aced1ab55f77fb9fa0 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 19 Aug 2020 18:01:32 -0600 Subject: [PATCH 25/31] update docoumentation about the constraints when using tileable rr_graph generator --- docs/source/manual/arch_lang/addon_vpr_syntax.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/source/manual/arch_lang/addon_vpr_syntax.rst b/docs/source/manual/arch_lang/addon_vpr_syntax.rst index 18f61703a..4af72aa7c 100644 --- a/docs/source/manual/arch_lang/addon_vpr_syntax.rst +++ b/docs/source/manual/arch_lang/addon_vpr_syntax.rst @@ -54,6 +54,8 @@ Layout .. warning:: Currently ``through_channel`` supports only a fixed routing channel width! + .. warning:: You must define custom pin location for the ``height > 1`` or ``width >1`` tiles when using the tileable routing resource graph!!! Otherwise, it will cause undriven pins in your device!!! + A quick example to show tileable routing is enabled and through channels are disabled: From 47f15729adda78734f5222071f044ae2b145bd6b Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 19 Aug 2020 18:37:28 -0600 Subject: [PATCH 26/31] update doc about the limitation on using tileable routing --- docs/source/manual/arch_lang/addon_vpr_syntax.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/manual/arch_lang/addon_vpr_syntax.rst b/docs/source/manual/arch_lang/addon_vpr_syntax.rst index 4af72aa7c..dc7e868b6 100644 --- a/docs/source/manual/arch_lang/addon_vpr_syntax.rst +++ b/docs/source/manual/arch_lang/addon_vpr_syntax.rst @@ -54,7 +54,7 @@ Layout .. warning:: Currently ``through_channel`` supports only a fixed routing channel width! - .. warning:: You must define custom pin location for the ``height > 1`` or ``width >1`` tiles when using the tileable routing resource graph!!! Otherwise, it will cause undriven pins in your device!!! + .. warning:: You cannot use ``spread`` pin location for the ``height > 1`` or ``width >1`` tiles when using the tileable routing resource graph!!! Otherwise, it will cause undriven pins in your device!!! A quick example to show tileable routing is enabled and through channels are disabled: From 881672d46a7ef58abf908fb9213340ca657162d7 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 19 Aug 2020 19:52:35 -0600 Subject: [PATCH 27/31] update thru channel arch for avoid buggy pin locations --- ...N10_tileable_thru_channel_adder_chain_mem16K_40nm.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/openfpga_flow/vpr_arch/k6_frac_N10_tileable_thru_channel_adder_chain_mem16K_40nm.xml b/openfpga_flow/vpr_arch/k6_frac_N10_tileable_thru_channel_adder_chain_mem16K_40nm.xml index 7e4cf8e7a..ffefc9146 100644 --- a/openfpga_flow/vpr_arch/k6_frac_N10_tileable_thru_channel_adder_chain_mem16K_40nm.xml +++ b/openfpga_flow/vpr_arch/k6_frac_N10_tileable_thru_channel_adder_chain_mem16K_40nm.xml @@ -188,7 +188,14 @@ - + + From 8041c90f127aceb35499fadc37aff1c4efee7a40 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 19 Aug 2020 20:01:50 -0600 Subject: [PATCH 28/31] bug fix in through channel support in tileable routing --- vpr/src/route/route_common.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vpr/src/route/route_common.cpp b/vpr/src/route/route_common.cpp index 8fd661d05..6ced2779f 100644 --- a/vpr/src/route/route_common.cpp +++ b/vpr/src/route/route_common.cpp @@ -292,7 +292,7 @@ bool try_route(int width_fac, segment_inf, router_opts.base_cost_type, router_opts.trim_empty_channels, - router_opts.trim_obs_channels, + router_opts.trim_obs_channels || det_routing_arch->through_channel, router_opts.clock_modeling, directs, num_directs, &warning_count); From 1a3e0201749c2078cc8dacde28be0d1b1c9f02dc Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 19 Aug 2020 20:04:01 -0600 Subject: [PATCH 29/31] deploy through channel test case to CI --- .travis/fpga_verilog_reg_test.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis/fpga_verilog_reg_test.sh b/.travis/fpga_verilog_reg_test.sh index 7ee1a5095..8424475fb 100755 --- a/.travis/fpga_verilog_reg_test.sh +++ b/.travis/fpga_verilog_reg_test.sh @@ -81,6 +81,9 @@ python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/power_gated_design/p echo -e "Testing Depopulated crossbar in local routing"; python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/depopulate_crossbar --debug --show_thread_logs +echo -e "Testing through channels in tileable routing"; +python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/thru_channel --debug --show_thread_logs + # Verify MCNC big20 benchmark suite with ModelSim # Please make sure you have ModelSim installed in the environment # Otherwise, it will fail From 6c925dcded560ac9b7525341830c26f12ad3661b Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 19 Aug 2020 20:11:37 -0600 Subject: [PATCH 30/31] [regression test] Add more tests for thru channels and deploy to CI --- .travis/fpga_verilog_reg_test.sh | 3 +- .../{ => thru_narrow_tile}/config/task.conf | 0 .../thru_wide_tile/config/task.conf | 36 + ..._tileable_adder_chain_wide_mem16K_40nm.xml | 2 +- ...u_channel_adder_chain_wide_mem16K_40nm.xml | 734 ++++++++++++++++++ 5 files changed, 773 insertions(+), 2 deletions(-) rename openfpga_flow/tasks/fpga_verilog/thru_channel/{ => thru_narrow_tile}/config/task.conf (100%) create mode 100644 openfpga_flow/tasks/fpga_verilog/thru_channel/thru_wide_tile/config/task.conf create mode 100644 openfpga_flow/vpr_arch/k6_frac_N10_tileable_thru_channel_adder_chain_wide_mem16K_40nm.xml diff --git a/.travis/fpga_verilog_reg_test.sh b/.travis/fpga_verilog_reg_test.sh index 8424475fb..fde145744 100755 --- a/.travis/fpga_verilog_reg_test.sh +++ b/.travis/fpga_verilog_reg_test.sh @@ -82,7 +82,8 @@ echo -e "Testing Depopulated crossbar in local routing"; python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/depopulate_crossbar --debug --show_thread_logs echo -e "Testing through channels in tileable routing"; -python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/thru_channel --debug --show_thread_logs +python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/thru_channel/thru_narrow_tile --debug --show_thread_logs +python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/thru_channel/thru_wide_tile --debug --show_thread_logs # Verify MCNC big20 benchmark suite with ModelSim # Please make sure you have ModelSim installed in the environment diff --git a/openfpga_flow/tasks/fpga_verilog/thru_channel/config/task.conf b/openfpga_flow/tasks/fpga_verilog/thru_channel/thru_narrow_tile/config/task.conf similarity index 100% rename from openfpga_flow/tasks/fpga_verilog/thru_channel/config/task.conf rename to openfpga_flow/tasks/fpga_verilog/thru_channel/thru_narrow_tile/config/task.conf diff --git a/openfpga_flow/tasks/fpga_verilog/thru_channel/thru_wide_tile/config/task.conf b/openfpga_flow/tasks/fpga_verilog/thru_channel/thru_wide_tile/config/task.conf new file mode 100644 index 000000000..5f6de1078 --- /dev/null +++ b/openfpga_flow/tasks/fpga_verilog/thru_channel/thru_wide_tile/config/task.conf @@ -0,0 +1,36 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = true +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=vpr_blif + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/OpenFPGAShellScripts/example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_mem16K_40nm_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k6_frac_N10_tileable_thru_channel_adder_chain_wide_mem16K_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.blif + +[SYNTHESIS_PARAM] +bench0_top = and2 +bench0_act = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.act +bench0_verilog = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= +vpr_fpga_verilog_formal_verification_top_netlist= diff --git a/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_wide_mem16K_40nm.xml b/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_wide_mem16K_40nm.xml index f07f16c80..46b23c83e 100644 --- a/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_wide_mem16K_40nm.xml +++ b/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_wide_mem16K_40nm.xml @@ -188,7 +188,7 @@ - + diff --git a/openfpga_flow/vpr_arch/k6_frac_N10_tileable_thru_channel_adder_chain_wide_mem16K_40nm.xml b/openfpga_flow/vpr_arch/k6_frac_N10_tileable_thru_channel_adder_chain_wide_mem16K_40nm.xml new file mode 100644 index 000000000..bc5c762b3 --- /dev/null +++ b/openfpga_flow/vpr_arch/k6_frac_N10_tileable_thru_channel_adder_chain_wide_mem16K_40nm.xml @@ -0,0 +1,734 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + io.outpad io.inpad + io.outpad io.inpad + io.outpad io.inpad + io.outpad io.inpad + + + + + + + + + + + + + + + + + + + clb.clk + clb.cin + clb.O[9:0] clb.I[19:0] + clb.cout clb.O[19:10] clb.I[39:20] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 1 1 1 1 + 1 1 1 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 235e-12 + 235e-12 + 235e-12 + 235e-12 + 235e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 195e-12 + 195e-12 + 195e-12 + 195e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 261e-12 + 261e-12 + 261e-12 + 261e-12 + 261e-12 + 261e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From fb5a5a244871c52e6608be163757a6ba942ee0b7 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 19 Aug 2020 20:12:49 -0600 Subject: [PATCH 31/31] [documentation] remove the limitation on through channels --- docs/source/manual/arch_lang/addon_vpr_syntax.rst | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/source/manual/arch_lang/addon_vpr_syntax.rst b/docs/source/manual/arch_lang/addon_vpr_syntax.rst index dc7e868b6..773ac0992 100644 --- a/docs/source/manual/arch_lang/addon_vpr_syntax.rst +++ b/docs/source/manual/arch_lang/addon_vpr_syntax.rst @@ -52,8 +52,6 @@ Layout .. warning:: Do NOT enable ``through_channel`` if you are not using the tileable routing resource graph generator! - .. warning:: Currently ``through_channel`` supports only a fixed routing channel width! - .. warning:: You cannot use ``spread`` pin location for the ``height > 1`` or ``width >1`` tiles when using the tileable routing resource graph!!! Otherwise, it will cause undriven pins in your device!!!