Merge pull request #212 from lnis-uofu/soft_adder_lut_support

Support overloading LUT bitstream from attributes in .eblif file format
This commit is contained in:
ganeshgore 2021-02-04 21:55:02 -07:00 committed by GitHub
commit ee14c15e58
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
47 changed files with 1685 additions and 13 deletions

View File

@ -30,7 +30,10 @@ echo -e "Testing Verilog generation with VPR's untileable routing architecture "
run-task fpga_verilog/untileable --debug --show_thread_logs
echo -e "Testing Verilog generation with hard adder chain in CLBs ";
run-task fpga_verilog/hard_adder --debug --show_thread_logs
run-task fpga_verilog/adder/hard_adder --debug --show_thread_logs
echo -e "Testing Verilog generation with soft adder chain in CLBs ";
run-task fpga_verilog/adder/soft_adder --debug --show_thread_logs
echo -e "Testing Verilog generation with 16k block RAMs ";
run-task fpga_verilog/bram/dpram16k --debug --show_thread_logs

View File

@ -0,0 +1,27 @@
.. _file_formats_bitstream_setting:
Bitstream Setting (.xml)
------------------------
An example of bitstream settings is shown as follows.
This can define a hard-coded bitstream for a reconfigurable resource in FPGA fabrics.
.. code-block:: xml
<openfpga_bitstream_setting>
<pb_type name="<string>" source="eblif" content=".param LUT"/>
</openfpga_bitstream_setting>
.. option:: pb_type="<string>"
The ``pb_type`` name to be constrained, which should be the full path of a ``pb_type`` consistent with VPR's architecture description. For example, ``pb_type="clb.fle[arithmetic].soft_adder.adder_lut4"``
.. option:: source="<string>"
The source of the ``pb_type`` bitstream, which could be from a ``.eblif`` file. For example, ``source="eblif"``.
.. option:: content="<string>"
The content of the ``pb_type`` bitstream, which could be a keyword in a ``.eblif`` file. For example, ``content=".attr LUT"`` means that the bitstream will be extracted from the ``.attr LUT`` line which is defined under the ``.blif model`` (that is defined under the ``pb_type`` in VPR architecture file).
.. warning:: Bitstream is a feature for power-users. It may cause wrong bitstream to be generated. For example, the hard-coded bitstream is not compatible with LUTs whose nets may be swapped during routing stage (cause a change on the truth table as well as bitstream). It is users's responsibility to ensure correct bitstream.

View File

@ -18,4 +18,6 @@ OpenFPGA widely uses XML format for interchangable files
fabric_bitstream
bitstream_setting
fabric_key

View File

@ -56,6 +56,33 @@ write_openfpga_simulation_setting
Show verbose log
read_openfpga_bitstream_setting
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Read the XML file about bitstream settings (see details in :ref:`file_formats_bitstream_setting`)
.. option:: --file <string> or -f <string>
Specify the file name. For example, ``--file bitstream_setting.xml``
.. option:: --verbose
Show verbose log
write_openfpga_bitstream_setting
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Write the OpenFPGA XML bitstream settings to a file
.. option:: --file <string> or -f <string>
Specify the file name. For example, ``--file auto_bitstream_setting_echo.xml``.
See details about file format at :ref:`file_formats_bitstream_setting`.
.. option:: --verbose
Show verbose log
link_openfpga_arch
~~~~~~~~~~~~~~~~~~

View File

@ -0,0 +1,80 @@
#include "vtr_assert.h"
#include "bitstream_setting.h"
/* namespace openfpga begins */
namespace openfpga {
/************************************************************************
* Member functions for class BitstreamSetting
***********************************************************************/
/************************************************************************
* Public Accessors : aggregates
***********************************************************************/
BitstreamSetting::bitstream_pb_type_setting_range BitstreamSetting::pb_type_settings() const {
return vtr::make_range(pb_type_setting_ids_.begin(), pb_type_setting_ids_.end());
}
/************************************************************************
* Constructors
***********************************************************************/
BitstreamSetting::BitstreamSetting() {
return;
}
/************************************************************************
* Public Accessors
***********************************************************************/
std::string BitstreamSetting::pb_type_name(const BitstreamPbTypeSettingId& pb_type_setting_id) const {
VTR_ASSERT(true == valid_bitstream_pb_type_setting_id(pb_type_setting_id));
return pb_type_names_[pb_type_setting_id];
}
std::vector<std::string> BitstreamSetting::parent_pb_type_names(const BitstreamPbTypeSettingId& pb_type_setting_id) const {
VTR_ASSERT(true == valid_bitstream_pb_type_setting_id(pb_type_setting_id));
return parent_pb_type_names_[pb_type_setting_id];
}
std::vector<std::string> BitstreamSetting::parent_mode_names(const BitstreamPbTypeSettingId& pb_type_setting_id) const {
VTR_ASSERT(true == valid_bitstream_pb_type_setting_id(pb_type_setting_id));
return parent_mode_names_[pb_type_setting_id];
}
std::string BitstreamSetting::pb_type_bitstream_source(const BitstreamPbTypeSettingId& pb_type_setting_id) const {
VTR_ASSERT(true == valid_bitstream_pb_type_setting_id(pb_type_setting_id));
return pb_type_bitstream_sources_[pb_type_setting_id];
}
std::string BitstreamSetting::pb_type_bitstream_content(const BitstreamPbTypeSettingId& pb_type_setting_id) const {
VTR_ASSERT(true == valid_bitstream_pb_type_setting_id(pb_type_setting_id));
return pb_type_bitstream_contents_[pb_type_setting_id];
}
/************************************************************************
* Public Mutators
***********************************************************************/
BitstreamPbTypeSettingId BitstreamSetting::add_bitstream_pb_type_setting(const std::string& pb_type_name,
const std::vector<std::string>& parent_pb_type_names,
const std::vector<std::string>& parent_mode_names,
const std::string& bitstream_source,
const std::string& bitstream_content) {
BitstreamPbTypeSettingId pb_type_setting_id = BitstreamPbTypeSettingId(pb_type_setting_ids_.size());
pb_type_setting_ids_.push_back(pb_type_setting_id);
pb_type_names_.push_back(pb_type_name);
parent_pb_type_names_.push_back(parent_pb_type_names);
parent_mode_names_.push_back(parent_mode_names);
pb_type_bitstream_sources_.push_back(bitstream_source);
pb_type_bitstream_contents_.push_back(bitstream_content);
return pb_type_setting_id;
}
/************************************************************************
* Public Validators
***********************************************************************/
bool BitstreamSetting::valid_bitstream_pb_type_setting_id(const BitstreamPbTypeSettingId& pb_type_setting_id) const {
return ( size_t(pb_type_setting_id) < pb_type_setting_ids_.size() ) && ( pb_type_setting_id == pb_type_setting_ids_[pb_type_setting_id] );
}
} /* namespace openfpga ends */

View File

@ -0,0 +1,61 @@
#ifndef BITSTREAM_SETTING_H
#define BITSTREAM_SETTING_H
/********************************************************************
* This file include the declaration of simulation settings
* which are used by OpenFPGA
*******************************************************************/
#include <string>
#include "vtr_vector.h"
#include "bitstream_setting_fwd.h"
/* namespace openfpga begins */
namespace openfpga {
/********************************************************************
* A data structure to describe bitstream settings
*
* Typical usage:
* --------------
* // Create an empty bitstream setting
* BitstreamSetting bitstream_setting;
* // call your builder for bitstream_setting
*
*******************************************************************/
class BitstreamSetting {
public: /* Types */
typedef vtr::vector<BitstreamPbTypeSettingId, BitstreamPbTypeSettingId>::const_iterator bitstream_pb_type_setting_iterator;
/* Create range */
typedef vtr::Range<bitstream_pb_type_setting_iterator> bitstream_pb_type_setting_range;
public: /* Constructors */
BitstreamSetting();
public: /* Accessors: aggregates */
bitstream_pb_type_setting_range pb_type_settings() const;
public: /* Public Accessors */
std::string pb_type_name(const BitstreamPbTypeSettingId& pb_type_setting_id) const;
std::vector<std::string> parent_pb_type_names(const BitstreamPbTypeSettingId& pb_type_setting_id) const;
std::vector<std::string> parent_mode_names(const BitstreamPbTypeSettingId& pb_type_setting_id) const;
std::string pb_type_bitstream_source(const BitstreamPbTypeSettingId& pb_type_setting_id) const;
std::string pb_type_bitstream_content(const BitstreamPbTypeSettingId& pb_type_setting_id) const;
public: /* Public Mutators */
BitstreamPbTypeSettingId add_bitstream_pb_type_setting(const std::string& pb_type_name,
const std::vector<std::string>& parent_pb_type_names,
const std::vector<std::string>& parent_mode_names,
const std::string& bitstream_source,
const std::string& bitstream_content);
public: /* Public Validators */
bool valid_bitstream_pb_type_setting_id(const BitstreamPbTypeSettingId& pb_type_setting_id) const;
private: /* Internal data */
vtr::vector<BitstreamPbTypeSettingId, BitstreamPbTypeSettingId> pb_type_setting_ids_;
vtr::vector<BitstreamPbTypeSettingId, std::string> pb_type_names_;
vtr::vector<BitstreamPbTypeSettingId, std::vector<std::string>> parent_pb_type_names_;
vtr::vector<BitstreamPbTypeSettingId, std::vector<std::string>> parent_mode_names_;
vtr::vector<BitstreamPbTypeSettingId, std::string> pb_type_bitstream_sources_;
vtr::vector<BitstreamPbTypeSettingId, std::string> pb_type_bitstream_contents_;
};
} /* namespace openfpga ends */
#endif

View File

@ -0,0 +1,22 @@
/************************************************************************
* A header file for BitstreamSetting class, including critical data declaration
* Please include this file only for using any BitstreamSetting data structure
* Refer to bitstream_setting.h for more details
***********************************************************************/
/************************************************************************
* Create strong id for the pb_type annotation in Bitstream setting to avoid illegal type casting
***********************************************************************/
#ifndef BITSTREAM_SETTING_FWD_H
#define BITSTREAM_SETTING_FWD_H
#include "vtr_strong_id.h"
struct bitstream_pb_type_setting_id_tag;
typedef vtr::StrongId<bitstream_pb_type_setting_id_tag> BitstreamPbTypeSettingId;
/* Short declaration of class */
class BitstreamSetting;
#endif

View File

@ -6,7 +6,6 @@
#include "circuit_library.h"
#include "technology_library.h"
#include "simulation_setting.h"
#include "config_protocol.h"
#include "arch_direct.h"
#include "tile_annotation.h"

View File

@ -0,0 +1,65 @@
/********************************************************************
* This file includes the top-level function of this library
* which reads an XML modeling OpenFPGA architecture to the associated
* data structures
*******************************************************************/
#include <string>
/* Headers from pugi XML library */
#include "pugixml.hpp"
#include "pugixml_util.hpp"
/* Headers from vtr util library */
#include "vtr_assert.h"
/* Headers from openfpga util library */
#include "openfpga_pb_parser.h"
/* Headers from libarchfpga */
#include "arch_error.h"
#include "read_xml_util.h"
#include "read_xml_bitstream_setting.h"
/********************************************************************
* Parse XML description for a pb_type annotation under a <pb_type> XML node
*******************************************************************/
static
void read_xml_bitstream_pb_type_setting(pugi::xml_node& xml_pb_type,
const pugiutil::loc_data& loc_data,
openfpga::BitstreamSetting& bitstream_setting) {
const std::string& name_attr = get_attribute(xml_pb_type, "name", loc_data).as_string();
const std::string& source_attr = get_attribute(xml_pb_type, "source", loc_data).as_string();
const std::string& content_attr = get_attribute(xml_pb_type, "content", loc_data).as_string();
/* Parse the attributes for operating pb_type */
openfpga::PbParser operating_pb_parser(name_attr);
/* Add to bitstream setting */
bitstream_setting.add_bitstream_pb_type_setting(operating_pb_parser.leaf(),
operating_pb_parser.parents(),
operating_pb_parser.modes(),
source_attr,
content_attr);
}
/********************************************************************
* Parse XML codes about <openfpga_bitstream_setting> to an object
*******************************************************************/
openfpga::BitstreamSetting read_xml_bitstream_setting(pugi::xml_node& Node,
const pugiutil::loc_data& loc_data) {
openfpga::BitstreamSetting bitstream_setting;
/* Iterate over the children under this node,
* each child should be named after <pb_type>
*/
for (pugi::xml_node xml_pb_type : Node.children()) {
/* Error out if the XML child has an invalid name! */
if (xml_pb_type.name() != std::string("pb_type")) {
bad_tag(xml_pb_type, loc_data, Node, {"pb_type"});
}
read_xml_bitstream_pb_type_setting(xml_pb_type, loc_data, bitstream_setting);
}
return bitstream_setting;
}

