Merge pull request #266 from lnis-uofu/ganesh_dev

[Task/Flow] Extended Yosys support in OpenFPGA task
This commit is contained in:
tangxifan 2021-03-15 10:06:11 -06:00 committed by GitHub
commit 063c58b6cb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 373 additions and 41 deletions

View File

@ -136,6 +136,8 @@ When a global port, e.g., ``clk``, is defined in ``tile_annotation`` using the f
Clock port ``clk`` of each ``clb`` tile will be connected to a common clock port of the top module, while local clock network is customizable through VPR's architecture description language. For instance, the local clock network can be a programmable clock network. Clock port ``clk`` of each ``clb`` tile will be connected to a common clock port of the top module, while local clock network is customizable through VPR's architecture description language. For instance, the local clock network can be a programmable clock network.
.. _annotate_vpr_arch_pb_type_annotation:
Primitive Blocks inside Multi-mode Configurable Logic Blocks Primitive Blocks inside Multi-mode Configurable Logic Blocks
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -9,7 +9,7 @@ This can define a hard-coded bitstream for a reconfigurable resource in FPGA fab
.. code-block:: xml .. code-block:: xml
<openfpga_bitstream_setting> <openfpga_bitstream_setting>
<pb_type name="<string>" source="eblif" content=".param LUT"/> <pb_type name="<string>" source="eblif" content=".param LUT" is_mode_select_bistream="true" bitstream_offset="1"/>
</openfpga_bitstream_setting> </openfpga_bitstream_setting>
.. option:: pb_type="<string>" .. option:: pb_type="<string>"
@ -24,4 +24,14 @@ This can define a hard-coded bitstream for a reconfigurable resource in FPGA fab
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). 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.
.. option:: is_mode_select_bitstream="<bool>"
Can be either ``true`` or ``false``. When set ``true``, the bitstream is considered as mode-selection bitstream, which may overwrite ``mode_bits`` definition in ``pb_type_annotation`` of OpenFPGA architecture description. (See details in :ref:`annotate_vpr_arch_pb_type_annotation`)
.. option:: bitstream_offset="<int>"
Specify the offset to be applied when overloading the bitstream to a target. For example, a LUT may have a 16-bit bitstream. When ``offset=1``, bitstream overloading will skip the first bit and start from the second bit of the 16-bit bitstream.
.. warning:: Bitstream setting is a feature for power-users. It may cause wrong bitstream to be generated. For example, the hard-coded bitstream is not compatible with LUTs whose nets may be swapped during routing stage (cause a change on the truth table as well as bitstream). It is users's responsibility to ensure correct bitstream.

View File

@ -51,6 +51,17 @@ std::string BitstreamSetting::pb_type_bitstream_content(const BitstreamPbTypeSet
return pb_type_bitstream_contents_[pb_type_setting_id]; return pb_type_bitstream_contents_[pb_type_setting_id];
} }
bool BitstreamSetting::is_mode_select_bitstream(const BitstreamPbTypeSettingId& pb_type_setting_id) const {
VTR_ASSERT(true == valid_bitstream_pb_type_setting_id(pb_type_setting_id));
return is_mode_select_bitstreams_[pb_type_setting_id];
}
size_t BitstreamSetting::bitstream_offset(const BitstreamPbTypeSettingId& pb_type_setting_id) const {
VTR_ASSERT(true == valid_bitstream_pb_type_setting_id(pb_type_setting_id));
return bitstream_offsets_[pb_type_setting_id];
}
/************************************************************************ /************************************************************************
* Public Mutators * Public Mutators
***********************************************************************/ ***********************************************************************/
@ -66,10 +77,24 @@ BitstreamPbTypeSettingId BitstreamSetting::add_bitstream_pb_type_setting(const s
parent_mode_names_.push_back(parent_mode_names); parent_mode_names_.push_back(parent_mode_names);
pb_type_bitstream_sources_.push_back(bitstream_source); pb_type_bitstream_sources_.push_back(bitstream_source);
pb_type_bitstream_contents_.push_back(bitstream_content); pb_type_bitstream_contents_.push_back(bitstream_content);
is_mode_select_bitstreams_.push_back(false);
bitstream_offsets_.push_back(0);
return pb_type_setting_id; return pb_type_setting_id;
} }
void BitstreamSetting::set_mode_select_bitstream(const BitstreamPbTypeSettingId& pb_type_setting_id,
const bool& is_mode_select_bitstream) {
VTR_ASSERT(true == valid_bitstream_pb_type_setting_id(pb_type_setting_id));
is_mode_select_bitstreams_[pb_type_setting_id] = is_mode_select_bitstream;
}
void BitstreamSetting::set_bitstream_offset(const BitstreamPbTypeSettingId& pb_type_setting_id,
const size_t& offset) {
VTR_ASSERT(true == valid_bitstream_pb_type_setting_id(pb_type_setting_id));
bitstream_offsets_[pb_type_setting_id] = offset;
}
/************************************************************************ /************************************************************************
* Public Validators * Public Validators
***********************************************************************/ ***********************************************************************/

View File

