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:
commit
ee14c15e58
|
@ -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
|
||||
|
|
|
@ -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.
|
|
@ -18,4 +18,6 @@ OpenFPGA widely uses XML format for interchangable files
|
|||
|
||||
fabric_bitstream
|
||||
|
||||
bitstream_setting
|
||||
|
||||
fabric_key
|
||||
|
|
|
@ -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
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
|
|
@ -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 */
|
|
@ -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
|
|
@ -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
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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";
|
||||
}
|
|
@ -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
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]);
|
||||
}
|
||||
}
|
|
@ -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 */
|
|
@ -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
|
|
@ -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*/
|
|
@ -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
|
|
@ -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_;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
|
@ -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'
|
||||
*/
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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"
|
||||
|
||||
/********************************************************************
|
||||
|
|
|
@ -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
|
||||
******************************************************************************/
|
||||
|
|
|
@ -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_;
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -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
|
|
@ -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
|
|
@ -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>
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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>
|
|
@ -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=
|
|
@ -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 -->
|
||||
|
|
Loading…
Reference in New Issue