View File

@ -0,0 +1,18 @@
#ifndef READ_XML_BITSTREAM_SETTING_H
#define READ_XML_BITSTREAM_SETTING_H
/********************************************************************
* Include header files that are required by function declaration
*******************************************************************/
#include "pugixml_util.hpp"
#include "pugixml.hpp"
#include "bitstream_setting.h"
/********************************************************************
* Function declaration
*******************************************************************/
openfpga::BitstreamSetting read_xml_bitstream_setting(pugi::xml_node& Node,
const pugiutil::loc_data& loc_data);
#endif

View File

@ -23,6 +23,7 @@
#include "read_xml_routing_circuit.h"
#include "read_xml_tile_annotation.h"
#include "read_xml_pb_type_annotation.h"
#include "read_xml_bitstream_setting.h"
#include "read_xml_openfpga_arch.h"
#include "openfpga_arch_linker.h"
@ -149,3 +150,34 @@ openfpga::SimulationSetting read_xml_openfpga_simulation_settings(const char* si
return openfpga_sim_setting;
}
/********************************************************************
* Top-level function to parse an XML file and load data to bitstream settings
*******************************************************************/
openfpga::BitstreamSetting read_xml_openfpga_bitstream_settings(const char* bitstream_setting_file_name) {
vtr::ScopedStartFinishTimer timer("Read OpenFPGA bitstream settings");
openfpga::BitstreamSetting openfpga_bitstream_setting;
pugi::xml_node Next;
/* Parse the file */
pugi::xml_document doc;
pugiutil::loc_data loc_data;
try {
loc_data = pugiutil::load_xml(doc, bitstream_setting_file_name);
/* Second node should be <openfpga_simulation_setting> */
auto xml_bitstream_settings = get_single_child(doc, "openfpga_bitstream_setting", loc_data);
/* Parse simulation settings to data structure */
openfpga_bitstream_setting = read_xml_bitstream_setting(xml_bitstream_settings, loc_data);
} catch (pugiutil::XmlError& e) {
archfpga_throw(bitstream_setting_file_name, e.line(),
"%s", e.what());
}
return openfpga_bitstream_setting;
}

View File

@ -6,6 +6,8 @@
*******************************************************************/
#include <string>
#include "openfpga_arch.h"
#include "simulation_setting.h"
#include "bitstream_setting.h"
/********************************************************************
* Function declaration
@ -14,4 +16,6 @@ openfpga::Arch read_xml_openfpga_arch(const char* arch_file_name);
openfpga::SimulationSetting read_xml_openfpga_simulation_settings(const char* sim_setting_file_name);
openfpga::BitstreamSetting read_xml_openfpga_bitstream_settings(const char* bitstream_setting_file_name);
#endif

View File

@ -0,0 +1,84 @@
/********************************************************************
* This file includes functions that outputs a bitstream setting to XML format
*******************************************************************/
/* Headers from system goes first */
#include <string>
#include <algorithm>
/* Headers from vtr util library */
#include "vtr_assert.h"
#include "vtr_log.h"
#include "openfpga_digest.h"
/* Headers from readarchopenfpga library */
#include "write_xml_utils.h"
#include "write_xml_bitstream_setting.h"
/********************************************************************
* Generate the full hierarchy name for a pb_type in bitstream setting
*******************************************************************/
static
std::string generate_bitstream_setting_pb_type_hierarchy_name(const openfpga::BitstreamSetting& bitstream_setting,
const BitstreamPbTypeSettingId& bitstream_pb_type_setting_id) {
/* Iterate over the parent_pb_type and modes names, they should well match */
VTR_ASSERT_SAFE(bitstream_setting.parent_pb_type_names(bitstream_pb_type_setting_id).size() == bitstream_setting.parent_mode_names(bitstream_pb_type_setting_id).size());
std::string hie_name;
for (size_t i = 0 ; i < bitstream_setting.parent_pb_type_names(bitstream_pb_type_setting_id).size(); ++i) {
hie_name += bitstream_setting.parent_pb_type_names(bitstream_pb_type_setting_id)[i];
hie_name += std::string("[");
hie_name += bitstream_setting.parent_mode_names(bitstream_pb_type_setting_id)[i];
hie_name += std::string("]");
hie_name += std::string(".");
}
/* Add the leaf pb_type */
hie_name += bitstream_setting.pb_type_name(bitstream_pb_type_setting_id);
return hie_name;
}
/********************************************************************
* A writer to output a bitstream pb_type setting to XML format
*******************************************************************/
static
void write_xml_bitstream_pb_type_setting(std::fstream& fp,
const char* fname,
const openfpga::BitstreamSetting& bitstream_setting,
const BitstreamPbTypeSettingId& bitstream_pb_type_setting_id) {
/* Validate the file stream */
openfpga::check_file_stream(fname, fp);
fp << "\t" << "<pb_type";
/* Generate the full hierarchy name of the pb_type */
write_xml_attribute(fp, "name", generate_bitstream_setting_pb_type_hierarchy_name(bitstream_setting, bitstream_pb_type_setting_id).c_str());
write_xml_attribute(fp, "source", bitstream_setting.pb_type_bitstream_source(bitstream_pb_type_setting_id).c_str());
write_xml_attribute(fp, "content", bitstream_setting.pb_type_bitstream_content(bitstream_pb_type_setting_id).c_str());
fp << "/>" << "\n";
}
/********************************************************************
* A writer to output a bitstream setting to XML format
*******************************************************************/
void write_xml_bitstream_setting(std::fstream& fp,
const char* fname,
const openfpga::BitstreamSetting& bitstream_setting) {
/* Validate the file stream */
openfpga::check_file_stream(fname, fp);
/* Write the root node <openfpga_bitstream_setting>
*/
fp << "<openfpga_bitstream_setting>" << "\n";
/* Write clock settings */
for (const auto& bitstream_pb_type_setting_id : bitstream_setting.pb_type_settings()) {
write_xml_bitstream_pb_type_setting(fp, fname, bitstream_setting, bitstream_pb_type_setting_id);
}
/* Write the root node <openfpga_bitstream_setting> */
fp << "</openfpga_bitstream_setting>" << "\n";
}

View File

@ -0,0 +1,17 @@
#ifndef WRITE_XML_BITSTREAM_SETTING_H
#define WRITE_XML_BITSTREAM_SETTING_H
/********************************************************************
* Include header files that are required by function declaration
*******************************************************************/
#include <fstream>
#include "bitstream_setting.h"
/********************************************************************
* Function declaration
*******************************************************************/
void write_xml_bitstream_setting(std::fstream& fp,
const char* fname,
const openfpga::BitstreamSetting& bitstream_setting);
#endif

View File

@ -14,6 +14,7 @@
#include "write_xml_circuit_library.h"
#include "write_xml_technology_library.h"
#include "write_xml_simulation_setting.h"
#include "write_xml_bitstream_setting.h"
#include "write_xml_config_protocol.h"
#include "write_xml_routing_circuit.h"
#include "write_xml_tile_annotation.h"
@ -92,3 +93,25 @@ void write_xml_openfpga_simulation_settings(const char* fname,
/* Close the file stream */
fp.close();
}
/********************************************************************
* A writer to output an OpenFPGA bitstream setting database to XML format
*******************************************************************/
void write_xml_openfpga_bitstream_settings(const char* fname,
const openfpga::BitstreamSetting& openfpga_bitstream_setting) {
vtr::ScopedStartFinishTimer timer("Write OpenFPGA bitstream settings");
/* Create a file handler */
std::fstream fp;
/* Open the file stream */
fp.open(std::string(fname), std::fstream::out | std::fstream::trunc);
/* Validate the file stream */
openfpga::check_file_stream(fname, fp);
/* Write the simulation */
write_xml_bitstream_setting(fp, fname, openfpga_bitstream_setting);
/* Close the file stream */
fp.close();
}

View File