@ -39,12 +39,18 @@ class BitstreamSetting {
std::vector<std::string> parent_mode_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_source(const BitstreamPbTypeSettingId& pb_type_setting_id) const;
std::string pb_type_bitstream_content(const BitstreamPbTypeSettingId& pb_type_setting_id) const; std::string pb_type_bitstream_content(const BitstreamPbTypeSettingId& pb_type_setting_id) const;
bool is_mode_select_bitstream(const BitstreamPbTypeSettingId& pb_type_setting_id) const;
size_t bitstream_offset(const BitstreamPbTypeSettingId& pb_type_setting_id) const;
public: /* Public Mutators */ public: /* Public Mutators */
BitstreamPbTypeSettingId add_bitstream_pb_type_setting(const std::string& pb_type_name, 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_pb_type_names,
const std::vector<std::string>& parent_mode_names, const std::vector<std::string>& parent_mode_names,
const std::string& bitstream_source, const std::string& bitstream_source,
const std::string& bitstream_content); const std::string& bitstream_content);
void set_mode_select_bitstream(const BitstreamPbTypeSettingId& pb_type_setting_id,
const bool& is_mode_select_bitstream);
void set_bitstream_offset(const BitstreamPbTypeSettingId& pb_type_setting_id,
const size_t& offset);
public: /* Public Validators */ public: /* Public Validators */
bool valid_bitstream_pb_type_setting_id(const BitstreamPbTypeSettingId& pb_type_setting_id) const; bool valid_bitstream_pb_type_setting_id(const BitstreamPbTypeSettingId& pb_type_setting_id) const;
private: /* Internal data */ private: /* Internal data */
@ -54,6 +60,10 @@ class BitstreamSetting {
vtr::vector<BitstreamPbTypeSettingId, std::vector<std::string>> parent_mode_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_sources_;
vtr::vector<BitstreamPbTypeSettingId, std::string> pb_type_bitstream_contents_; vtr::vector<BitstreamPbTypeSettingId, std::string> pb_type_bitstream_contents_;
/* Indicate if the bitstream is applied to mode selection bits of a pb_type */
vtr::vector<BitstreamPbTypeSettingId, bool> is_mode_select_bitstreams_;
/* The offset that the bitstream is applied to the original bitstream of a pb_type */
vtr::vector<BitstreamPbTypeSettingId, size_t> bitstream_offsets_;
}; };
} /* namespace openfpga ends */ } /* namespace openfpga ends */

View File

@ -36,11 +36,18 @@ void read_xml_bitstream_pb_type_setting(pugi::xml_node& xml_pb_type,
openfpga::PbParser operating_pb_parser(name_attr); openfpga::PbParser operating_pb_parser(name_attr);
/* Add to bitstream setting */ /* Add to bitstream setting */
bitstream_setting.add_bitstream_pb_type_setting(operating_pb_parser.leaf(), BitstreamPbTypeSettingId bitstream_pb_type_id = bitstream_setting.add_bitstream_pb_type_setting(operating_pb_parser.leaf(),
operating_pb_parser.parents(), operating_pb_parser.parents(),
operating_pb_parser.modes(), operating_pb_parser.modes(),
source_attr, source_attr,
content_attr); content_attr);
/* Parse if the bitstream overwritting is applied to mode bits of a pb_type */
const bool& is_mode_select_bitstream = get_attribute(xml_pb_type, "is_mode_select_bitstream", loc_data, pugiutil::ReqOpt::OPTIONAL).as_bool(false);
bitstream_setting.set_mode_select_bitstream(bitstream_pb_type_id, is_mode_select_bitstream);
const int& offset = get_attribute(xml_pb_type, "bitstream_offset", loc_data, pugiutil::ReqOpt::OPTIONAL).as_int(0);
bitstream_setting.set_bitstream_offset(bitstream_pb_type_id, offset);
} }
/******************************************************************** /********************************************************************

View File

@ -57,6 +57,8 @@ void write_xml_bitstream_pb_type_setting(std::fstream& fp,
write_xml_attribute(fp, "source", bitstream_setting.pb_type_bitstream_source(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()); write_xml_attribute(fp, "content", bitstream_setting.pb_type_bitstream_content(bitstream_pb_type_setting_id).c_str());
write_xml_attribute(fp, "is_mode_select_bitstream", bitstream_setting.is_mode_select_bitstream(bitstream_pb_type_setting_id));
write_xml_attribute(fp, "bitstream_offset", bitstream_setting.bitstream_offset(bitstream_pb_type_setting_id));
fp << "/>" << "\n"; fp << "/>" << "\n";
} }

View File

@ -56,17 +56,30 @@ int annotate_bitstream_setting(const BitstreamSetting& bitstream_setting,
if (nullptr == target_pb_type) { if (nullptr == target_pb_type) {
continue; continue;
} }
/* Found one, build annotation */ /* Found one, build annotation */
if (std::string("eblif") == bitstream_setting.pb_type_bitstream_source(bitstream_pb_type_setting_id)) { 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! */ /* Invalid source, error out! */
VTR_LOG_ERROR("Invalid bitstream source '%s' for pb_type '%s' which is defined in bitstream setting\n", 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(), bitstream_setting.pb_type_bitstream_source(bitstream_pb_type_setting_id).c_str(),
target_pb_type_names[0].c_str()); target_pb_type_names[0].c_str());
return CMD_EXEC_FATAL_ERROR; 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));
/* Depending on the bitstream type, annotate through different entrances
* - For regular bitstream, set bitstream content, flags etc.
* - For mode-select bitstream, set mode-select bitstream content, flags etc.
*/
if (false == bitstream_setting.is_mode_select_bitstream(bitstream_pb_type_setting_id)) {
vpr_bitstream_annotation.set_pb_type_bitstream_source(target_pb_type, VprBitstreamAnnotation::e_bitstream_source_type::BITSTREAM_SOURCE_EBLIF);
vpr_bitstream_annotation.set_pb_type_bitstream_content(target_pb_type, bitstream_setting.pb_type_bitstream_content(bitstream_pb_type_setting_id));
vpr_bitstream_annotation.set_pb_type_bitstream_offset(target_pb_type, bitstream_setting.bitstream_offset(bitstream_pb_type_setting_id));
} else {
VTR_ASSERT_SAFE(false == bitstream_setting.is_mode_select_bitstream(bitstream_pb_type_setting_id));
vpr_bitstream_annotation.set_pb_type_mode_select_bitstream_source(target_pb_type, VprBitstreamAnnotation::e_bitstream_source_type::BITSTREAM_SOURCE_EBLIF);
vpr_bitstream_annotation.set_pb_type_mode_select_bitstream_content(target_pb_type, bitstream_setting.pb_type_bitstream_content(bitstream_pb_type_setting_id));
vpr_bitstream_annotation.set_pb_type_mode_select_bitstream_offset(target_pb_type, bitstream_setting.bitstream_offset(bitstream_pb_type_setting_id));
}
link_success = true; link_success = true;
} }

