Merge branch 'master' into netlist_name_patch
This commit is contained in:
commit
87006e1374
|
@ -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.
|
||||
|
||||
.. _annotate_vpr_arch_pb_type_annotation:
|
||||
|
||||
Primitive Blocks inside Multi-mode Configurable Logic Blocks
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ This can define a hard-coded bitstream for a reconfigurable resource in FPGA fab
|
|||
.. code-block:: xml
|
||||
|
||||
<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>
|
||||
|
||||
.. 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).
|
||||
|
||||
.. 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.
|
||||
|
||||
|
|
|
@ -51,6 +51,17 @@ std::string BitstreamSetting::pb_type_bitstream_content(const BitstreamPbTypeSet
|
|||
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
|
||||
***********************************************************************/
|
||||
|
@ -66,10 +77,24 @@ BitstreamPbTypeSettingId BitstreamSetting::add_bitstream_pb_type_setting(const s
|
|||
parent_mode_names_.push_back(parent_mode_names);
|
||||
pb_type_bitstream_sources_.push_back(bitstream_source);
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
***********************************************************************/
|
||||
|
|
|
@ -39,12 +39,18 @@ class BitstreamSetting {
|
|||
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;
|
||||
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 */
|
||||
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);
|
||||
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 */
|
||||
bool valid_bitstream_pb_type_setting_id(const BitstreamPbTypeSettingId& pb_type_setting_id) const;
|
||||
private: /* Internal data */
|
||||
|
@ -54,6 +60,10 @@ class BitstreamSetting {
|
|||
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_;
|
||||
/* 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 */
|
||||
|
|
|
@ -36,11 +36,18 @@ void read_xml_bitstream_pb_type_setting(pugi::xml_node& xml_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);
|
||||
BitstreamPbTypeSettingId bitstream_pb_type_id = bitstream_setting.add_bitstream_pb_type_setting(operating_pb_parser.leaf(),
|
||||
operating_pb_parser.parents(),
|
||||
operating_pb_parser.modes(),
|
||||
source_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);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
|
|
|
@ -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, "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";
|
||||
}
|
||||
|
|
|
@ -56,17 +56,30 @@ int annotate_bitstream_setting(const BitstreamSetting& bitstream_setting,
|
|||
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 {
|
||||
if (std::string("eblif") != bitstream_setting.pb_type_bitstream_source(bitstream_pb_type_setting_id)) {
|
||||
/* 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));
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
|
|
@ -38,6 +38,46 @@ std::string VprBitstreamAnnotation::pb_type_bitstream_content(t_pb_type* pb_type
|
|||
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
|
||||
***********************************************************************/
|
||||
|
@ -45,10 +85,30 @@ 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;
|
||||
}
|
||||
|
||||
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*/
|
||||
|
|
|
@ -33,16 +33,41 @@ class 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;
|
||||
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 */
|
||||
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);
|
||||
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 */
|
||||
/* For regular bitstreams */
|
||||
/* 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_;
|
||||
/* 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*/
|
||||
|
|
|
@ -448,18 +448,18 @@ void build_lut_bitstream(BitstreamManager& bitstream_manager,
|
|||
/* 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);
|
||||
size_t start_index = physical_pb.fixed_bitstream_offset(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",
|
||||
if (lut_bitstream.size() - start_index < fixed_bitstream.size()) {
|
||||
VTR_LOG_ERROR("Unmatched length of fixed bitstream %s!Expected to be less than %ld bits\n",
|
||||
fixed_bitstream.c_str(),
|
||||
lut_bitstream.size());
|
||||
lut_bitstream.size() - start_index);
|
||||
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);
|
||||
/* Overload the bitstream here */
|
||||
for (size_t bit_index = 0; bit_index < lut_bitstream.size(); ++bit_index) {
|
||||
VTR_ASSERT('0' == fixed_bitstream[bit_index] || '1' == fixed_bitstream[bit_index]);
|
||||
lut_bitstream[bit_index + start_index] = ('1' == fixed_bitstream[bit_index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -469,9 +469,29 @@ void build_lut_bitstream(BitstreamManager& bitstream_manager,
|
|||
std::vector<bool> mode_select_bitstream;
|
||||
if (true == physical_pb.valid_pb_id(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 */
|
||||
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 */
|
||||
for (const bool& bit : mode_select_bitstream) {
|
||||
lut_bitstream.push_back(bit);
|
||||
|
|
|
@ -107,6 +107,21 @@ std::string PhysicalPb::fixed_bitstream(const PhysicalPbId& pb) const {
|
|||
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
|
||||
******************************************************************************/
|
||||
|
@ -133,7 +148,11 @@ PhysicalPbId PhysicalPb::create_pb(const t_pb_graph_node* pb_graph_node) {
|
|||
|
||||
truth_tables_.emplace_back();
|
||||
mode_bits_.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 */
|
||||
type2id_map_[pb_graph_node] = pb;
|
||||
|
@ -218,6 +237,24 @@ void PhysicalPb::set_fixed_bitstream(const PhysicalPbId& pb,
|
|||
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
|
||||
******************************************************************************/
|
||||
|
|
|
@ -55,6 +55,9 @@ class PhysicalPb {
|
|||
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;
|
||||
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 */
|
||||
PhysicalPbId create_pb(const t_pb_graph_node* pb_graph_node);
|
||||
void add_child(const PhysicalPbId& parent,
|
||||
|
@ -75,6 +78,12 @@ class PhysicalPb {
|
|||
const bool& wire_lut_output);
|
||||
void set_fixed_bitstream(const PhysicalPbId& pb,
|
||||
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 */
|
||||
bool valid_pb_id(const PhysicalPbId& pb_id) const;
|
||||
bool empty() const;
|
||||
|
@ -98,6 +107,10 @@ class PhysicalPb {
|
|||
vtr::vector<PhysicalPbId, std::vector<size_t>> mode_bits_;
|
||||
|
||||
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 */
|
||||
std::map<const t_pb_graph_node*, PhysicalPbId> type2id_map_;
|
||||
|
|
|
@ -304,7 +304,7 @@ 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
|
||||
*/
|
||||
|
@ -313,17 +313,55 @@ void rec_update_physical_pb_from_operating_pb(PhysicalPb& phy_pb,
|
|||
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)) {
|
||||
if (param_search.first == tokens[1]) {
|
||||
phy_pb.set_fixed_bitstream(physical_pb, param_search.second);
|
||||
}
|
||||
/* Bypass unmatched parameter identifier */
|
||||
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]) {
|
||||
for (const auto& attr_search : atom_ctx.nlist.block_attrs(atom_blk)) {
|
||||
/* Bypass unmatched parameter identifier */
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,4 +4,4 @@ ${READ_VERILOG_FILE}
|
|||
|
||||
synth_quicklogic -blif ${OUTPUT_BLIF} -top ${TOP_MODULE} ${YOSYS_ARGS}
|
||||
|
||||
write_verilog -noattr -nohex ${TOP_MODULE}.v
|
||||
write_verilog -noattr -nohex ${OUTPUT_VERILOG}
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
# Rewrite the .blif to Verilog
|
||||
# so that the pin sequence matches
|
||||
read_blif rewritten_${OUTPUT_BLIF}
|
||||
write_verilog ${OUTPUT_VERILOG}
|
|
@ -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}
|
|
@ -206,9 +206,9 @@
|
|||
<!-- 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
|
||||
-->
|
||||
<!--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"/>
|
||||
</circuit_model-->
|
||||
</circuit_model -->
|
||||
</circuit_library>
|
||||
<configuration_protocol>
|
||||
<organization type="scan_chain" circuit_model_name="DFFRQ" num_regions="1"/>
|
||||
|
|
|
@ -63,7 +63,7 @@ wire [0:0] sky130_fd_sc_hd__or2_1_0_X;
|
|||
.A(in[1]),
|
||||
.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_ (
|
||||
.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]));
|
||||
|
||||
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]));
|
||||
|
||||
sky130_fd_sc_hd__buf_2 sky130_fd_sc_hd__buf_2_3_ (
|
||||
|
|
|
@ -99,6 +99,8 @@ parser.add_argument('--arch_variable_file', type=str, default=None,
|
|||
# help="Key file for shell")
|
||||
parser.add_argument('--yosys_tmpl', type=str, default=None,
|
||||
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",
|
||||
help="Open display while running VPR")
|
||||
parser.add_argument('--debug', action="store_true",
|
||||
|
@ -260,7 +262,7 @@ def main():
|
|||
if args.power:
|
||||
run_ace2()
|
||||
run_pro_blif_3arg()
|
||||
else:
|
||||
else:
|
||||
# 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")
|
||||
|
||||
|
@ -488,6 +490,7 @@ def run_yosys_with_abc():
|
|||
"TOP_MODULE": args.top_module,
|
||||
"LUT_SIZE": lut_size,
|
||||
"OUTPUT_BLIF": args.top_module+"_yosys_out.blif",
|
||||
"OUTPUT_VERILOG": args.top_module+"_output_verilog.v"
|
||||
}
|
||||
|
||||
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():
|
||||
# Rewrite the verilog after optimization
|
||||
script_cmd = [
|
||||
"read_blif %s" % args.top_module+".blif",
|
||||
"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)
|
||||
# If there is no template script provided, use a default template
|
||||
# If there is a template script provided, replace parameters from configuration
|
||||
if not args.ys_rewrite_tmpl:
|
||||
script_cmd = [
|
||||
"read_blif %s" % args.top_module+".blif",
|
||||
"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):
|
||||
|
|
|
@ -175,7 +175,7 @@ def generate_each_task_actions(taskname):
|
|||
curr_task_dir = repo_tasks
|
||||
else:
|
||||
clean_up_and_exit("Task directory [%s] not found" % curr_task_dir)
|
||||
|
||||
|
||||
os.chdir(curr_task_dir)
|
||||
|
||||
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
|
||||
# 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_rewrite_for_task_common = SynthSection.get("bench_yosys_rewrite_common")
|
||||
chan_width_common = SynthSection.get("bench_chan_width_common")
|
||||
|
||||
# Individual benchmark configuration
|
||||
|
@ -263,6 +267,8 @@ def generate_each_task_actions(taskname):
|
|||
fallback="top")
|
||||
CurrBenchPara["ys_script"] = SynthSection.get(bech_name+"_yosys",
|
||||
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",
|
||||
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"):
|
||||
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"):
|
||||
command += ["--power"]
|
||||
command += ["--power_tech", task_gc.get("power_tech_file")]
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
<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 IN2_IS_CIN" is_mode_select_bitstream="true" bitstream_offset="0"/>
|
||||
</openfpga_bitstream_setting>
|
||||
|
|
|
@ -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
|
||||
|
||||
[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_yosys=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/qlf_yosys.ys
|
||||
|
||||
[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH]
|
||||
##########################
|
||||
# The output verilog of yosys is not synthesizable!!!
|
||||
# Turn off verification for now
|
||||
# SHOULD focus on fixing the Verilog problem and run verification at the end of the flow
|
||||
#end_flow_with_test=
|
||||
#vpr_fpga_verilog_formal_verification_top_netlist=
|
||||
end_flow_with_test=
|
||||
vpr_fpga_verilog_formal_verification_top_netlist=
|
||||
|
|
Loading…
Reference in New Issue