@ -16,5 +16,8 @@ void write_xml_openfpga_arch(const char* xml_fname,
void write_xml_openfpga_simulation_settings(const char* xml_fname,
const openfpga::SimulationSetting& openfpga_sim_setting);
void write_xml_openfpga_bitstream_settings(const char* fname,
const openfpga::BitstreamSetting& openfpga_bitstream_setting);
#endif

View File

@ -0,0 +1,31 @@
/********************************************************************
* Unit test functions to validate the correctness of
* 1. parser of data structures
* 2. writer of data structures
*******************************************************************/
/* Headers from vtrutils */
#include "vtr_assert.h"
#include "vtr_log.h"
/* Headers from readarchopenfpga */
#include "read_xml_openfpga_arch.h"
#include "write_xml_openfpga_arch.h"
int main(int argc, const char** argv) {
/* Ensure we have only one or two argument */
VTR_ASSERT((2 == argc) || (3 == argc));
/* Parse the simulation settings from an XML file */
const openfpga::BitstreamSetting& openfpga_bitstream_setting = read_xml_openfpga_bitstream_settings(argv[1]);
VTR_LOG("Parsed bitstream settings from XML %s.\n",
argv[1]);
/* Output the simulation settings to an XML file
* This is optional only used when there is a second argument
*/
if (3 <= argc) {
write_xml_openfpga_bitstream_settings(argv[2], openfpga_bitstream_setting);
VTR_LOG("Echo the OpenFPGA bitstream settings to an XML file: %s.\n",
argv[2]);
}
}

View File

@ -0,0 +1,85 @@
/********************************************************************
* This file includes functions that are used to annotate pb_type
* from VPR to OpenFPGA
*******************************************************************/
#include <cmath>
#include <iterator>
/* Headers from openfpgashell library */
#include "command_exit_codes.h"
/* Headers from vtrutil library */
#include "vtr_assert.h"
#include "vtr_log.h"
#include "pb_type_utils.h"
#include "annotate_bitstream_setting.h"
/* begin namespace openfpga */
namespace openfpga {
/********************************************************************
* Annotate bitstream setting based on VPR device information
* - Find the pb_type and link to the bitstream source
* - Find the pb_type and link to the bitstream content
*******************************************************************/
int annotate_bitstream_setting(const BitstreamSetting& bitstream_setting,
const DeviceContext& vpr_device_ctx,
VprBitstreamAnnotation& vpr_bitstream_annotation) {
for (const auto& bitstream_pb_type_setting_id : bitstream_setting.pb_type_settings()) {
/* Get the full name of pb_type */
std::vector<std::string> target_pb_type_names;
std::vector<std::string> target_pb_mode_names;
target_pb_type_names = bitstream_setting.parent_pb_type_names(bitstream_pb_type_setting_id);
target_pb_type_names.push_back(bitstream_setting.pb_type_name(bitstream_pb_type_setting_id));
target_pb_mode_names = bitstream_setting.parent_mode_names(bitstream_pb_type_setting_id);
/* Pb type information are located at the logic_block_types in the device context of VPR
* We iterate over the vectors and find the pb_type matches the parent_pb_type_name
*/
bool link_success = false;
for (const t_logical_block_type& lb_type : vpr_device_ctx.logical_block_types) {
/* By pass nullptr for pb_type head */
if (nullptr == lb_type.pb_type) {
continue;
}
/* Check the name of the top-level pb_type, if it does not match, we can bypass */
if (target_pb_type_names[0] != std::string(lb_type.pb_type->name)) {
continue;
}
/* Match the name in the top-level, we go further to search the pb_type in the graph */
t_pb_type* target_pb_type = try_find_pb_type_with_given_path(lb_type.pb_type, target_pb_type_names,
target_pb_mode_names);
if (nullptr == target_pb_type) {
continue;
}
/* Found one, build annotation */
if (std::string("eblif") == bitstream_setting.pb_type_bitstream_source(bitstream_pb_type_setting_id)) {
vpr_bitstream_annotation.set_pb_type_bitstream_source(target_pb_type, VprBitstreamAnnotation::e_bitstream_source_type::BITSTREAM_SOURCE_EBLIF);
} else {
/* Invalid source, error out! */
VTR_LOG_ERROR("Invalid bitstream source '%s' for pb_type '%s' which is defined in bitstream setting\n",
bitstream_setting.pb_type_bitstream_source(bitstream_pb_type_setting_id).c_str(),
target_pb_type_names[0].c_str());
return CMD_EXEC_FATAL_ERROR;
}
vpr_bitstream_annotation.set_pb_type_bitstream_content(target_pb_type, bitstream_setting.pb_type_bitstream_content(bitstream_pb_type_setting_id));
link_success = true;
}
/* If fail to link bitstream setting to architecture, error out immediately */
if (false == link_success) {
VTR_LOG_ERROR("Fail to find a pb_type '%s' which is defined in bitstream setting from VPR architecture description\n",
target_pb_type_names[0].c_str());
return CMD_EXEC_FATAL_ERROR;
}
}
return CMD_EXEC_SUCCESS;
}
} /* end namespace openfpga */

View File

@ -0,0 +1,23 @@
#ifndef ANNOTATE_BITSTREAM_SETTING_H
#define ANNOTATE_BITSTREAM_SETTING_H
/********************************************************************
* Include header files that are required by function declaration
*******************************************************************/
#include "vpr_context.h"
#include "openfpga_context.h"
/********************************************************************
* Function declaration
*******************************************************************/
/* begin namespace openfpga */
namespace openfpga {
int annotate_bitstream_setting(const BitstreamSetting& bitstream_setting,
const DeviceContext& vpr_device_ctx,
VprBitstreamAnnotation& vpr_bitstream_annotation);
} /* end namespace openfpga */
#endif

View File

@ -0,0 +1,54 @@
/************************************************************************
* Member functions for class VprBitstreamAnnotation
***********************************************************************/
#include "vtr_log.h"
#include "vtr_assert.h"
#include "vpr_bitstream_annotation.h"
/* namespace openfpga begins */
namespace openfpga {
/************************************************************************
* Constructors
***********************************************************************/
VprBitstreamAnnotation::VprBitstreamAnnotation() {
return;
}
/************************************************************************
* Public accessors
***********************************************************************/
VprBitstreamAnnotation::e_bitstream_source_type VprBitstreamAnnotation::pb_type_bitstream_source(t_pb_type* pb_type) const {
auto result = bitstream_sources_.find(pb_type);
if (result != bitstream_sources_.end()) {
return result->second;
}
/* Not found, return an invalid type*/
return NUM_BITSTREAM_SOURCE_TYPES;
}
std::string VprBitstreamAnnotation::pb_type_bitstream_content(t_pb_type* pb_type) const {
auto result = bitstream_contents_.find(pb_type);
if (result != bitstream_contents_.end()) {
return result->second;
}
/* Not found, return an invalid type */
return std::string();
}
/************************************************************************
* Public mutators
***********************************************************************/
void VprBitstreamAnnotation::set_pb_type_bitstream_source(t_pb_type* pb_type,
const e_bitstream_source_type& bitstream_source) {
bitstream_sources_[pb_type] = bitstream_source;
}
void VprBitstreamAnnotation::set_pb_type_bitstream_content(t_pb_type* pb_type,
const std::string& bitstream_content) {
bitstream_contents_[pb_type] = bitstream_content;
}
} /* End namespace openfpga*/

View File

@ -0,0 +1,50 @@
#ifndef VPR_BITSTREAM_ANNOTATION_H
#define VPR_BITSTREAM_ANNOTATION_H
/********************************************************************
* Include header files required by the data structure definition
*******************************************************************/
#include <string>
#include <map>
/* Header from vpr library */
#include "vpr_context.h"
/* Begin namespace openfpga */
namespace openfpga {
/********************************************************************
* This is the critical data structure to link the pb_type in VPR
* to openfpga annotations
* With a given pb_type pointer, it aims to identify:
* 1. if the pb_type requires another bitstream source than .blif file
* which may be .eblif file
* 2. if the pb_type requires a fixed bitstream value
* or an attribute line in the .eblif file
*******************************************************************/
class VprBitstreamAnnotation {
public: /* Type */
enum e_bitstream_source_type {
BITSTREAM_SOURCE_EBLIF,
NUM_BITSTREAM_SOURCE_TYPES
};
public: /* Constructor */
VprBitstreamAnnotation();
public: /* Public accessors */
e_bitstream_source_type pb_type_bitstream_source(t_pb_type* pb_type) const;
std::string pb_type_bitstream_content(t_pb_type* pb_type) const;
public: /* Public mutators */
void set_pb_type_bitstream_source(t_pb_type* pb_type,
const e_bitstream_source_type& bitstream_source);
void set_pb_type_bitstream_content(t_pb_type* pb_type,
const std::string& bitstream_content);
private: /* Internal data */
/* A look up for pb type to find bitstream source type */
std::map<t_pb_type*, e_bitstream_source_type> bitstream_sources_;
/* Binding from pb type to bitstream content */
std::map<t_pb_type*, std::string> bitstream_contents_;
};
} /* End namespace openfpga*/
#endif

View File

@ -4,11 +4,14 @@
#include <vector>
#include "vpr_context.h"
#include "openfpga_arch.h"
#include "simulation_setting.h"
#include "bitstream_setting.h"
#include "vpr_netlist_annotation.h"
#include "vpr_device_annotation.h"
#include "vpr_clustering_annotation.h"
#include "vpr_placement_annotation.h"
#include "vpr_routing_annotation.h"
#include "vpr_bitstream_annotation.h"
#include "mux_library.h"
#include "decoder_library.h"
#include "tile_direct.h"
@ -52,11 +55,13 @@ class OpenfpgaContext : public Context {
public: /* Public accessors */
const openfpga::Arch& arch() const { return arch_; }
const openfpga::SimulationSetting& simulation_setting() const { return sim_setting_; }
const openfpga::BitstreamSetting& bitstream_setting() const { return bitstream_setting_; }
const openfpga::VprDeviceAnnotation& vpr_device_annotation() const { return vpr_device_annotation_; }
const openfpga::VprNetlistAnnotation& vpr_netlist_annotation() const { return vpr_netlist_annotation_; }
const openfpga::VprClusteringAnnotation& vpr_clustering_annotation() const { return vpr_clustering_annotation_; }
const openfpga::VprPlacementAnnotation& vpr_placement_annotation() const { return vpr_placement_annotation_; }
const openfpga::VprRoutingAnnotation& vpr_routing_annotation() const { return vpr_routing_annotation_; }
const openfpga::VprBitstreamAnnotation& vpr_bitstream_annotation() const { return vpr_bitstream_annotation_; }
const openfpga::DeviceRRGSB& device_rr_gsb() const { return device_rr_gsb_; }
const openfpga::MuxLibrary& mux_lib() const { return mux_lib_; }
const openfpga::DecoderLibrary& decoder_lib() const { return decoder_lib_; }
@ -72,11 +77,13 @@ class OpenfpgaContext : public Context {
public: /* Public mutators */
openfpga::Arch& mutable_arch() { return arch_; }
openfpga::SimulationSetting& mutable_simulation_setting() { return sim_setting_; }
openfpga::BitstreamSetting& mutable_bitstream_setting() { return bitstream_setting_; }
openfpga::VprDeviceAnnotation& mutable_vpr_device_annotation() { return vpr_device_annotation_; }
openfpga::VprNetlistAnnotation& mutable_vpr_netlist_annotation() { return vpr_netlist_annotation_; }
openfpga::VprClusteringAnnotation& mutable_vpr_clustering_annotation() { return vpr_clustering_annotation_; }
openfpga::VprPlacementAnnotation& mutable_vpr_placement_annotation() { return vpr_placement_annotation_; }
openfpga::VprRoutingAnnotation& mutable_vpr_routing_annotation() { return vpr_routing_annotation_; }
openfpga::VprBitstreamAnnotation& mutable_vpr_bitstream_annotation() { return vpr_bitstream_annotation_; }
openfpga::DeviceRRGSB& mutable_device_rr_gsb() { return device_rr_gsb_; }
openfpga::MuxLibrary& mutable_mux_lib() { return mux_lib_; }
openfpga::DecoderLibrary& mutable_decoder_lib() { return decoder_lib_; }
@ -93,6 +100,7 @@ class OpenfpgaContext : public Context {
/* Data structure to store information from read_openfpga_arch library */
openfpga::Arch arch_;
openfpga::SimulationSetting sim_setting_;
openfpga::BitstreamSetting bitstream_setting_;
/* Annotation to pb_type of VPR */
openfpga::VprDeviceAnnotation vpr_device_annotation_;
@ -109,6 +117,9 @@ class OpenfpgaContext : public Context {
/* Routing results annotation */
openfpga::VprRoutingAnnotation vpr_routing_annotation_;
/* Annotation to pb_type of VPR */
openfpga::VprBitstreamAnnotation vpr_bitstream_annotation_;
/* Device-level annotation */
openfpga::DeviceRRGSB device_rr_gsb_;

View File

@ -21,6 +21,7 @@
#include "annotate_routing.h"
#include "annotate_rr_graph.h"
#include "annotate_simulation_setting.h"
#include "annotate_bitstream_setting.h"
#include "mux_library_builder.h"
#include "build_tile_direct.h"
#include "annotate_placement.h"
@ -168,6 +169,14 @@ int link_arch(OpenfpgaContext& openfpga_ctx,
return CMD_EXEC_FATAL_ERROR;
}
/* Build bitstream annotation based on bitstream settings */
if (CMD_EXEC_FATAL_ERROR == annotate_bitstream_setting(openfpga_ctx.bitstream_setting(),
g_vpr_ctx.device(),
openfpga_ctx.mutable_vpr_bitstream_annotation())) {
return CMD_EXEC_FATAL_ERROR;
}
/* TODO: should identify the error code from internal function execution */
return CMD_EXEC_SUCCESS;
}

View File

@ -152,5 +152,59 @@ int write_simulation_setting(const OpenfpgaContext& openfpga_context,
return CMD_EXEC_SUCCESS;
}
/********************************************************************
* Top-level function to read an OpenFPGA bitstream setting file
* we use the APIs from the libarchopenfpga library
*
* The command will accept an option '--file' which is the bitstream setting
* file provided by users
*******************************************************************/
int read_bitstream_setting(OpenfpgaContext& openfpga_context,
const Command& cmd, const CommandContext& cmd_context) {
/* Check the option '--file' is enabled or not
* Actually, it must be enabled as the shell interface will check
* before reaching this fuction
*/
CommandOptionId opt_file = cmd.option("file");
VTR_ASSERT(true == cmd_context.option_enable(cmd, opt_file));
VTR_ASSERT(false == cmd_context.option_value(cmd, opt_file).empty());
std::string arch_file_name = cmd_context.option_value(cmd, opt_file);
VTR_LOG("Reading XML bitstream setting '%s'...\n",
arch_file_name.c_str());
openfpga_context.mutable_bitstream_setting() = read_xml_openfpga_bitstream_settings(arch_file_name.c_str());
/* TODO: should identify the error code from internal function execution */
return CMD_EXEC_SUCCESS;
}
/********************************************************************
* A function to write an OpenFPGA bitstream setting file
* we use the APIs from the libarchopenfpga library
*
* The command will accept an option '--file' which is the simulation setting
* file provided by users
*******************************************************************/
int write_bitstream_setting(const OpenfpgaContext& openfpga_context,
const Command& cmd, const CommandContext& cmd_context) {
/* Check the option '--file' is enabled or not
* Actually, it must be enabled as the shell interface will check
* before reaching this fuction
*/
CommandOptionId opt_file = cmd.option("file");
VTR_ASSERT(true == cmd_context.option_enable(cmd, opt_file));
VTR_ASSERT(false == cmd_context.option_value(cmd, opt_file).empty());
std::string arch_file_name = cmd_context.option_value(cmd, opt_file);
VTR_LOG("Writing XML bitstream setting to '%s'...\n",
arch_file_name.c_str());
write_xml_openfpga_bitstream_settings(arch_file_name.c_str(), openfpga_context.bitstream_setting());
/* TODO: should identify the error code from internal function execution */
return CMD_EXEC_SUCCESS;
}
} /* end namespace openfpga */

View File

@ -27,6 +27,13 @@ int read_simulation_setting(OpenfpgaContext& openfpga_context,
int write_simulation_setting(const OpenfpgaContext& openfpga_context,
const Command& cmd, const CommandContext& cmd_context);
int read_bitstream_setting(OpenfpgaContext& openfpga_context,
const Command& cmd, const CommandContext& cmd_context);
int write_bitstream_setting(const OpenfpgaContext& openfpga_context,
const Command& cmd, const CommandContext& cmd_context);
} /* end namespace openfpga */
#endif

View File

@ -45,6 +45,7 @@ int repack(OpenfpgaContext& openfpga_ctx,
g_vpr_ctx.clustering(),
openfpga_ctx.mutable_vpr_device_annotation(),
openfpga_ctx.mutable_vpr_clustering_annotation(),
openfpga_ctx.vpr_bitstream_annotation(),
repack_design_constraints,
cmd_context.option_enable(cmd, opt_verbose));

View File

@ -113,6 +113,55 @@ ShellCommandId add_openfpga_write_simulation_setting_command(openfpga::Shell<Ope
return shell_cmd_id;
}
/********************************************************************
* - Add a command to Shell environment: read_openfpga_bitstream_setting
* - Add associated options
* - Add command dependency
*******************************************************************/
static
ShellCommandId add_openfpga_read_bitstream_setting_command(openfpga::Shell<OpenfpgaContext>& shell,
const ShellCommandClassId& cmd_class_id) {
Command shell_cmd("read_openfpga_bitstream_setting");
/* Add an option '--file' in short '-f'*/
CommandOptionId opt_file = shell_cmd.add_option("file", true, "file path to the bitstream setting XML");
shell_cmd.set_option_short_name(opt_file, "f");
shell_cmd.set_option_require_value(opt_file, openfpga::OPT_STRING);
/* Add command 'read_openfpga_bitstream_setting' to the Shell */
ShellCommandId shell_cmd_id = shell.add_command(shell_cmd, "read OpenFPGA bitstream setting file");
shell.set_command_class(shell_cmd_id, cmd_class_id);
shell.set_command_execute_function(shell_cmd_id, read_bitstream_setting);
return shell_cmd_id;
}
/********************************************************************
* - Add a command to Shell environment: write_openfpga_bitstream_setting
* - Add associated options
* - Add command dependency
*******************************************************************/
static
ShellCommandId add_openfpga_write_bitstream_setting_command(openfpga::Shell<OpenfpgaContext>& shell,
const ShellCommandClassId& cmd_class_id,
const std::vector<ShellCommandId>& dependent_cmds) {
Command shell_cmd("write_openfpga_bitstream_setting");
/* Add an option '--file' in short '-f'*/
CommandOptionId opt_file = shell_cmd.add_option("file", true, "file path to the bitstream setting XML");
shell_cmd.set_option_short_name(opt_file, "f");
shell_cmd.set_option_require_value(opt_file, openfpga::OPT_STRING);
/* Add command 'write_openfpga_bitstream_setting' to the Shell */
ShellCommandId shell_cmd_id = shell.add_command(shell_cmd, "write OpenFPGA bitstream setting file");
shell.set_command_class(shell_cmd_id, cmd_class_id);
shell.set_command_const_execute_function(shell_cmd_id, write_bitstream_setting);
/* Add command dependency to the Shell */
shell.set_command_dependency(shell_cmd_id, dependent_cmds);
return shell_cmd_id;
}
/********************************************************************
* - Add a command to Shell environment: link_openfpga_arch
* - Add associated options
@ -373,6 +422,22 @@ void add_openfpga_setup_commands(openfpga::Shell<OpenfpgaContext>& shell) {
openfpga_setup_cmd_class,
write_sim_setting_dependent_cmds);
/********************************
* Command 'read_openfpga_bitstream_setting'
*/
ShellCommandId read_bitstream_setting_cmd_id = add_openfpga_read_bitstream_setting_command(shell,
openfpga_setup_cmd_class);
/********************************
* Command 'write_openfpga_bitstream_setting'
*/
/* The 'write_openfpga_bitstream_setting' command should NOT be executed before 'read_openfpga_bitstream_setting' */
std::vector<ShellCommandId> write_bitstream_setting_dependent_cmds(1, read_bitstream_setting_cmd_id);
add_openfpga_write_bitstream_setting_command(shell,
openfpga_setup_cmd_class,
write_bitstream_setting_dependent_cmds);
/********************************
* Command 'link_openfpga_arch'
*/

View File

@ -445,6 +445,23 @@ void build_lut_bitstream(BitstreamManager& bitstream_manager,
device_annotation,
physical_pb.truth_tables(lut_pb_id),
circuit_lib.port_default_value(lut_regular_sram_ports[0]));
/* If the physical pb contains fixed bitstream, overload here */
if (false == physical_pb.fixed_bitstream(lut_pb_id).empty()) {
std::string fixed_bitstream = physical_pb.fixed_bitstream(lut_pb_id);
/* Ensure the length matches!!! */
if (lut_bitstream.size() != fixed_bitstream.size()) {
VTR_LOG_ERROR("Unmatched length of fixed bitstream %s!Expected to be %ld bits\n",
fixed_bitstream.c_str(),
lut_bitstream.size());
exit(1);
}
/* Overload here */
lut_bitstream.clear();
for (const char& fixed_bit : fixed_bitstream) {
VTR_ASSERT('0' == fixed_bit || '1' == fixed_bit);
lut_bitstream.push_back('1' == fixed_bit);
}
}
}
/* Generate bitstream for mode-select ports */

View File

@ -7,6 +7,7 @@
#include "vpr_context.h"
#include "vpr_device_annotation.h"
#include "vpr_clustering_annotation.h"
#include "vpr_bitstream_annotation.h"
#include "circuit_library.h"
/********************************************************************

View File

@ -102,6 +102,11 @@ std::vector<size_t> PhysicalPb::mode_bits(const PhysicalPbId& pb) const {
return mode_bits_[pb];
}
std::string PhysicalPb::fixed_bitstream(const PhysicalPbId& pb) const {
VTR_ASSERT(true == valid_pb_id(pb));
return fixed_bitstreams_[pb];
}
/******************************************************************************
* Private Mutators
******************************************************************************/
@ -128,6 +133,7 @@ PhysicalPbId PhysicalPb::create_pb(const t_pb_graph_node* pb_graph_node) {
truth_tables_.emplace_back();
mode_bits_.emplace_back();
fixed_bitstreams_.emplace_back();
/* Register in the name2id map */
type2id_map_[pb_graph_node] = pb;
@ -206,6 +212,12 @@ void PhysicalPb::set_wire_lut_output(const PhysicalPbId& pb,
wire_lut_outputs_[pb][pb_graph_pin] = wire_lut_output;
}
void PhysicalPb::set_fixed_bitstream(const PhysicalPbId& pb,
const std::string& fixed_bitstream) {
VTR_ASSERT(true == valid_pb_id(pb));
fixed_bitstreams_[pb] = fixed_bitstream;
}
/******************************************************************************
* Private validators/invalidators
******************************************************************************/

View File

@ -54,6 +54,7 @@ class PhysicalPb {
const t_pb_graph_pin* pb_graph_pin) const;
std::map<const t_pb_graph_pin*, AtomNetlist::TruthTable> truth_tables(const PhysicalPbId& pb) const;
std::vector<size_t> mode_bits(const PhysicalPbId& pb) const;
std::string fixed_bitstream(const PhysicalPbId& pb) const;
public: /* Public mutators */
PhysicalPbId create_pb(const t_pb_graph_node* pb_graph_node);
void add_child(const PhysicalPbId& parent,
@ -72,6 +73,8 @@ class PhysicalPb {
void set_wire_lut_output(const PhysicalPbId& pb,
const t_pb_graph_pin* pb_graph_pin,
const bool& wire_lut_output);
void set_fixed_bitstream(const PhysicalPbId& pb,
const std::string& fixed_bitstream);
public: /* Public validators/invalidators */
bool valid_pb_id(const PhysicalPbId& pb_id) const;
bool empty() const;
@ -94,6 +97,8 @@ class PhysicalPb {
vtr::vector<PhysicalPbId, std::vector<size_t>> mode_bits_;
vtr::vector<PhysicalPbId, std::string> fixed_bitstreams_;
/* Fast lookup */
std::map<const t_pb_graph_node*, PhysicalPbId> type2id_map_;
};

View File

@ -611,6 +611,7 @@ void repack_cluster(const AtomContext& atom_ctx,
const ClusteringContext& clustering_ctx,
const VprDeviceAnnotation& device_annotation,
VprClusteringAnnotation& clustering_annotation,
const VprBitstreamAnnotation& bitstream_annotation,
const RepackDesignConstraints& design_constraints,
const ClusterBlockId& block_id,
const bool& verbose) {
@ -659,6 +660,7 @@ void repack_cluster(const AtomContext& atom_ctx,
clustering_ctx.clb_nlist.block_pb(block_id)->pb_route,
atom_ctx,
device_annotation,
bitstream_annotation,
verbose);
/* Save routing results */
save_lb_router_results_to_physical_pb(phy_pb, lb_router, lb_rr_graph);
@ -678,6 +680,7 @@ void repack_clusters(const AtomContext& atom_ctx,
const ClusteringContext& clustering_ctx,
const VprDeviceAnnotation& device_annotation,
VprClusteringAnnotation& clustering_annotation,
const VprBitstreamAnnotation& bitstream_annotation,
const RepackDesignConstraints& design_constraints,
const bool& verbose) {
vtr::ScopedStartFinishTimer timer("Repack clustered blocks to physical implementation of logical tile");
@ -686,6 +689,7 @@ void repack_clusters(const AtomContext& atom_ctx,
repack_cluster(atom_ctx, clustering_ctx,
device_annotation,
clustering_annotation,
bitstream_annotation,
design_constraints,
blk_id, verbose);
}
@ -706,6 +710,7 @@ void pack_physical_pbs(const DeviceContext& device_ctx,
const ClusteringContext& clustering_ctx,
VprDeviceAnnotation& device_annotation,
VprClusteringAnnotation& clustering_annotation,
const VprBitstreamAnnotation& bitstream_annotation,
const RepackDesignConstraints& design_constraints,
const bool& verbose) {
@ -716,7 +721,9 @@ void pack_physical_pbs(const DeviceContext& device_ctx,
/* Call the LbRouter to re-pack each clustered block to physical implementation */
repack_clusters(atom_ctx, clustering_ctx,
const_cast<const VprDeviceAnnotation&>(device_annotation), clustering_annotation,
const_cast<const VprDeviceAnnotation&>(device_annotation),
clustering_annotation,
bitstream_annotation,
design_constraints,
verbose);
}

View File

@ -8,6 +8,7 @@
#include "vpr_device_annotation.h"
#include "vpr_clustering_annotation.h"
#include "vpr_routing_annotation.h"
#include "vpr_bitstream_annotation.h"
#include "repack_design_constraints.h"
/********************************************************************
@ -22,6 +23,7 @@ void pack_physical_pbs(const DeviceContext& device_ctx,
const ClusteringContext& clustering_ctx,
VprDeviceAnnotation& device_annotation,
VprClusteringAnnotation& clustering_annotation,
const VprBitstreamAnnotation& bitstream_annotation,
const RepackDesignConstraints& design_constraints,
const bool& verbose);

View File

@ -6,6 +6,9 @@
#include "vtr_assert.h"
#include "vtr_log.h"
/* Headers from openfpgautil library */
#include "openfpga_tokenizer.h"
#include "openfpga_naming.h"
#include "pb_type_utils.h"
#include "physical_pb_utils.h"
@ -278,6 +281,7 @@ void rec_update_physical_pb_from_operating_pb(PhysicalPb& phy_pb,
const t_pb_routes& pb_route,
const AtomContext& atom_ctx,
const VprDeviceAnnotation& device_annotation,
const VprBitstreamAnnotation& bitstream_annotation,
const bool& verbose) {
t_pb_graph_node* pb_graph_node = op_pb->pb_graph_node;
t_pb_type* pb_type = pb_graph_node->pb_type;
@ -297,6 +301,29 @@ void rec_update_physical_pb_from_operating_pb(PhysicalPb& phy_pb,
VTR_ASSERT(atom_blk);
phy_pb.add_atom_block(physical_pb, atom_blk);
/* if the operating pb type has bitstream annotation,
* bind the bitstream value from atom block to the physical pb
*/
if (VprBitstreamAnnotation::e_bitstream_source_type::BITSTREAM_SOURCE_EBLIF == bitstream_annotation.pb_type_bitstream_source(pb_type)) {
StringToken tokenizer = bitstream_annotation.pb_type_bitstream_content(pb_type);
std::vector<std::string> tokens = tokenizer.split(" ");
/* FIXME: The token-level check should be done much earlier!!! */
VTR_ASSERT(2 == tokens.size());
if (std::string(".param") == tokens[0]) {
for (const auto& param_search : atom_ctx.nlist.block_params(atom_blk)) {
if (param_search.first == tokens[1]) {
phy_pb.set_fixed_bitstream(physical_pb, param_search.second);
}
}
} else if (std::string(".attr") == tokens[0]) {
for (const auto& attr_search : atom_ctx.nlist.block_attrs(atom_blk)) {
if (attr_search.first == tokens[1]) {
phy_pb.set_fixed_bitstream(physical_pb, attr_search.second);
}
}
}
}
/* Iterate over ports and annotate the atom pins */
synchronize_primitive_physical_pb_atom_nets(phy_pb, physical_pb,
@ -318,6 +345,7 @@ void rec_update_physical_pb_from_operating_pb(PhysicalPb& phy_pb,
pb_route,
atom_ctx,
device_annotation,
bitstream_annotation,
verbose);
} else {
/* Some pb may be used just in routing purpose, find out the output nets */

View File

@ -10,6 +10,7 @@
#include <vector>
#include "physical_types.h"
#include "vpr_device_annotation.h"
#include "vpr_bitstream_annotation.h"
#include "vpr_context.h"
#include "physical_pb.h"
@ -29,6 +30,7 @@ void rec_update_physical_pb_from_operating_pb(PhysicalPb& phy_pb,
const t_pb_routes& pb_route,
const AtomContext& atom_ctx,
const VprDeviceAnnotation& device_annotation,
const VprBitstreamAnnotation& bitstream_annotation,
const bool& verbose);
} /* end namespace openfpga */

View File

@ -0,0 +1,2 @@
# This is just a placehold activity file which is empty
# This is due to that ACE2 does not support eblif file format

View File

@ -0,0 +1,39 @@
# Generated by Yosys 0.9+2406 (git sha1 1fafc16a, clang 12.0.0 -fPIC -Os)
.model adder_8
.inputs a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] b[0] b[1] b[2] b[3] b[4] b[5] b[6] b[7] cin
.outputs cout sum[0] sum[1] sum[2] sum[3] sum[4] sum[5] sum[6] sum[7]
.names $false
.names $true
1
.names $undef
.subckt adder_lut4 in[3]=$false in[2]=$false in[1]=cin in[0]=$false lut2_out[1]=cin_frac_lut4_in_lut2_out[1] lut2_out[0]=cin_frac_lut4_in_lut2_out[0]
.param LUT 1100000000000011
.subckt carry_follower a=cin_frac_lut4_in_lut2_out[1] cin=cin_frac_lut4_in_lut2_out[0] cout=sum_frac_lut4_lut4_out_7_in
.subckt adder_lut4 in[3]=$false in[2]=sum_frac_lut4_lut4_out_lut2_out_carry_follower_a_cout[7] in[1]=$false in[0]=$false lut2_out[1]=cout_frac_lut4_lut4_out_lut2_out[1] lut2_out[0]=cout_frac_lut4_lut4_out_lut2_out[0] lut4_out=cout
.param LUT 0110100101100001
.subckt adder_lut4 in[3]=$false in[2]=sum_frac_lut4_lut4_out_lut2_out_carry_follower_a_cout[6] in[1]=a[7] in[0]=b[7] lut2_out[1]=sum_frac_lut4_lut4_out_lut2_out[1] lut2_out[0]=sum_frac_lut4_lut4_out_lut2_out[0] lut4_out=sum[7]
.param LUT 0110100101100001
.subckt adder_lut4 in[3]=$false in[2]=sum_frac_lut4_lut4_out_lut2_out_carry_follower_a_cout[5] in[1]=a[6] in[0]=b[6] lut2_out[1]=sum_frac_lut4_lut4_out_1_lut2_out[1] lut2_out[0]=sum_frac_lut4_lut4_out_1_lut2_out[0] lut4_out=sum[6]
.param LUT 0110100101100001
.subckt carry_follower a=sum_frac_lut4_lut4_out_1_lut2_out[1] b=sum_frac_lut4_lut4_out_lut2_out_carry_follower_a_cout[5] cin=sum_frac_lut4_lut4_out_1_lut2_out[0] cout=sum_frac_lut4_lut4_out_lut2_out_carry_follower_a_cout[6]
.subckt adder_lut4 in[3]=$false in[2]=sum_frac_lut4_lut4_out_lut2_out_carry_follower_a_cout[4] in[1]=a[5] in[0]=b[5] lut2_out[1]=sum_frac_lut4_lut4_out_2_lut2_out[1] lut2_out[0]=sum_frac_lut4_lut4_out_2_lut2_out[0] lut4_out=sum[5]
.param LUT 0110100101100001
.subckt carry_follower a=sum_frac_lut4_lut4_out_2_lut2_out[1] b=sum_frac_lut4_lut4_out_lut2_out_carry_follower_a_cout[4] cin=sum_frac_lut4_lut4_out_2_lut2_out[0] cout=sum_frac_lut4_lut4_out_lut2_out_carry_follower_a_cout[5]
.subckt adder_lut4 in[3]=$false in[2]=sum_frac_lut4_lut4_out_lut2_out_carry_follower_a_cout[3] in[1]=a[4] in[0]=b[4] lut2_out[1]=sum_frac_lut4_lut4_out_3_lut2_out[1] lut2_out[0]=sum_frac_lut4_lut4_out_3_lut2_out[0] lut4_out=sum[4]
.param LUT 0110100101100001
.subckt carry_follower a=sum_frac_lut4_lut4_out_3_lut2_out[1] b=sum_frac_lut4_lut4_out_lut2_out_carry_follower_a_cout[3] cin=sum_frac_lut4_lut4_out_3_lut2_out[0] cout=sum_frac_lut4_lut4_out_lut2_out_carry_follower_a_cout[4]
.subckt adder_lut4 in[3]=$false in[2]=sum_frac_lut4_lut4_out_lut2_out_carry_follower_a_cout[2] in[1]=a[3] in[0]=b[3] lut2_out[1]=sum_frac_lut4_lut4_out_4_lut2_out[1] lut2_out[0]=sum_frac_lut4_lut4_out_4_lut2_out[0] lut4_out=sum[3]
.param LUT 0110100101100001
.subckt carry_follower a=sum_frac_lut4_lut4_out_4_lut2_out[1] b=sum_frac_lut4_lut4_out_lut2_out_carry_follower_a_cout[2] cin=sum_frac_lut4_lut4_out_4_lut2_out[0] cout=sum_frac_lut4_lut4_out_lut2_out_carry_follower_a_cout[3]
.subckt adder_lut4 in[3]=$false in[2]=sum_frac_lut4_lut4_out_lut2_out_carry_follower_a_cout[1] in[1]=a[2] in[0]=b[2] lut2_out[1]=sum_frac_lut4_lut4_out_5_lut2_out[1] lut2_out[0]=sum_frac_lut4_lut4_out_5_lut2_out[0] lut4_out=sum[2]
.param LUT 0110100101100001
.subckt carry_follower a=sum_frac_lut4_lut4_out_5_lut2_out[1] b=sum_frac_lut4_lut4_out_lut2_out_carry_follower_a_cout[1] cin=sum_frac_lut4_lut4_out_5_lut2_out[0] cout=sum_frac_lut4_lut4_out_lut2_out_carry_follower_a_cout[2]
.subckt adder_lut4 in[3]=$false in[2]=sum_frac_lut4_lut4_out_lut2_out_carry_follower_a_cout[0] in[1]=a[1] in[0]=b[1] lut2_out[1]=sum_frac_lut4_lut4_out_6_lut2_out[1] lut2_out[0]=sum_frac_lut4_lut4_out_6_lut2_out[0] lut4_out=sum[1]
.param LUT 0110100101100001
.subckt carry_follower a=sum_frac_lut4_lut4_out_6_lut2_out[1] b=sum_frac_lut4_lut4_out_lut2_out_carry_follower_a_cout[0] cin=sum_frac_lut4_lut4_out_6_lut2_out[0] cout=sum_frac_lut4_lut4_out_lut2_out_carry_follower_a_cout[1]
.subckt adder_lut4 in[3]=$false in[2]=sum_frac_lut4_lut4_out_7_in in[1]=a[0] in[0]=b[0] lut2_out[1]=sum_frac_lut4_lut4_out_7_lut2_out[1] lut2_out[0]=sum_frac_lut4_lut4_out_7_lut2_out[0] lut4_out=sum[0]
.param LUT 0110100101100001
.subckt carry_follower a=sum_frac_lut4_lut4_out_7_lut2_out[1] b=sum_frac_lut4_lut4_out_7_in cin=sum_frac_lut4_lut4_out_7_lut2_out[0] cout=sum_frac_lut4_lut4_out_lut2_out_carry_follower_a_cout[0]
.subckt carry_follower a=sum_frac_lut4_lut4_out_lut2_out[1] b=sum_frac_lut4_lut4_out_lut2_out_carry_follower_a_cout[6] cin=sum_frac_lut4_lut4_out_lut2_out[0] cout=sum_frac_lut4_lut4_out_lut2_out_carry_follower_a_cout[7]
.end

View File

@ -0,0 +1,21 @@
// Creating a scaleable adder
module adder_8(cout, sum, a, b, cin);
parameter size = 8; /* declare a parameter. default required */
output cout;
output [size-1:0] sum; // sum uses the size parameter
input cin;
input [size-1:0] a, b; // 'a' and 'b' use the size parameter
assign {cout, sum} = a + b + cin;
endmodule

View File

@ -0,0 +1,144 @@
/* Generated by Yosys 0.9+2406 (git sha1 e6ff764e, clang 12.0.0 -fPIC -Os) */
module adder_8(cout, sum, a, b, cin);
input [7:0] a;
input [7:0] b;
input cin;
output cout;
wire [0:1] cout_frac_lut4_lut4_out_lut2_out;
output [7:0] sum;
wire [0:1] sum_frac_lut4_lut4_out_1_lut2_out;
wire [0:1] sum_frac_lut4_lut4_out_2_lut2_out;
wire [0:1] sum_frac_lut4_lut4_out_3_lut2_out;
wire [0:1] sum_frac_lut4_lut4_out_4_lut2_out;
wire [0:1] sum_frac_lut4_lut4_out_5_lut2_out;
wire [0:1] sum_frac_lut4_lut4_out_6_lut2_out;
wire sum_frac_lut4_lut4_out_7_in;
wire [0:1] sum_frac_lut4_lut4_out_7_lut2_out;
wire [0:1] sum_frac_lut4_lut4_out_lut2_out;
wire [8:0] sum_frac_lut4_lut4_out_lut2_out_carry_follower_a_cout;
frac_lut4 #(
.LUT(16'b0110100101100001)
) cout_frac_lut4_lut4_out (
.in({ 2'b00, sum_frac_lut4_lut4_out_lut2_out_carry_follower_a_cout[7], 1'b0 }),
.lut2_out(cout_frac_lut4_lut4_out_lut2_out),
.lut4_out(cout)
);
frac_lut4 #(
.LUT(16'b0110100101100001)
) sum_frac_lut4_lut4_out (
.in({ b[7], a[7], sum_frac_lut4_lut4_out_lut2_out_carry_follower_a_cout[6], 1'b0 }),
.lut2_out(sum_frac_lut4_lut4_out_lut2_out),
.lut4_out(sum[7])
);
frac_lut4 #(
.LUT(16'b0110100101100001)
) sum_frac_lut4_lut4_out_1 (
.in({ b[6], a[6], sum_frac_lut4_lut4_out_lut2_out_carry_follower_a_cout[5], 1'b0 }),
.lut2_out(sum_frac_lut4_lut4_out_1_lut2_out),
.lut4_out(sum[6])
);
carry_follower sum_frac_lut4_lut4_out_1_lut2_out_carry_follower_a (
.a(sum_frac_lut4_lut4_out_1_lut2_out[1]),
.b(sum_frac_lut4_lut4_out_lut2_out_carry_follower_a_cout[5]),
.cin(sum_frac_lut4_lut4_out_1_lut2_out[0]),
.cout(sum_frac_lut4_lut4_out_lut2_out_carry_follower_a_cout[6])
);
frac_lut4 #(
.LUT(16'b0110100101100001)
) sum_frac_lut4_lut4_out_2 (
.in({ b[5], a[5], sum_frac_lut4_lut4_out_lut2_out_carry_follower_a_cout[4], 1'b0 }),
.lut2_out(sum_frac_lut4_lut4_out_2_lut2_out),
.lut4_out(sum[5])
);
carry_follower sum_frac_lut4_lut4_out_2_lut2_out_carry_follower_a (
.a(sum_frac_lut4_lut4_out_2_lut2_out[1]),
.b(sum_frac_lut4_lut4_out_lut2_out_carry_follower_a_cout[4]),
.cin(sum_frac_lut4_lut4_out_2_lut2_out[0]),
.cout(sum_frac_lut4_lut4_out_lut2_out_carry_follower_a_cout[5])
);
frac_lut4 #(
.LUT(16'b0110100101100001)
) sum_frac_lut4_lut4_out_3 (
.in({ b[4], a[4], sum_frac_lut4_lut4_out_lut2_out_carry_follower_a_cout[3], 1'b0 }),
.lut2_out(sum_frac_lut4_lut4_out_3_lut2_out),
.lut4_out(sum[4])
);
carry_follower sum_frac_lut4_lut4_out_3_lut2_out_carry_follower_a (
.a(sum_frac_lut4_lut4_out_3_lut2_out[1]),
.b(sum_frac_lut4_lut4_out_lut2_out_carry_follower_a_cout[3]),
.cin(sum_frac_lut4_lut4_out_3_lut2_out[0]),
.cout(sum_frac_lut4_lut4_out_lut2_out_carry_follower_a_cout[4])
);
frac_lut4 #(
.LUT(16'b0110100101100001)
) sum_frac_lut4_lut4_out_4 (
.in({ b[3], a[3], sum_frac_lut4_lut4_out_lut2_out_carry_follower_a_cout[2], 1'b0 }),
.lut2_out(sum_frac_lut4_lut4_out_4_lut2_out),
.lut4_out(sum[3])
);
carry_follower sum_frac_lut4_lut4_out_4_lut2_out_carry_follower_a (
.a(sum_frac_lut4_lut4_out_4_lut2_out[1]),
.b(sum_frac_lut4_lut4_out_lut2_out_carry_follower_a_cout[2]),
.cin(sum_frac_lut4_lut4_out_4_lut2_out[0]),
.cout(sum_frac_lut4_lut4_out_lut2_out_carry_follower_a_cout[3])
);
frac_lut4 #(
.LUT(16'b0110100101100001)
) sum_frac_lut4_lut4_out_5 (
.in({ b[2], a[2], sum_frac_lut4_lut4_out_lut2_out_carry_follower_a_cout[1], 1'b0 }),
.lut2_out(sum_frac_lut4_lut4_out_5_lut2_out),
.lut4_out(sum[2])
);
carry_follower sum_frac_lut4_lut4_out_5_lut2_out_carry_follower_a (
.a(sum_frac_lut4_lut4_out_5_lut2_out[1]),
.b(sum_frac_lut4_lut4_out_lut2_out_carry_follower_a_cout[1]),
.cin(sum_frac_lut4_lut4_out_5_lut2_out[0]),
.cout(sum_frac_lut4_lut4_out_lut2_out_carry_follower_a_cout[2])
);
frac_lut4 #(
.LUT(16'b0110100101100001)
) sum_frac_lut4_lut4_out_6 (
.in({ b[1], a[1], sum_frac_lut4_lut4_out_lut2_out_carry_follower_a_cout[0], 1'b0 }),
.lut2_out(sum_frac_lut4_lut4_out_6_lut2_out),
.lut4_out(sum[1])
);
carry_follower sum_frac_lut4_lut4_out_6_lut2_out_carry_follower_a (
.a(sum_frac_lut4_lut4_out_6_lut2_out[1]),
.b(sum_frac_lut4_lut4_out_lut2_out_carry_follower_a_cout[0]),
.cin(sum_frac_lut4_lut4_out_6_lut2_out[0]),
.cout(sum_frac_lut4_lut4_out_lut2_out_carry_follower_a_cout[1])
);
frac_lut4 #(
.LUT(16'b0110100101100001)
) sum_frac_lut4_lut4_out_7 (
.in({ b[0], a[0], sum_frac_lut4_lut4_out_7_in, 1'b0 }),
.lut2_out(sum_frac_lut4_lut4_out_7_lut2_out),
.lut4_out(sum[0])
);
carry_follower sum_frac_lut4_lut4_out_7_in_carry_follower_cout (
.a(sum_frac_lut4_lut4_out_7_lut2_out[1]),
.b(),
.cin(sum_frac_lut4_lut4_out_7_lut2_out[0]),
.cout(sum_frac_lut4_lut4_out_7_in)
);
frac_lut4 #(
.LUT(16'b1100000000000011)
) sum_frac_lut4_lut4_out_7_lut2_out_frac_lut4_lut2_out (
.in({ 1'bx, cin, 2'bxx }),
.lut2_out(sum_frac_lut4_lut4_out_7_lut2_out),
.lut4_out()
);
carry_follower sum_frac_lut4_lut4_out_lut2_out_carry_follower_a (
.a(sum_frac_lut4_lut4_out_lut2_out[1]),
.b(sum_frac_lut4_lut4_out_lut2_out_carry_follower_a_cout[6]),
.cin(sum_frac_lut4_lut4_out_lut2_out[0]),
.cout(sum_frac_lut4_lut4_out_lut2_out_carry_follower_a_cout[7])
);
carry_follower sum_frac_lut4_lut4_out_lut2_out_carry_follower_a_cout_carry_follower_cout (
.a(sum_frac_lut4_lut4_out_7_lut2_out[1]),
.b(sum_frac_lut4_lut4_out_7_in),
.cin(sum_frac_lut4_lut4_out_7_lut2_out[0]),
.cout(sum_frac_lut4_lut4_out_lut2_out_carry_follower_a_cout[0])
);
endmodule

View File

@ -0,0 +1,19 @@
# This is an artificial microbenchmark
# which is designed to validate the support
# on using bitstream information from the .param
# attribute of hard macro of LUTs
#
.model and2
.inputs a b
.outputs c
.subckt adder_lut4 in[1]=a in[0]=b lut4_out[0]=c
.param LUT 1000100010001000
.end
.model adder_lut4
.inputs in[3] in[2] in[1] in[0]
.outputs lut2_out[1] lut2_out[0] lut4_out[0]
.blackbox
.end

View File

@ -0,0 +1,277 @@
<!-- Architecture annotation for OpenFPGA framework
This annotation supports the k4_frac_cc_sky130nm.xml
- General purpose logic block
- K = 6, N = 10, I = 40
- Single mode
- Routing architecture
- L = 4, fc_in = 0.15, fc_out = 0.1
- Skywater 130nm PDK
- circuit models are binded to the opensource skywater
foundry middle-speed (ms) standard cell library
-->
<openfpga_architecture>
<technology_library>
<device_library>
<device_model name="logic" type="transistor">
<lib type="industry" corner="TOP_TT" ref="M" path="${OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.pm"/>
<design vdd="0.9" pn_ratio="2"/>
<pmos name="pch" chan_length="40e-9" min_width="140e-9" variation="logic_transistor_var"/>
<nmos name="nch" chan_length="40e-9" min_width="140e-9" variation="logic_transistor_var"/>
</device_model>
<device_model name="io" type="transistor">
<lib type="academia" ref="M" path="${OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.pm"/>
<design vdd="2.5" pn_ratio="3"/>
<pmos name="pch_25" chan_length="270e-9" min_width="320e-9" variation="io_transistor_var"/>
<nmos name="nch_25" chan_length="270e-9" min_width="320e-9" variation="io_transistor_var"/>
</device_model>
</device_library>
<variation_library>
<variation name="logic_transistor_var" abs_deviation="0.1" num_sigma="3"/>
<variation name="io_transistor_var" abs_deviation="0.1" num_sigma="3"/>
</variation_library>
</technology_library>
<circuit_library>
<circuit_model type="inv_buf" name="sky130_fd_sc_hd__inv_1" prefix="sky130_fd_sc_hd__inv_1" is_default="true">
<design_technology type="cmos" topology="inverter" size="1"/>
<device_technology device_model_name="logic"/>
<port type="input" prefix="in" lib_name="A" size="1"/>
<port type="output" prefix="out" lib_name="Y" size="1"/>
<delay_matrix type="rise" in_port="in" out_port="out">
10e-12
</delay_matrix>
<delay_matrix type="fall" in_port="in" out_port="out">
10e-12
</delay_matrix>
</circuit_model>
<circuit_model type="inv_buf" name="sky130_fd_sc_hd__buf_2" prefix="sky130_fd_sc_hd__buf_2" is_default="false">
<design_technology type="cmos" topology="buffer" size="1" num_level="2" f_per_stage="2"/>
<device_technology device_model_name="logic"/>
<port type="input" prefix="in" lib_name="A" size="1"/>
<port type="output" prefix="out" lib_name="X" size="1"/>
<delay_matrix type="rise" in_port="in" out_port="out">
10e-12
</delay_matrix>
<delay_matrix type="fall" in_port="in" out_port="out">
10e-12
</delay_matrix>
</circuit_model>
<circuit_model type="inv_buf" name="sky130_fd_sc_hd__buf_4" prefix="sky130_fd_sc_hd__buf_4" is_default="false">
<design_technology type="cmos" topology="buffer" size="1" num_level="2" f_per_stage="4"/>
<device_technology device_model_name="logic"/>
<port type="input" prefix="in" lib_name="A" size="1"/>
<port type="output" prefix="out" lib_name="X" size="1"/>
<delay_matrix type="rise" in_port="in" out_port="out">
10e-12
</delay_matrix>
<delay_matrix type="fall" in_port="in" out_port="out">
10e-12
</delay_matrix>
</circuit_model>
<circuit_model type="inv_buf" name="sky130_fd_sc_hd__inv_2" prefix="sky130_fd_sc_hd__inv_2" is_default="false">
<design_technology type="cmos" topology="buffer" size="1"/>
<device_technology device_model_name="logic"/>
<port type="input" prefix="in" lib_name="A" size="1"/>
<port type="output" prefix="out" lib_name="Y" size="1"/>
<delay_matrix type="rise" in_port="in" out_port="out">
10e-12
</delay_matrix>
<delay_matrix type="fall" in_port="in" out_port="out">
10e-12
</delay_matrix>
</circuit_model>
<circuit_model type="gate" name="sky130_fd_sc_hd__or2_1" prefix="sky130_fd_sc_hd__or2_1" is_default="true">
<design_technology type="cmos" topology="OR"/>
<device_technology device_model_name="logic"/>
<input_buffer exist="false"/>
<output_buffer exist="false"/>
<port type="input" prefix="a" lib_name="A" size="1"/>
<port type="input" prefix="b" lib_name="B" size="1"/>
<port type="output" prefix="out" lib_name="X" size="1"/>
<delay_matrix type="rise" in_port="a b" out_port="out">
10e-12 5e-12
</delay_matrix>
<delay_matrix type="fall" in_port="a b" out_port="out">
10e-12 5e-12
</delay_matrix>
</circuit_model>
<!-- Define a circuit model for the standard cell MUX2
OpenFPGA requires the following truth table for the MUX2
When the select signal sel is enabled, the first input, i.e., in0
will be propagated to the output, i.e., out
If your standard cell provider does not offer the exact truth table,
you can simply swap the inputs as shown in the example below
-->
<circuit_model type="gate" name="sky130_fd_sc_hd__mux2_1" prefix="sky130_fd_sc_hd__mux2_1">
<design_technology type="cmos" topology="MUX2"/>
<device_technology device_model_name="logic"/>
<input_buffer exist="false"/>
<output_buffer exist="false"/>
<port type="input" prefix="in0" lib_name="A1" size="1"/>
<port type="input" prefix="in1" lib_name="A0" size="1"/>
<port type="input" prefix="sel" lib_name="S" size="1"/>
<port type="output" prefix="out" lib_name="X" size="1"/>
</circuit_model>
<circuit_model type="chan_wire" name="chan_segment" prefix="track_seg" is_default="true">
<design_technology type="cmos"/>
<input_buffer exist="false"/>
<output_buffer exist="false"/>
<port type="input" prefix="in" size="1"/>
<port type="output" prefix="out" size="1"/>
<wire_param model_type="pi" R="101" C="22.5e-15" num_level="1"/>
<!-- model_type could be T, res_val and cap_val DON'T CARE -->
</circuit_model>
<circuit_model type="wire" name="direct_interc" prefix="direct_interc" is_default="true">
<design_technology type="cmos"/>
<input_buffer exist="false"/>
<output_buffer exist="false"/>
<port type="input" prefix="in" size="1"/>
<port type="output" prefix="out" size="1"/>
<wire_param model_type="pi" R="0" C="0" num_level="1"/>
<!-- model_type could be T, res_val cap_val should be defined -->
</circuit_model>
<circuit_model type="mux" name="mux_tree" prefix="mux_tree" is_default="true" dump_structural_verilog="true">
<design_technology type="cmos" structure="tree" add_const_input="true" const_input_val="1"/>
<input_buffer exist="false"/>
<output_buffer exist="false"/>
<pass_gate_logic circuit_model_name="sky130_fd_sc_hd__mux2_1"/>
<port type="input" prefix="in" size="1"/>
<port type="output" prefix="out" size="1"/>
<port type="sram" prefix="sram" size="1"/>
</circuit_model>
<circuit_model type="mux" name="mux_tree_tapbuf" prefix="mux_tree_tapbuf" dump_structural_verilog="true">
<design_technology type="cmos" structure="tree" add_const_input="true" const_input_val="1"/>
<input_buffer exist="false"/>
<output_buffer exist="true" circuit_model_name="sky130_fd_sc_hd__buf_4"/>
<pass_gate_logic circuit_model_name="sky130_fd_sc_hd__mux2_1"/>
<port type="input" prefix="in" size="1"/>
<port type="output" prefix="out" size="1"/>
<port type="sram" prefix="sram" size="1"/>
</circuit_model>
<!--DFF subckt ports should be defined as <D> <Q> <CLK> <RESET> <SET> -->
<circuit_model type="ff" name="SDFFRQ" prefix="SDFFRQ" verilog_netlist="${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/verilog/dff.v">
<design_technology type="cmos"/>
<input_buffer exist="true" circuit_model_name="sky130_fd_sc_hd__inv_1"/>
<output_buffer exist="true" circuit_model_name="sky130_fd_sc_hd__inv_1"/>
<port type="input" prefix="D" size="1"/>
<port type="input" prefix="DI" lib_name="SI" size="1"/>
<port type="input" prefix="Test_en" lib_name="SE" size="1" is_global="true" default_val="0"/>
<port type="input" prefix="reset" lib_name="RST" size="1" default_val="0"/>
<port type="output" prefix="Q" size="1"/>
<port type="clock" prefix="clk" lib_name="CK" size="1" default_val="0" />
</circuit_model>
<circuit_model type="lut" name="frac_lut4" prefix="frac_lut4" dump_structural_verilog="true">
<design_technology type="cmos" fracturable_lut="true"/>
<input_buffer exist="false"/>
<output_buffer exist="true" circuit_model_name="sky130_fd_sc_hd__buf_2"/>
<lut_input_inverter exist="true" circuit_model_name="sky130_fd_sc_hd__inv_1"/>
<lut_input_buffer exist="true" circuit_model_name="sky130_fd_sc_hd__buf_2"/>
<lut_intermediate_buffer exist="true" circuit_model_name="sky130_fd_sc_hd__buf_2" location_map="-1-"/>
<pass_gate_logic circuit_model_name="sky130_fd_sc_hd__mux2_1"/>
<port type="input" prefix="in" size="4" tri_state_map="---1" circuit_model_name="sky130_fd_sc_hd__or2_1"/>
<port type="output" prefix="lut2_out" size="2" lut_frac_level="2" lut_output_mask="2,3"/>
<port type="output" prefix="lut3_out" size="2" lut_frac_level="3" lut_output_mask="0,1"/>
<port type="output" prefix="lut4_out" size="1" lut_output_mask="0"/>
<port type="sram" prefix="sram" size="16"/>
<port type="sram" prefix="mode" size="1" mode_select="true" circuit_model_name="DFFRQ" default_val="1"/>
</circuit_model>
<!--Scan-chain DFF subckt ports should be defined as <D> <Q> <Qb> <CLK> <RESET> <SET> -->
<circuit_model type="ccff" name="DFFRQ" prefix="DFFRQ" verilog_netlist="${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/verilog/dff.v">
<design_technology type="cmos"/>
<input_buffer exist="true" circuit_model_name="sky130_fd_sc_hd__inv_1"/>
<output_buffer exist="true" circuit_model_name="sky130_fd_sc_hd__inv_1"/>
<port type="input" prefix="D" size="1"/>
<port type="output" prefix="Q" size="1"/>
<port type="clock" prefix="prog_clk" lib_name="CK" size="1" is_global="true" default_val="0" is_prog="true"/>
<port type="input" prefix="pReset" lib_name="RST" size="1" is_global="true" default_val="0" is_prog="true" is_reset="true"/>
</circuit_model>
<circuit_model type="iopad" name="EMBEDDED_IO_ISOLN" prefix="EMBEDDED_IO_ISOLN" is_default="true" verilog_netlist="${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/verilog/gpio.v">
<design_technology type="cmos"/>
<input_buffer exist="true" circuit_model_name="sky130_fd_sc_hd__inv_1"/>
<output_buffer exist="true" circuit_model_name="sky130_fd_sc_hd__inv_1"/>
<port type="input" prefix="SOC_IN" lib_name="SOC_IN" size="1" is_global="true" is_io="true" is_data_io="true"/>
<port type="output" prefix="SOC_OUT" lib_name="SOC_OUT" size="1" is_global="true" is_io="true" is_data_io="true"/>
<port type="output" prefix="SOC_DIR" lib_name="SOC_DIR" size="1" is_global="true" is_io="true"/>
<port type="input" prefix="IO_ISOL_N" lib_name="IO_ISOL_N" size="1" is_global="true" default_val="1"/>
<port type="output" prefix="inpad" lib_name="FPGA_IN" size="1"/>
<port type="input" prefix="outpad" lib_name="FPGA_OUT" size="1"/>
<port type="sram" prefix="en" lib_name="FPGA_DIR" size="1" mode_select="true" circuit_model_name="DFFRQ" default_val="1"/>
</circuit_model>
<circuit_model type="hard_logic" name="CARRY_MUX2" prefix="CARRY_MUX2" verilog_netlist="${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/verilog/mux2.v">
<design_technology type="cmos"/>
<device_technology device_model_name="logic"/>
<input_buffer exist="false"/>
<output_buffer exist="false"/>
<port type="input" prefix="a" lib_name="A0" size="1"/>
<port type="input" prefix="b" lib_name="A1" size="1"/>
<port type="input" prefix="cin" lib_name="S" size="1"/>
<port type="output" prefix="cout" lib_name="Y" size="1"/>
</circuit_model>
</circuit_library>
<configuration_protocol>
<organization type="scan_chain" circuit_model_name="DFFRQ" num_regions="1"/>
</configuration_protocol>
<connection_block>
<switch name="ipin_cblock" circuit_model_name="mux_tree_tapbuf"/>
</connection_block>
<switch_block>
<switch name="L1_mux" circuit_model_name="mux_tree_tapbuf"/>
<switch name="L2_mux" circuit_model_name="mux_tree_tapbuf"/>
<switch name="L4_mux" circuit_model_name="mux_tree_tapbuf"/>
</switch_block>
<routing_segment>
<segment name="L1" circuit_model_name="chan_segment"/>
<segment name="L2" circuit_model_name="chan_segment"/>
<segment name="L4" circuit_model_name="chan_segment"/>
</routing_segment>
<direct_connection>
<direct name="carry_chain" circuit_model_name="direct_interc"/>
<direct name="shift_register" circuit_model_name="direct_interc"/>
<direct name="scan_chain" circuit_model_name="direct_interc" type="column" x_dir="positive" y_dir="positive"/>
</direct_connection>
<tile_annotations>
<global_port name="clk" is_clock="true" default_val="0">
<tile name="clb" port="clk" x="-1" y="-1"/>
</global_port>
<global_port name="Reset" is_reset="true" default_val="1">
<tile name="clb" port="reset" x="-1" y="-1"/>
</global_port>
</tile_annotations>
<pb_type_annotations>
<!-- physical pb_type binding in complex block IO -->
<pb_type name="io" physical_mode_name="physical" idle_mode_name="inpad"/>
<!-- IMPORTANT: must set unused I/Os to operating in INPUT mode !!! -->
<pb_type name="io[physical].iopad" circuit_model_name="EMBEDDED_IO_ISOLN" mode_bits="1"/>
<pb_type name="io[inpad].inpad" physical_pb_type_name="io[physical].iopad" mode_bits="1"/>
<pb_type name="io[outpad].outpad" physical_pb_type_name="io[physical].iopad" mode_bits="0"/>
<!-- End physical pb_type binding in complex block IO -->
<!-- physical pb_type binding in complex block CLB -->
<!-- physical mode will be the default mode if not specified -->
<pb_type name="clb.fle" physical_mode_name="physical"/>
<pb_type name="clb.fle[physical].fabric.frac_logic.frac_lut4" circuit_model_name="frac_lut4" mode_bits="0"/>
<pb_type name="clb.fle[physical].fabric.frac_logic.carry_follower" circuit_model_name="CARRY_MUX2"/>
<pb_type name="clb.fle[physical].fabric.ff" circuit_model_name="SDFFRQ"/>
<!-- Binding operating pb_type to physical pb_type -->
<!-- Binding operating pb_types in mode 'arithmetic' -->
<pb_type name="clb.fle[arithmetic].soft_adder.adder_lut4" physical_pb_type_name="clb.fle[physical].fabric.frac_logic.frac_lut4" mode_bits="1"/>
<pb_type name="clb.fle[arithmetic].soft_adder.ff" physical_pb_type_name="clb.fle[physical].fabric.ff"/>
<pb_type name="clb.fle[arithmetic].soft_adder.carry_follower" physical_pb_type_name="clb.fle[physical].fabric.frac_logic.carry_follower"/>
<!-- Binding operating pb_types in mode 'n2_lut3' -->
<pb_type name="clb.fle[n2_lut3].lut3inter.ble3.lut3" physical_pb_type_name="clb.fle[physical].fabric.frac_logic.frac_lut4" mode_bits="1" physical_pb_type_index_factor="0.5">
<!-- Binding the lut3 to the first 3 inputs of fracturable lut4 -->
<port name="in" physical_mode_port="in[0:2]"/>
<port name="out" physical_mode_port="lut3_out[0:0]" physical_mode_pin_rotate_offset="1"/>
</pb_type>
<pb_type name="clb.fle[n2_lut3].lut3inter.ble3.ff" physical_pb_type_name="clb.fle[physical].fabric.ff"/>
<!-- Binding operating pb_types in mode 'ble4' -->
<pb_type name="clb.fle[n1_lut4].ble4.lut4" physical_pb_type_name="clb.fle[physical].fabric.frac_logic.frac_lut4" mode_bits="0">
<!-- Binding the lut4 to the first 4 inputs of fracturable lut4 -->
<port name="in" physical_mode_port="in[0:3]"/>
<port name="out" physical_mode_port="lut4_out"/>
</pb_type>
<pb_type name="clb.fle[n1_lut4].ble4.ff" physical_pb_type_name="clb.fle[physical].fabric.ff" physical_pb_type_index_factor="2" physical_pb_type_index_offset="0"/>
<!-- Binding operating pb_types in mode 'shift_register' -->
<pb_type name="clb.fle[shift_register].shift_reg.ff" physical_pb_type_name="clb.fle[physical].fabric.ff"/>
<!-- End physical pb_type binding in complex block IO -->
</pb_type_annotations>
</openfpga_architecture>

View File

@ -53,3 +53,26 @@ module MUX2(
`endif
endmodule
//-----------------------------------------------------
// Design Name : CARRY_MUX2
// File Name : mux2.v
// Function : Standard cell (static gate) implementation
// of 2-input multiplexers to be used by carry logic
// Coder : Xifan Tang
//-----------------------------------------------------
module CARRY_MUX2(
input [0:0] A0, // Data input 0
input [0:0] A1, // Data input 1
input [0:0] S, // Select port
output [0:0] Y // Data output
);
assign Y = S ? A1 : A0;
// Note:
// MUX2 appears in the datapath logic driven by carry-in and LUT outputs
// where initial values and signal deposit are not required
endmodule

View File

@ -0,0 +1,77 @@
# Run VPR for the 'and' design
#--write_rr_graph example_rr_graph.xml
vpr ${VPR_ARCH_FILE} ${VPR_TESTBENCH_BLIF} --clock_modeling route --circuit_format ${OPENFPGA_VPR_CIRCUIT_FORMAT}
# Read OpenFPGA architecture definition
read_openfpga_arch -f ${OPENFPGA_ARCH_FILE}
# Read OpenFPGA simulation settings
read_openfpga_simulation_setting -f ${OPENFPGA_SIM_SETTING_FILE}
# Read OpenFPGA bitstream settings
read_openfpga_bitstream_setting -f ${OPENFPGA_BITSTREAM_SETTING_FILE}
# Annotate the OpenFPGA architecture to VPR data base
# to debug use --verbose options
link_openfpga_arch --sort_gsb_chan_node_in_edges
# Check and correct any naming conflicts in the BLIF netlist
check_netlist_naming_conflict --fix --report ./netlist_renaming.xml
# Apply fix-up to clustering nets based on routing results
pb_pin_fixup --verbose
# Apply fix-up to Look-Up Table truth tables based on packing results
lut_truth_table_fixup
# Build the module graph
# - Enabled compression on routing architecture modules
# - Enable pin duplication on grid modules
build_fabric --compress_routing #--verbose
# Write the fabric hierarchy of module graph to a file
# This is used by hierarchical PnR flows
write_fabric_hierarchy --file ./fabric_hierarchy.txt
# Repack the netlist to physical pbs
# This must be done before bitstream generator and testbench generation
# Strongly recommend it is done after all the fix-up have been applied
repack #--verbose
# Build the bitstream
# - Output the fabric-independent bitstream to a file
build_architecture_bitstream --verbose --write_file fabric_independent_bitstream.xml
# Build fabric-dependent bitstream
build_fabric_bitstream --verbose
# Write fabric-dependent bitstream
write_fabric_bitstream --file fabric_bitstream.xml --format xml
# Write the Verilog netlist for FPGA fabric
# - Enable the use of explicit port mapping in Verilog netlist
write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --print_user_defined_template --verbose
# Write the Verilog testbench for FPGA fabric
# - We suggest the use of same output directory as fabric Verilog netlists
# - Must specify the reference benchmark file if you want to output any testbenches
# - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA
# - Enable pre-configured top-level testbench which is a fast verification skipping programming phase
# - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts
write_verilog_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --print_top_testbench --print_preconfig_top_testbench --print_simulation_ini ./SimulationDeck/simulation_deck.ini --include_signal_init --support_icarus_simulator --explicit_port_mapping
# Write the SDC files for PnR backend
# - Turn on every options here
write_pnr_sdc --file ./SDC
# Write SDC to disable timing for configure ports
write_sdc_disable_timing_configure_ports --file ./SDC/disable_configure_ports.sdc
# Write the SDC to run timing analysis for a mapped FPGA fabric
write_analysis_sdc --file ./SDC_analysis
# Finish and exit OpenFPGA
exit
# Note :
# To run verification at the end of the flow maintain source in ./SRC directory

View File

@ -0,0 +1,3 @@
<openfpga_bitstream_setting>
<pb_type name="clb.fle[arithmetic].soft_adder.adder_lut4" source="eblif" content=".param LUT"/>
</openfpga_bitstream_setting>

View File

@ -0,0 +1,48 @@
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
# 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 = false
spice_output=false
verilog_output=true
timeout_each_job = 1*60
fpga_flow=vpr_blif
[OpenFPGA_SHELL]
openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/bitstream_setting_example_script.openfpga
openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_frac_N8_reset_softadder_register_scan_chain_caravel_io_skywater130nm_fdhd_cc_openfpga.xml
openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/fixed_sim_openfpga.xml
openfpga_bitstream_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/tasks/fpga_verilog/adder/soft_adder/config/bitstream_annotation.xml
openfpga_vpr_circuit_format=eblif
external_fabric_key_file=
[ARCHITECTURES]
arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_frac_N8_tileable_reset_softadder_register_scan_chain_nonLR_caravel_io_skywater130nm.xml
[BENCHMARKS]
bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.eblif
#bench1=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/adder_8/adder_8.eblif
[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
bench0_chan_width = 300
##########################
# Due to the limitation in pack pattern, 8-bit adder benchmark cannot pass VPR
#bench1_top = adder_8
#bench1_act = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/adder_8/adder_8.act
#bench1_verilog = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/adder_8/adder_8.v
#bench1_chan_width = 300
[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH]
end_flow_with_test=
vpr_fpga_verilog_formal_verification_top_netlist=

View File

@ -33,7 +33,25 @@
<port name="inpad"/>
</output_ports>
</model>
<model name="adder_lut4">
<input_ports>
<port name="in" combinational_sink_ports="lut2_out lut4_out"/>
</input_ports>
<output_ports>
<port name="lut2_out"/>
<port name="lut4_out"/>
</output_ports>
</model>
<model name="carry_follower">
<input_ports>
<port name="a" combinational_sink_ports="cout"/>
<port name="b" combinational_sink_ports="cout"/>
<port name="cin" combinational_sink_ports="cout"/>
</input_ports>
<output_ports>
<port name="cout"/>
</output_ports>
</model>
<model name="frac_lut4">
<input_ports>
<port name="in"/>
@ -44,11 +62,11 @@
<port name="lut4_out"/>
</output_ports>
</model>
<model name="carry_follower">
<model name="carry_follower_physical">
<input_ports>
<port name="a"/>
<port name="b"/>
<port name="cin"/>
<port name="a" combinational_sink_ports="cout"/>
<port name="b" combinational_sink_ports="cout"/>
<port name="cin" combinational_sink_ports="cout"/>
</input_ports>
<output_ports>
<port name="cout"/>
@ -404,11 +422,14 @@
<output name="lut3_out" num_pins="2"/>
<output name="lut4_out" num_pins="1"/>
</pb_type>
<pb_type name="carry_follower" blif_model=".subckt carry_follower" num_pb="1">
<pb_type name="carry_follower" blif_model=".subckt carry_follower_physical" num_pb="1">
<input name="a" num_pins="1"/>
<input name="b" num_pins="1"/>
<input name="cin" num_pins="1"/>
<output name="cout" num_pins="1"/>
<delay_constant max="0.3e-9" in_port="carry_follower.a" out_port="carry_follower.cout"/>
<delay_constant max="0.3e-9" in_port="carry_follower.b" out_port="carry_follower.cout"/>
<delay_constant max="0.3e-9" in_port="carry_follower.cin" out_port="carry_follower.cout"/>
</pb_type>
<interconnect>
<direct name="direct1" input="frac_logic.in[0:1]" output="frac_lut4.in[0:1]"/>
@ -437,10 +458,12 @@
</pb_type>
<interconnect>
<direct name="direct1" input="fabric.in" output="frac_logic.in"/>
<direct name="direct2" input="fabric.sc_in" output="ff[0].DI"/>
<direct name="direct3" input="ff[0].Q" output="ff[1].DI"/>
<direct name="direct4" input="ff[1].Q" output="fabric.sc_out"/>
<direct name="direct5" input="ff[1].Q" output="fabric.reg_out"/>
<direct name="direct2" input="fabric.cin" output="frac_logic.cin"/>
<direct name="direct3" input="fabric.sc_in" output="ff[0].DI"/>
<direct name="direct4" input="ff[0].Q" output="ff[1].DI"/>
<direct name="direct5" input="ff[1].Q" output="fabric.sc_out"/>
<direct name="direct6" input="ff[1].Q" output="fabric.reg_out"/>
<direct name="direct7" input="frac_logic.cout" output="fabric.cout"/>
<complete name="complete1" input="fabric.clk" output="ff[1:0].clk"/>
<complete name="complete2" input="fabric.reset" output="ff[1:0].reset"/>
<mux name="mux1" input="frac_logic.out[0:0] fabric.reg_in" output="ff[0:0].D">
@ -477,6 +500,68 @@
</interconnect>
</mode>
<!-- Physical mode definition end (physical implementation of the fle) -->
<!-- Arithmetic mode definition begin -->
<mode name="arithmetic">
<pb_type name="soft_adder" num_pb="1">
<input name="in" num_pins="4"/>
<input name="cin" num_pins="1"/>
<output name="sumout" num_pins="1"/>
<output name="cout" num_pins="1"/>
<!-- Define special LUT marco to be used as adder -->
<pb_type name="adder_lut4" blif_model=".subckt adder_lut4" num_pb="1">
<input name="in" num_pins="4"/>
<output name="lut2_out" num_pins="2"/>
<output name="lut4_out" num_pins="1"/>
<delay_constant max="0.3e-9" in_port="adder_lut4.in" out_port="adder_lut4.lut2_out"/>
<delay_constant max="0.3e-9" in_port="adder_lut4.in" out_port="adder_lut4.lut4_out"/>
</pb_type>
<pb_type name="carry_follower" blif_model=".subckt carry_follower" num_pb="1">
<input name="a" num_pins="1"/>
<input name="b" num_pins="1"/>
<input name="cin" num_pins="1"/>
<output name="cout" num_pins="1"/>
<delay_constant max="0.3e-9" in_port="carry_follower.a" out_port="carry_follower.cout"/>
<delay_constant max="0.3e-9" in_port="carry_follower.b" out_port="carry_follower.cout"/>
<delay_constant max="0.3e-9" in_port="carry_follower.cin" out_port="carry_follower.cout"/>
</pb_type>
<interconnect>
<direct name="direct1" input="soft_adder.in[0:1]" output="adder_lut4.in[0:1]"/>
<direct name="direct2" input="soft_adder.in[3:3]" output="adder_lut4.in[3:3]"/>
<direct name="direct3" input="soft_adder.cin" output="carry_follower.b">
<!-- Pack pattern to build an adder chain connection considered by packer -->
<pack_pattern name="chain" in_port="soft_adder.cin" out_port="carry_follower.b"/>
</direct>
<direct name="direct4" input="adder_lut4.lut2_out[1:1]" output="carry_follower.a">
<!-- Pack pattern to pair adder_lut4 and carry_follower into a molecule
considered by packer -->
<pack_pattern name="lut_follower" in_port="adder_lut4.lut2_out[1:1]" out_port="carry_follower.a"/>
</direct>
<direct name="direct5" input="adder_lut4.lut2_out[0:0]" output="carry_follower.cin">
</direct>
<direct name="direct6" input="carry_follower.cout" output="soft_adder.cout">
<!-- Pack pattern to build an adder chain connection considered by packer -->
<pack_pattern name="chain" in_port="carry_follower.cout" out_port="soft_adder.cout"/>
</direct>
<direct name="direct7" input="adder_lut4.lut4_out" output="soft_adder.sumout[0:0]">
</direct>
<mux name="mux1" input="soft_adder.cin soft_adder.in[2:2]" output="adder_lut4.in[2:2]">
</mux>
</interconnect>
</pb_type>
<interconnect>
<direct name="direct1" input="fle.in" output="soft_adder.in"/>
<direct name="direct2" input="fle.cin" output="soft_adder.cin">
<!-- Pack pattern to build an adder chain connection considered by packer -->
<pack_pattern name="chain" in_port="fle.cin" out_port="soft_adder.cin"/>
</direct>
<direct name="direct3" input="soft_adder.sumout" output="fle.out[0:0]"/>
<direct name="direct4" input="soft_adder.cout" output="fle.cout">
<!-- Pack pattern to build an adder chain connection considered by packer -->
<pack_pattern name="chain" in_port="soft_adder.cout" out_port="fle.cout"/>
</direct>
</interconnect>
</mode>
<!-- Arithmetic mode definition end -->
<!-- Dual 3-LUT mode definition begin -->
<mode name="n2_lut3">
<pb_type name="lut3inter" num_pb="1">
@ -722,11 +807,14 @@
<!-- Carry chain links -->
<direct name="carry_chain_in" input="clb.cin" output="fle[0:0].cin">
<!-- Put all inter-block carry chain delay on this one edge -->
<pack_pattern name="chain" in_port="clb.cin" out_port="fle[0:0].cin"/>
<delay_constant max="0.16e-9" in_port="clb.cin" out_port="fle[0:0].cin"/>
</direct>
<direct name="carry_chain_out" input="fle[7:7].cout" output="clb.cout">
<pack_pattern name="chain" in_port="fle[7:7].cout" out_port="clb.cout"/>
</direct>
<direct name="carry_chain_link" input="fle[6:0].cout" output="fle[7:1].cin">
<pack_pattern name="chain" in_port="fle[6:0].cout" out_port="fle[7:1].cin"/>
</direct>
</interconnect>
<!-- Every input pin is driven by 15% of the tracks in a channel, every output pin is driven by 10% of the tracks in a channel -->