View File

@ -38,6 +38,46 @@ std::string VprBitstreamAnnotation::pb_type_bitstream_content(t_pb_type* pb_type
return std::string(); return std::string();
} }
size_t VprBitstreamAnnotation::pb_type_bitstream_offset(t_pb_type* pb_type) const {
auto result = bitstream_offsets_.find(pb_type);
if (result != bitstream_offsets_.end()) {
return result->second;
}
/* Not found, return an zero offset */
return 0;
}
VprBitstreamAnnotation::e_bitstream_source_type VprBitstreamAnnotation::pb_type_mode_select_bitstream_source(t_pb_type* pb_type) const {
auto result = mode_select_bitstream_sources_.find(pb_type);
if (result != mode_select_bitstream_sources_.end()) {
return result->second;
}
/* Not found, return an invalid type*/
return NUM_BITSTREAM_SOURCE_TYPES;
}
std::string VprBitstreamAnnotation::pb_type_mode_select_bitstream_content(t_pb_type* pb_type) const {
auto result = mode_select_bitstream_contents_.find(pb_type);
if (result != mode_select_bitstream_contents_.end()) {
return result->second;
}
/* Not found, return an invalid type */
return std::string();
}
size_t VprBitstreamAnnotation::pb_type_mode_select_bitstream_offset(t_pb_type* pb_type) const {
auto result = mode_select_bitstream_offsets_.find(pb_type);
if (result != mode_select_bitstream_offsets_.end()) {
return result->second;
}
/* Not found, return an zero offset */
return 0;
}
/************************************************************************ /************************************************************************
* Public mutators * Public mutators
***********************************************************************/ ***********************************************************************/
@ -45,10 +85,30 @@ void VprBitstreamAnnotation::set_pb_type_bitstream_source(t_pb_type* pb_type,
const e_bitstream_source_type& bitstream_source) { const e_bitstream_source_type& bitstream_source) {
bitstream_sources_[pb_type] = bitstream_source; bitstream_sources_[pb_type] = bitstream_source;
} }
void VprBitstreamAnnotation::set_pb_type_bitstream_content(t_pb_type* pb_type, void VprBitstreamAnnotation::set_pb_type_bitstream_content(t_pb_type* pb_type,
const std::string& bitstream_content) { const std::string& bitstream_content) {
bitstream_contents_[pb_type] = bitstream_content; bitstream_contents_[pb_type] = bitstream_content;
} }
void VprBitstreamAnnotation::set_pb_type_bitstream_offset(t_pb_type* pb_type,
const size_t& offset) {
bitstream_offsets_[pb_type] = offset;
}
void VprBitstreamAnnotation::set_pb_type_mode_select_bitstream_source(t_pb_type* pb_type,
const e_bitstream_source_type& bitstream_source) {
mode_select_bitstream_sources_[pb_type] = bitstream_source;
}
void VprBitstreamAnnotation::set_pb_type_mode_select_bitstream_content(t_pb_type* pb_type,
const std::string& bitstream_content) {
mode_select_bitstream_contents_[pb_type] = bitstream_content;
}
void VprBitstreamAnnotation::set_pb_type_mode_select_bitstream_offset(t_pb_type* pb_type,
const size_t& offset) {
mode_select_bitstream_offsets_[pb_type] = offset;
}
} /* End namespace openfpga*/ } /* End namespace openfpga*/

View File

@ -33,16 +33,41 @@ class VprBitstreamAnnotation {
public: /* Public accessors */ public: /* Public accessors */
e_bitstream_source_type pb_type_bitstream_source(t_pb_type* pb_type) const; 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; std::string pb_type_bitstream_content(t_pb_type* pb_type) const;
size_t pb_type_bitstream_offset(t_pb_type* pb_type) const;
e_bitstream_source_type pb_type_mode_select_bitstream_source(t_pb_type* pb_type) const;
std::string pb_type_mode_select_bitstream_content(t_pb_type* pb_type) const;
size_t pb_type_mode_select_bitstream_offset(t_pb_type* pb_type) const;
public: /* Public mutators */ public: /* Public mutators */
void set_pb_type_bitstream_source(t_pb_type* pb_type, void set_pb_type_bitstream_source(t_pb_type* pb_type,
const e_bitstream_source_type& bitstream_source); const e_bitstream_source_type& bitstream_source);
void set_pb_type_bitstream_content(t_pb_type* pb_type, void set_pb_type_bitstream_content(t_pb_type* pb_type,
const std::string& bitstream_content); const std::string& bitstream_content);
void set_pb_type_bitstream_offset(t_pb_type* pb_type,
const size_t& offset);
void set_pb_type_mode_select_bitstream_source(t_pb_type* pb_type,
const e_bitstream_source_type& bitstream_source);
void set_pb_type_mode_select_bitstream_content(t_pb_type* pb_type,
const std::string& bitstream_content);
void set_pb_type_mode_select_bitstream_offset(t_pb_type* pb_type,
const size_t& offset);
private: /* Internal data */ private: /* Internal data */
/* For regular bitstreams */
/* A look up for pb type to find bitstream source type */ /* A look up for pb type to find bitstream source type */
std::map<t_pb_type*, e_bitstream_source_type> bitstream_sources_; std::map<t_pb_type*, e_bitstream_source_type> bitstream_sources_;
/* Binding from pb type to bitstream content */ /* Binding from pb type to bitstream content */
std::map<t_pb_type*, std::string> bitstream_contents_; std::map<t_pb_type*, std::string> bitstream_contents_;
/* Offset to be applied to bitstream */
std::map<t_pb_type*, size_t> bitstream_offsets_;
/* For mode-select bitstreams */
/* A look up for pb type to find bitstream source type */
std::map<t_pb_type*, e_bitstream_source_type> mode_select_bitstream_sources_;
/* Binding from pb type to bitstream content */
std::map<t_pb_type*, std::string> mode_select_bitstream_contents_;
/* Offset to be applied to mode-select bitstream */
std::map<t_pb_type*, size_t> mode_select_bitstream_offsets_;
}; };
} /* End namespace openfpga*/ } /* End namespace openfpga*/

View File

@ -448,18 +448,18 @@ void build_lut_bitstream(BitstreamManager& bitstream_manager,
/* If the physical pb contains fixed bitstream, overload here */ /* If the physical pb contains fixed bitstream, overload here */
if (false == physical_pb.fixed_bitstream(lut_pb_id).empty()) { if (false == physical_pb.fixed_bitstream(lut_pb_id).empty()) {
std::string fixed_bitstream = physical_pb.fixed_bitstream(lut_pb_id); std::string fixed_bitstream = physical_pb.fixed_bitstream(lut_pb_id);
size_t start_index = physical_pb.fixed_bitstream_offset(lut_pb_id);
/* Ensure the length matches!!! */ /* Ensure the length matches!!! */
if (lut_bitstream.size() != fixed_bitstream.size()) { if (lut_bitstream.size() - start_index < fixed_bitstream.size()) {
VTR_LOG_ERROR("Unmatched length of fixed bitstream %s!Expected to be %ld bits\n", VTR_LOG_ERROR("Unmatched length of fixed bitstream %s!Expected to be less than %ld bits\n",
fixed_bitstream.c_str(), fixed_bitstream.c_str(),
lut_bitstream.size()); lut_bitstream.size() - start_index);
exit(1); exit(1);
} }
/* Overload here */ /* Overload the bitstream here */
lut_bitstream.clear(); for (size_t bit_index = 0; bit_index < lut_bitstream.size(); ++bit_index) {
for (const char& fixed_bit : fixed_bitstream) { VTR_ASSERT('0' == fixed_bitstream[bit_index] || '1' == fixed_bitstream[bit_index]);
VTR_ASSERT('0' == fixed_bit || '1' == fixed_bit); lut_bitstream[bit_index + start_index] = ('1' == fixed_bitstream[bit_index]);
lut_bitstream.push_back('1' == fixed_bit);
} }
} }
} }
@ -469,9 +469,29 @@ void build_lut_bitstream(BitstreamManager& bitstream_manager,
std::vector<bool> mode_select_bitstream; std::vector<bool> mode_select_bitstream;
if (true == physical_pb.valid_pb_id(lut_pb_id)) { if (true == physical_pb.valid_pb_id(lut_pb_id)) {
mode_select_bitstream = generate_mode_select_bitstream(physical_pb.mode_bits(lut_pb_id)); mode_select_bitstream = generate_mode_select_bitstream(physical_pb.mode_bits(lut_pb_id));
/* If the physical pb contains fixed mode-select bitstream, overload here */
if (false == physical_pb.fixed_mode_select_bitstream(lut_pb_id).empty()) {
std::string fixed_mode_select_bitstream = physical_pb.fixed_mode_select_bitstream(lut_pb_id);
size_t mode_bits_start_index = physical_pb.fixed_mode_select_bitstream_offset(lut_pb_id);
/* Ensure the length matches!!! */
if (mode_select_bitstream.size() - mode_bits_start_index < fixed_mode_select_bitstream.size()) {
VTR_LOG_ERROR("Unmatched length of fixed mode_select_bitstream %s!Expected to be less than %ld bits\n",
fixed_mode_select_bitstream.c_str(),
mode_select_bitstream.size() - mode_bits_start_index);
exit(1);
}
/* Overload the bitstream here */
for (size_t bit_index = 0; bit_index < fixed_mode_select_bitstream.size(); ++bit_index) {
VTR_ASSERT('0' == fixed_mode_select_bitstream[bit_index] || '1' == fixed_mode_select_bitstream[bit_index]);
mode_select_bitstream[bit_index + mode_bits_start_index] = ('1' == fixed_mode_select_bitstream[bit_index]);
}
}
} else { /* get default mode_bits */ } else { /* get default mode_bits */
mode_select_bitstream = generate_mode_select_bitstream(device_annotation.pb_type_mode_bits(lut_pb_type)); mode_select_bitstream = generate_mode_select_bitstream(device_annotation.pb_type_mode_bits(lut_pb_type));
} }
/* Conjunct the mode-select bitstream to the lut bitstream */ /* Conjunct the mode-select bitstream to the lut bitstream */
for (const bool& bit : mode_select_bitstream) { for (const bool& bit : mode_select_bitstream) {
lut_bitstream.push_back(bit); lut_bitstream.push_back(bit);

View File

@ -107,6 +107,21 @@ std::string PhysicalPb::fixed_bitstream(const PhysicalPbId& pb) const {
return fixed_bitstreams_[pb]; return fixed_bitstreams_[pb];
} }
size_t PhysicalPb::fixed_bitstream_offset(const PhysicalPbId& pb) const {
VTR_ASSERT(true == valid_pb_id(pb));
return fixed_bitstream_offsets_[pb];
}
std::string PhysicalPb::fixed_mode_select_bitstream(const PhysicalPbId& pb) const {
VTR_ASSERT(true == valid_pb_id(pb));
return fixed_mode_select_bitstreams_[pb];
}
size_t PhysicalPb::fixed_mode_select_bitstream_offset(const PhysicalPbId& pb) const {
VTR_ASSERT(true == valid_pb_id(pb));
return fixed_mode_select_bitstream_offsets_[pb];
}
/****************************************************************************** /******************************************************************************
* Private Mutators * Private Mutators
******************************************************************************/ ******************************************************************************/
@ -133,7 +148,11 @@ PhysicalPbId PhysicalPb::create_pb(const t_pb_graph_node* pb_graph_node) {
truth_tables_.emplace_back(); truth_tables_.emplace_back();
mode_bits_.emplace_back(); mode_bits_.emplace_back();
fixed_bitstreams_.emplace_back(); fixed_bitstreams_.emplace_back();
fixed_bitstream_offsets_.push_back(0);
fixed_mode_select_bitstreams_.emplace_back();
fixed_mode_select_bitstream_offsets_.push_back(0);
/* Register in the name2id map */ /* Register in the name2id map */
type2id_map_[pb_graph_node] = pb; type2id_map_[pb_graph_node] = pb;
@ -218,6 +237,24 @@ void PhysicalPb::set_fixed_bitstream(const PhysicalPbId& pb,
fixed_bitstreams_[pb] = fixed_bitstream; fixed_bitstreams_[pb] = fixed_bitstream;
} }
void PhysicalPb::set_fixed_bitstream_offset(const PhysicalPbId& pb,
const size_t& offset) {
VTR_ASSERT(true == valid_pb_id(pb));
fixed_bitstream_offsets_[pb] = offset;
}
void PhysicalPb::set_fixed_mode_select_bitstream(const PhysicalPbId& pb,
const std::string& fixed_bitstream) {
VTR_ASSERT(true == valid_pb_id(pb));
fixed_mode_select_bitstreams_[pb] = fixed_bitstream;
}
void PhysicalPb::set_fixed_mode_select_bitstream_offset(const PhysicalPbId& pb,
const size_t& offset) {
VTR_ASSERT(true == valid_pb_id(pb));
fixed_mode_select_bitstream_offsets_[pb] = offset;
}
/****************************************************************************** /******************************************************************************
* Private validators/invalidators * Private validators/invalidators
******************************************************************************/ ******************************************************************************/

View File

@ -55,6 +55,9 @@ class PhysicalPb {
std::map<const t_pb_graph_pin*, AtomNetlist::TruthTable> truth_tables(const PhysicalPbId& pb) 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::vector<size_t> mode_bits(const PhysicalPbId& pb) const;
std::string fixed_bitstream(const PhysicalPbId& pb) const; std::string fixed_bitstream(const PhysicalPbId& pb) const;
size_t fixed_bitstream_offset(const PhysicalPbId& pb) const;
std::string fixed_mode_select_bitstream(const PhysicalPbId& pb) const;
size_t fixed_mode_select_bitstream_offset(const PhysicalPbId& pb) const;
public: /* Public mutators */ public: /* Public mutators */
PhysicalPbId create_pb(const t_pb_graph_node* pb_graph_node); PhysicalPbId create_pb(const t_pb_graph_node* pb_graph_node);
void add_child(const PhysicalPbId& parent, void add_child(const PhysicalPbId& parent,
@ -75,6 +78,12 @@ class PhysicalPb {
const bool& wire_lut_output); const bool& wire_lut_output);
void set_fixed_bitstream(const PhysicalPbId& pb, void set_fixed_bitstream(const PhysicalPbId& pb,
const std::string& fixed_bitstream); const std::string& fixed_bitstream);
void set_fixed_bitstream_offset(const PhysicalPbId& pb,
const size_t& offset);
void set_fixed_mode_select_bitstream(const PhysicalPbId& pb,
const std::string& fixed_bitstream);
void set_fixed_mode_select_bitstream_offset(const PhysicalPbId& pb,
const size_t& offset);
public: /* Public validators/invalidators */ public: /* Public validators/invalidators */
bool valid_pb_id(const PhysicalPbId& pb_id) const; bool valid_pb_id(const PhysicalPbId& pb_id) const;
bool empty() const; bool empty() const;
@ -98,6 +107,10 @@ class PhysicalPb {
vtr::vector<PhysicalPbId, std::vector<size_t>> mode_bits_; vtr::vector<PhysicalPbId, std::vector<size_t>> mode_bits_;
vtr::vector<PhysicalPbId, std::string> fixed_bitstreams_; vtr::vector<PhysicalPbId, std::string> fixed_bitstreams_;
vtr::vector<PhysicalPbId, size_t> fixed_bitstream_offsets_;
vtr::vector<PhysicalPbId, std::string> fixed_mode_select_bitstreams_;
vtr::vector<PhysicalPbId, size_t> fixed_mode_select_bitstream_offsets_;
/* Fast lookup */ /* Fast lookup */
std::map<const t_pb_graph_node*, PhysicalPbId> type2id_map_; std::map<const t_pb_graph_node*, PhysicalPbId> type2id_map_;

View File

@ -304,7 +304,7 @@ void rec_update_physical_pb_from_operating_pb(PhysicalPb& phy_pb,
VTR_ASSERT(atom_blk); VTR_ASSERT(atom_blk);
phy_pb.add_atom_block(physical_pb, atom_blk); phy_pb.add_atom_block(physical_pb, atom_blk);
/* if the operating pb type has bitstream annotation, /* if the operating pb type has bitstream annotation,
* bind the bitstream value from atom block to the physical pb * bind the bitstream value from atom block to the physical pb
*/ */
@ -313,17 +313,55 @@ void rec_update_physical_pb_from_operating_pb(PhysicalPb& phy_pb,
std::vector<std::string> tokens = tokenizer.split(" "); std::vector<std::string> tokens = tokenizer.split(" ");
/* FIXME: The token-level check should be done much earlier!!! */ /* FIXME: The token-level check should be done much earlier!!! */
VTR_ASSERT(2 == tokens.size()); VTR_ASSERT(2 == tokens.size());
/* The token is typically organized as <.param|.attr> <identifier string> */
if (std::string(".param") == tokens[0]) { if (std::string(".param") == tokens[0]) {
for (const auto& param_search : atom_ctx.nlist.block_params(atom_blk)) { for (const auto& param_search : atom_ctx.nlist.block_params(atom_blk)) {
if (param_search.first == tokens[1]) { /* Bypass unmatched parameter identifier */
phy_pb.set_fixed_bitstream(physical_pb, param_search.second); if (param_search.first != tokens[1]) {
} continue;
}
phy_pb.set_fixed_bitstream(physical_pb, param_search.second);
phy_pb.set_fixed_bitstream_offset(physical_pb, bitstream_annotation.pb_type_bitstream_offset(pb_type));
} }
} else if (std::string(".attr") == tokens[0]) { } else if (std::string(".attr") == tokens[0]) {
for (const auto& attr_search : atom_ctx.nlist.block_attrs(atom_blk)) { for (const auto& attr_search : atom_ctx.nlist.block_attrs(atom_blk)) {
/* Bypass unmatched parameter identifier */
if (attr_search.first == tokens[1]) { if (attr_search.first == tokens[1]) {
phy_pb.set_fixed_bitstream(physical_pb, attr_search.second); continue;
} }
phy_pb.set_fixed_bitstream(physical_pb, attr_search.second);
phy_pb.set_fixed_bitstream_offset(physical_pb, bitstream_annotation.pb_type_bitstream_offset(pb_type));
}
}
}
/* if the operating pb type has mode-select 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_mode_select_bitstream_source(pb_type)) {
StringToken tokenizer = bitstream_annotation.pb_type_mode_select_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());
/* The token is typically organized as <.param|.attr> <identifier string> */
if (std::string(".param") == tokens[0]) {
for (const auto& param_search : atom_ctx.nlist.block_params(atom_blk)) {
/* Bypass unmatched parameter identifier */
if (param_search.first != tokens[1]) {
continue;
}
phy_pb.set_fixed_mode_select_bitstream(physical_pb, param_search.second);
phy_pb.set_fixed_mode_select_bitstream_offset(physical_pb, bitstream_annotation.pb_type_mode_select_bitstream_offset(pb_type));
}
} else if (std::string(".attr") == tokens[0]) {
for (const auto& attr_search : atom_ctx.nlist.block_attrs(atom_blk)) {
/* Bypass unmatched parameter identifier */
if (attr_search.first == tokens[1]) {
continue;
}
phy_pb.set_fixed_mode_select_bitstream(physical_pb, attr_search.second);
phy_pb.set_fixed_mode_select_bitstream_offset(physical_pb, bitstream_annotation.pb_type_mode_select_bitstream_offset(pb_type));
} }
} }
} }

View File

@ -4,4 +4,4 @@ ${READ_VERILOG_FILE}
synth_quicklogic -blif ${OUTPUT_BLIF} -top ${TOP_MODULE} ${YOSYS_ARGS} synth_quicklogic -blif ${OUTPUT_BLIF} -top ${TOP_MODULE} ${YOSYS_ARGS}
write_verilog -noattr -nohex ${TOP_MODULE}.v write_verilog -noattr -nohex ${OUTPUT_VERILOG}

View File

@ -0,0 +1,4 @@
# Rewrite the .blif to Verilog
# so that the pin sequence matches
read_blif rewritten_${OUTPUT_BLIF}
write_verilog ${OUTPUT_VERILOG}

View File

@ -0,0 +1,22 @@
# Yosys synthesis script for ${TOP_MODULE}
# Read verilog files
${READ_VERILOG_FILE}
# Technology mapping
hierarchy -top ${TOP_MODULE}
proc
techmap -D NO_LUT -map +/adff2dff.v
# Synthesis
synth -top ${TOP_MODULE} -flatten
clean
# LUT mapping
abc -lut ${LUT_SIZE}
# Check
synth -run check
# Clean and output blif
opt_clean -purge
write_blif rewritten_${OUTPUT_BLIF}

View File

@ -206,9 +206,9 @@
<!-- A dummy model to include the adder_lut verilog code in testbench netlists <!-- A dummy model to include the adder_lut verilog code in testbench netlists
so that HDL simulation can be run when adder lut is used in users' implementations so that HDL simulation can be run when adder lut is used in users' implementations
--> -->
<!--circuit_model type="inv_buf" name="dummy1" prefix="dummy1" verilog_netlist="${OPENFPGA_PATH}/yosys/techlibs/quicklogic/openfpga_cells_sim.v"> <!-- circuit_model type="inv_buf" name="dummy1" prefix="dummy1" verilog_netlist="${OPENFPGA_PATH}/yosys/techlibs/quicklogic/qlf_k4n8_cells_sim.v">
<design_technology type="cmos" topology="inverter" size="1"/> <design_technology type="cmos" topology="inverter" size="1"/>
</circuit_model--> </circuit_model -->
</circuit_library> </circuit_library>
<configuration_protocol> <configuration_protocol>
<organization type="scan_chain" circuit_model_name="DFFRQ" num_regions="1"/> <organization type="scan_chain" circuit_model_name="DFFRQ" num_regions="1"/>

View File

@ -63,7 +63,7 @@ wire [0:0] sky130_fd_sc_hd__or2_1_0_X;
.A(in[1]), .A(in[1]),
.Y(sky130_fd_sc_hd__inv_1_1_Y[0])); .Y(sky130_fd_sc_hd__inv_1_1_Y[0]));
assign arith_in2 = mode[0] ? in[2] : cin; assign arith_in2 = mode[0] ? cin : in[2];
sky130_fd_sc_hd__inv_1 sky130_fd_sc_hd__inv_1_2_ ( sky130_fd_sc_hd__inv_1 sky130_fd_sc_hd__inv_1_2_ (
.A(arith_in2), .A(arith_in2),
@ -82,7 +82,7 @@ wire [0:0] sky130_fd_sc_hd__or2_1_0_X;
.X(sky130_fd_sc_hd__buf_2_1_X[0])); .X(sky130_fd_sc_hd__buf_2_1_X[0]));
sky130_fd_sc_hd__buf_2 sky130_fd_sc_hd__buf_2_2_ ( sky130_fd_sc_hd__buf_2 sky130_fd_sc_hd__buf_2_2_ (
.A(in[2]), .A(arith_in2),
.X(sky130_fd_sc_hd__buf_2_2_X[0])); .X(sky130_fd_sc_hd__buf_2_2_X[0]));
sky130_fd_sc_hd__buf_2 sky130_fd_sc_hd__buf_2_3_ ( sky130_fd_sc_hd__buf_2 sky130_fd_sc_hd__buf_2_3_ (

View File

@ -99,6 +99,8 @@ parser.add_argument('--arch_variable_file', type=str, default=None,
# help="Key file for shell") # help="Key file for shell")
parser.add_argument('--yosys_tmpl', type=str, default=None, parser.add_argument('--yosys_tmpl', type=str, default=None,
help="Alternate yosys template, generates top_module.blif") help="Alternate yosys template, generates top_module.blif")
parser.add_argument('--ys_rewrite_tmpl', type=str, default=None,
help="Alternate yosys template, to rewrite verilog netlist")
parser.add_argument('--disp', action="store_true", parser.add_argument('--disp', action="store_true",
help="Open display while running VPR") help="Open display while running VPR")
parser.add_argument('--debug', action="store_true", parser.add_argument('--debug', action="store_true",
@ -260,7 +262,7 @@ def main():
if args.power: if args.power:
run_ace2() run_ace2()
run_pro_blif_3arg() run_pro_blif_3arg()
else: else:
# Make a copy of the blif file to be compatible with vpr flow # Make a copy of the blif file to be compatible with vpr flow
shutil.copy(args.top_module+'_yosys_out.blif', args.top_module+".blif") shutil.copy(args.top_module+'_yosys_out.blif', args.top_module+".blif")
@ -488,6 +490,7 @@ def run_yosys_with_abc():
"TOP_MODULE": args.top_module, "TOP_MODULE": args.top_module,
"LUT_SIZE": lut_size, "LUT_SIZE": lut_size,
"OUTPUT_BLIF": args.top_module+"_yosys_out.blif", "OUTPUT_BLIF": args.top_module+"_yosys_out.blif",
"OUTPUT_VERILOG": args.top_module+"_output_verilog.v"
} }
for indx in range(0, len(OpenFPGAArgs), 2): for indx in range(0, len(OpenFPGAArgs), 2):
@ -692,12 +695,41 @@ def extract_vpr_stats(logfile, r_filename="vpr_stat", parse_section="vpr"):
def run_rewrite_verilog(): def run_rewrite_verilog():
# Rewrite the verilog after optimization # Rewrite the verilog after optimization
script_cmd = [ # If there is no template script provided, use a default template
"read_blif %s" % args.top_module+".blif", # If there is a template script provided, replace parameters from configuration
"write_verilog %s" % args.top_module+"_output_verilog.v" if not args.ys_rewrite_tmpl:
] script_cmd = [
command = [cad_tools["yosys_path"], "-p", "; ".join(script_cmd)] "read_blif %s" % args.top_module+".blif",
run_command("Yosys", "yosys_rewrite.log", command) "write_verilog %s" % args.top_module+"_output_verilog.v"
]
command = [cad_tools["yosys_path"], "-p", "; ".join(script_cmd)]
run_command("Yosys", "yosys_rewrite.log", command)
else:
# Yosys script parameter mapping
ys_rewrite_params = {
"READ_VERILOG_FILE": " \n".join([
"read_verilog -nolatches " + shlex.quote(eachfile)
for eachfile in args.benchmark_files]),
"TOP_MODULE": args.top_module,
"OUTPUT_BLIF": args.top_module+"_yosys_out.blif",
"INPUT_BLIF": args.top_module+".blif",
"OUTPUT_VERILOG": args.top_module+"_output_verilog.v"
}
for indx in range(0, len(OpenFPGAArgs), 2):
tmpVar = OpenFPGAArgs[indx][2:].upper()
ys_rewrite_params[tmpVar] = OpenFPGAArgs[indx + 1]
# Split a series of scripts by delim ';'
# And execute the scripts serially
for iteration_idx, curr_rewrite_tmpl in enumerate(args.ys_rewrite_tmpl.split(";")):
tmpl = Template(open(curr_rewrite_tmpl, encoding='utf-8').read())
logger.info("Yosys rewrite iteration: " + str(iteration_idx))
with open("yosys_rewrite_" + str(iteration_idx) + ".ys", 'w') as archfile:
archfile.write(tmpl.safe_substitute(ys_rewrite_params))
run_command("Run yosys", "yosys_rewrite_output.log",
[cad_tools["yosys_path"], "yosys_rewrite_" + str(iteration_idx) + ".ys"])
def run_netlists_verification(exit_if_fail=True): def run_netlists_verification(exit_if_fail=True):

View File

@ -175,7 +175,7 @@ def generate_each_task_actions(taskname):
curr_task_dir = repo_tasks curr_task_dir = repo_tasks
else: else:
clean_up_and_exit("Task directory [%s] not found" % curr_task_dir) clean_up_and_exit("Task directory [%s] not found" % curr_task_dir)
os.chdir(curr_task_dir) os.chdir(curr_task_dir)
curr_task_conf_file = os.path.join(curr_task_dir, "config", "task.conf") curr_task_conf_file = os.path.join(curr_task_dir, "config", "task.conf")
@ -254,7 +254,11 @@ def generate_each_task_actions(taskname):
# Read provided benchmark configurations # Read provided benchmark configurations
# Common configurations # Common configurations
# - All the benchmarks may share the same yosys synthesis template script
# - All the benchmarks may share the same rewrite yosys template script, which converts post-synthesis .v netlist to be compatible with .blif port definition. This is required for correct verification at the end of flows
# - All the benchmarks may share the same routing channel width in VPR runs. This is designed to enable architecture evaluations for a fixed device model
ys_for_task_common = SynthSection.get("bench_yosys_common") ys_for_task_common = SynthSection.get("bench_yosys_common")
ys_rewrite_for_task_common = SynthSection.get("bench_yosys_rewrite_common")
chan_width_common = SynthSection.get("bench_chan_width_common") chan_width_common = SynthSection.get("bench_chan_width_common")
# Individual benchmark configuration # Individual benchmark configuration
@ -263,6 +267,8 @@ def generate_each_task_actions(taskname):
fallback="top") fallback="top")
CurrBenchPara["ys_script"] = SynthSection.get(bech_name+"_yosys", CurrBenchPara["ys_script"] = SynthSection.get(bech_name+"_yosys",
fallback=ys_for_task_common) fallback=ys_for_task_common)
CurrBenchPara["ys_rewrite_script"] = SynthSection.get(bech_name+"_yosys_rewrite",
fallback=ys_rewrite_for_task_common)
CurrBenchPara["chan_width"] = SynthSection.get(bech_name+"_chan_width", CurrBenchPara["chan_width"] = SynthSection.get(bech_name+"_chan_width",
fallback=chan_width_common) fallback=chan_width_common)
@ -381,6 +387,9 @@ def create_run_command(curr_job_dir, archfile, benchmark_obj, param, task_conf):
if benchmark_obj.get("ys_script"): if benchmark_obj.get("ys_script"):
command += ["--yosys_tmpl", benchmark_obj["ys_script"]] command += ["--yosys_tmpl", benchmark_obj["ys_script"]]
if benchmark_obj.get("ys_rewrite_script"):
command += ["--ys_rewrite_tmpl", benchmark_obj["ys_rewrite_script"]]
if task_gc.getboolean("power_analysis"): if task_gc.getboolean("power_analysis"):
command += ["--power"] command += ["--power"]
command += ["--power_tech", task_gc.get("power_tech_file")] command += ["--power_tech", task_gc.get("power_tech_file")]

View File

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

View File

@ -30,13 +30,15 @@ arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_frac_N8_tileable_reset_sof
bench1=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/adder_8/adder_8.v bench1=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/adder_8/adder_8.v
[SYNTHESIS_PARAM] [SYNTHESIS_PARAM]
bench_yosys_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/qlf_yosys.ys
bench_yosys_rewrite_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_flow_with_rewrite.ys;${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_rewrite_flow.ys
bench1_top = adder_8 bench1_top = adder_8
bench1_yosys=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/qlf_yosys.ys
[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] [SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH]
########################## ##########################
# The output verilog of yosys is not synthesizable!!! # The output verilog of yosys is not synthesizable!!!
# Turn off verification for now # Turn off verification for now
# SHOULD focus on fixing the Verilog problem and run verification at the end of the flow # SHOULD focus on fixing the Verilog problem and run verification at the end of the flow
#end_flow_with_test= end_flow_with_test=
#vpr_fpga_verilog_formal_verification_top_netlist= vpr_fpga_verilog_formal_verification_top_netlist=