Merge branch 'refactoring' into dev
This commit is contained in:
commit
de38e8ecd9
|
@ -265,24 +265,54 @@
|
|||
<routing_segment>
|
||||
<segment name="L4" circuit_model_name="chan_segment"/>
|
||||
</routing_segment>
|
||||
<!--direct_connection>
|
||||
<direct_connection>
|
||||
<direct name="adder" circuit_model_name="direct_interc"/>
|
||||
</direct_connection-->
|
||||
<complex_blocks>
|
||||
<pb_type name="io" physical_mode_name="io_phy"/>
|
||||
<mode name="io[io_phy]" disable_in_packing="true"/>
|
||||
</direct_connection>
|
||||
<pb_type_annotations>
|
||||
<!-- physical pb_type binding in complex block IO -->
|
||||
<pb_type name="io" physical_mode_name="io_phy" idle_mode_name="inpad"/>
|
||||
<pb_type name="io[io_phy].iopad" circuit_model_name="iopad" mode_bits="1"/>
|
||||
<pb_type name="io[io_phy].inpad" physical_pb_type_name="iopad" mode_bits="1"/>
|
||||
<pb_type name="io[io_phy].outpad" physical_pb_type_name="iopad" mode_bits="0"/>
|
||||
<pb_type name="io[inpad].inpad" physical_pb_type_name="iopad" mode_bits="1"/>
|
||||
<pb_type name="io[outpad].outpad" physical_pb_type_name="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">
|
||||
<!-- Binding interconnect to circuit models as their physical implementation, if not defined, we use the default model -->
|
||||
<interconnect name="crossbar0" circuit_model_name="mux_2level"/>
|
||||
<interconnect name="crossbar1" circuit_model_name="mux_2level"/>
|
||||
<interconnect name="crossbar2" circuit_model_name="mux_2level"/>
|
||||
<interconnect name="crossbar3" circuit_model_name="mux_2level"/>
|
||||
<interconnect name="crossbar4" circuit_model_name="mux_2level"/>
|
||||
<interconnect name="crossbar5" circuit_model_name="mux_2level"/>
|
||||
</pb_type>
|
||||
<pb_type name="clb.fle" physical_mode_name="fle_phy" idle_mode_name="n2_lut5"/>
|
||||
<pb_type name="clb.fle[fle_phy].frac_logic.frac_lut6" mode_bits="11" circuit_model_name="frac_lut6"/>
|
||||
<pb_type name="clb.fle[fle_phy].frac_logic.adder_phy" circuit_model_name="adder"/>
|
||||
<pb_type name="clb.fle[fle_phy].frac_logic.ff_phy" circuit_model_name="static_dff"/>
|
||||
<mode name="fle_phy" disabled_in_packing="true"/>
|
||||
<pb_type name="lut5" mode_bits="01" physical_pb_type_name="frac_lut6" physical_pb_type_index_factor="0.5"/>
|
||||
<input name="in" physical_mode_pin="in[5:0]"/>
|
||||
<output name="out" physical_mode_pin="lut5_out" physical_mode_pin_rotate_offset="1"/>
|
||||
</complex_blocks>
|
||||
<pb_type name="clb.fle[n2_lut5].lut5_inter.ble5[blut5].flut5.lut5" mode_bits="01" physical_pb_type_name="clb.fle[fle_phy].frac_logic.frac_lut6" physical_pb_type_index_factor="0.5">
|
||||
<!-- If not specified, we by default assume the physical mode pin share the same name -->
|
||||
<port name="in" physical_mode_port="in[4:0]"/>
|
||||
<port name="out" physical_mode_port="lut5_out" physical_mode_pin_rotate_offset="1"/>
|
||||
</pb_type>
|
||||
<pb_type name="clb.fle[n2_lut5].lut5_inter.ble5[blut5].flut5.ff" physical_pb_type_name="clb.fle[fle_phy].frac_logic.ff_phy"/>
|
||||
<pb_type name="clb.fle[n2_lut5].lut5_inter.ble5[arithmetic].arithemetic.lut4" mode_bits="11" physical_pb_type_name="clb.fle[fle_phy].frac_logic.frac_lut6">
|
||||
<!-- If not specified, we by default assume the physical mode pin share the same name -->
|
||||
<port name="in" physical_mode_port="in[3:0]"/>
|
||||
<port name="out" physical_mode_port="lut4_out" physical_mode_pin_rotate_offset="1"/>
|
||||
</pb_type>
|
||||
<pb_type name="clb.fle[n2_lut5].lut5_inter.ble5[arithmetic].arithemetic.adder" physical_pb_type_name="clb.fle[fle_phy].frac_logic.adder_phy"/>
|
||||
<pb_type name="clb.fle[n2_lut5].lut5_inter.ble5[arithmetic].arithemetic.ff" physical_pb_type_name="clb.fle[fle_phy].frac_logic.ff_phy"/>
|
||||
<pb_type name="clb.fle[n1_lut6].ble6.lut6" mode_bits="00" physical_pb_type_name="clb.fle[fle_phy].frac_logic.frac_lut6">
|
||||
<!-- If not specified, we by default assume the physical mode pin share the same name -->
|
||||
<port name="in" physical_mode_port="in[5:0]"/>
|
||||
<port name="out" physical_mode_port="lut6_out"/>
|
||||
</pb_type>
|
||||
<pb_type name="clb.fle[n1_lut6].ble6.ff" physical_pb_type_name="clb.fle[fle_phy].frac_logic.ff_phy" physical_pb_type_index_factor="2" physical_pb_type_index_offset="1"/>
|
||||
<pb_type name="clb.fle[shift_register].ble6_shift.ff" physical_pb_type_name="clb.fle[fle_phy].frac_logic.ff_phy"/>
|
||||
<!-- End physical pb_type binding in complex block IO -->
|
||||
</pb_type_annotations>
|
||||
</openfpga_architecture>
|
||||
<openfpga_simulation_setting>
|
||||
<clock_setting>
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
#ifndef OPENFPGA_ARCH_H
|
||||
#define OPENFPGA_ARCH_H
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include "circuit_library.h"
|
||||
#include "technology_library.h"
|
||||
#include "simulation_setting.h"
|
||||
#include "config_protocol.h"
|
||||
#include "pb_type_annotation.h"
|
||||
|
||||
/* namespace openfpga begins */
|
||||
namespace openfpga {
|
||||
|
@ -47,6 +49,12 @@ struct Arch {
|
|||
* to circuit models in circuit library
|
||||
*/
|
||||
std::map<std::string, CircuitModelId> direct2circuit;
|
||||
|
||||
/* Pb type annotations
|
||||
* Bind from operating to physical
|
||||
* Bind from physical to circuit model
|
||||
*/
|
||||
std::vector<PbTypeAnnotation> pb_type_annotations;
|
||||
};
|
||||
|
||||
} /* namespace openfpga ends */
|
||||
|
|
|
@ -0,0 +1,215 @@
|
|||
/************************************************************************
|
||||
* Member functions for class PbTypeAnnotation
|
||||
***********************************************************************/
|
||||
#include "vtr_log.h"
|
||||
#include "vtr_assert.h"
|
||||
#include "pb_type_annotation.h"
|
||||
|
||||
/* namespace openfpga begins */
|
||||
namespace openfpga {
|
||||
|
||||
/************************************************************************
|
||||
* Constructors
|
||||
***********************************************************************/
|
||||
PbTypeAnnotation::PbTypeAnnotation() {
|
||||
return;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Public Accessors
|
||||
***********************************************************************/
|
||||
std::string PbTypeAnnotation::operating_pb_type_name() const {
|
||||
return operating_pb_type_name_;
|
||||
}
|
||||
|
||||
std::vector<std::string> PbTypeAnnotation::operating_parent_pb_type_names() const {
|
||||
return operating_parent_pb_type_names_;
|
||||
}
|
||||
|
||||
std::vector<std::string> PbTypeAnnotation::operating_parent_mode_names() const {
|
||||
return operating_parent_mode_names_;
|
||||
}
|
||||
|
||||
bool PbTypeAnnotation::is_operating_pb_type() const {
|
||||
return (false == operating_pb_type_name_.empty())
|
||||
&& (false == physical_pb_type_name_.empty());
|
||||
}
|
||||
|
||||
|
||||
std::string PbTypeAnnotation::physical_pb_type_name() const {
|
||||
return physical_pb_type_name_;
|
||||
}
|
||||
|
||||
std::vector<std::string> PbTypeAnnotation::physical_parent_pb_type_names() const {
|
||||
return physical_parent_pb_type_names_;
|
||||
}
|
||||
|
||||
std::vector<std::string> PbTypeAnnotation::physical_parent_mode_names() const {
|
||||
return physical_parent_mode_names_;
|
||||
}
|
||||
|
||||
bool PbTypeAnnotation::is_physical_pb_type() const {
|
||||
return (true == operating_pb_type_name_.empty())
|
||||
&& (false == physical_pb_type_name_.empty());
|
||||
}
|
||||
|
||||
std::string PbTypeAnnotation::physical_mode_name() const {
|
||||
return physical_mode_name_;
|
||||
}
|
||||
|
||||
std::string PbTypeAnnotation::idle_mode_name() const {
|
||||
return idle_mode_name_;
|
||||
}
|
||||
|
||||
std::string PbTypeAnnotation::mode_bits() const {
|
||||
return mode_bits_;
|
||||
}
|
||||
|
||||
std::string PbTypeAnnotation::circuit_model_name() const {
|
||||
return circuit_model_name_;
|
||||
}
|
||||
|
||||
int PbTypeAnnotation::physical_pb_type_index_factor() const {
|
||||
return physical_pb_type_index_factor_;
|
||||
}
|
||||
|
||||
int PbTypeAnnotation::physical_pb_type_index_offset() const {
|
||||
return physical_pb_type_index_offset_;
|
||||
}
|
||||
|
||||
std::vector<std::string> PbTypeAnnotation::port_names() const {
|
||||
std::vector<std::string> keys;
|
||||
for (auto const& element : operating_pb_type_ports_) {
|
||||
keys.push_back(element.first);
|
||||
}
|
||||
return keys;
|
||||
}
|
||||
|
||||
BasicPort PbTypeAnnotation::physical_pb_type_port(const std::string& port_name) const {
|
||||
std::map<std::string, BasicPort>::const_iterator it = operating_pb_type_ports_.find(port_name);
|
||||
if (it == operating_pb_type_ports_.end()) {
|
||||
/* Return an empty port */
|
||||
return BasicPort();
|
||||
}
|
||||
return operating_pb_type_ports_.at(port_name);
|
||||
}
|
||||
|
||||
int PbTypeAnnotation::physical_pin_rotate_offset(const std::string& port_name) const {
|
||||
std::map<std::string, int>::const_iterator it = physical_pin_rotate_offsets_.find(port_name);
|
||||
if (it == physical_pin_rotate_offsets_.end()) {
|
||||
/* Return a zero offset which is default */
|
||||
return 0;
|
||||
}
|
||||
return physical_pin_rotate_offsets_.at(port_name);
|
||||
}
|
||||
|
||||
std::vector<std::string> PbTypeAnnotation::interconnect_names() const {
|
||||
std::vector<std::string> keys;
|
||||
for (auto const& element : interconnect_circuit_model_names_) {
|
||||
keys.push_back(element.first);
|
||||
}
|
||||
return keys;
|
||||
}
|
||||
|
||||
std::string PbTypeAnnotation::interconnect_circuit_model_name(const std::string& interc_name) const {
|
||||
std::map<std::string, std::string>::const_iterator it = interconnect_circuit_model_names_.find(interc_name);
|
||||
if (it == interconnect_circuit_model_names_.end()) {
|
||||
return std::string();
|
||||
}
|
||||
|
||||
return interconnect_circuit_model_names_.at(interc_name);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Public Mutators
|
||||
***********************************************************************/
|
||||
void PbTypeAnnotation::set_operating_pb_type_name(const std::string& name) {
|
||||
operating_pb_type_name_ = name;
|
||||
}
|
||||
|
||||
void PbTypeAnnotation::set_operating_parent_pb_type_names(const std::vector<std::string>& names) {
|
||||
operating_parent_pb_type_names_ = names;
|
||||
}
|
||||
|
||||
void PbTypeAnnotation::set_operating_parent_mode_names(const std::vector<std::string>& names) {
|
||||
operating_parent_mode_names_ = names;
|
||||
}
|
||||
|
||||
void PbTypeAnnotation::set_physical_pb_type_name(const std::string& name) {
|
||||
physical_pb_type_name_ = name;
|
||||
}
|
||||
|
||||
void PbTypeAnnotation::set_physical_parent_pb_type_names(const std::vector<std::string>& names) {
|
||||
physical_parent_pb_type_names_ = names;
|
||||
}
|
||||
|
||||
void PbTypeAnnotation::set_physical_parent_mode_names(const std::vector<std::string>& names) {
|
||||
physical_parent_mode_names_ = names;
|
||||
}
|
||||
|
||||
void PbTypeAnnotation::set_physical_mode_name(const std::string& name) {
|
||||
physical_mode_name_ = name;
|
||||
}
|
||||
|
||||
void PbTypeAnnotation::set_idle_mode_name(const std::string& name) {
|
||||
idle_mode_name_ = name;
|
||||
}
|
||||
|
||||
void PbTypeAnnotation::set_mode_bits(const std::string& mode_bits) {
|
||||
mode_bits_ = mode_bits;
|
||||
}
|
||||
|
||||
void PbTypeAnnotation::set_circuit_model_name(const std::string& name) {
|
||||
VTR_ASSERT(true == is_physical_pb_type());
|
||||
circuit_model_name_ = name;
|
||||
}
|
||||
|
||||
void PbTypeAnnotation::set_physical_pb_type_index_factor(const int& value) {
|
||||
VTR_ASSERT(true == is_operating_pb_type());
|
||||
physical_pb_type_index_factor_ = value;
|
||||
}
|
||||
|
||||
void PbTypeAnnotation::set_physical_pb_type_index_offset(const int& value) {
|
||||
VTR_ASSERT(true == is_operating_pb_type());
|
||||
physical_pb_type_index_offset_ = value;
|
||||
}
|
||||
|
||||
void PbTypeAnnotation::add_pb_type_port_pair(const std::string& operating_pb_port_name,
|
||||
const BasicPort& physical_pb_port) {
|
||||
/* Give a warning if the operating_pb_port_name already exist */
|
||||
std::map<std::string, BasicPort>::const_iterator it = operating_pb_type_ports_.find(operating_pb_port_name);
|
||||
/* Give a warning if the interconnection name already exist */
|
||||
if (it != operating_pb_type_ports_.end()) {
|
||||
VTR_LOG_WARN("Redefine operating pb type port '%s' with physical pb type port '%s'\n",
|
||||
operating_pb_port_name.c_str(), physical_pb_port.get_name().c_str());
|
||||
}
|
||||
|
||||
operating_pb_type_ports_[operating_pb_port_name] = physical_pb_port;
|
||||
}
|
||||
|
||||
void PbTypeAnnotation::set_physical_pin_rotate_offset(const std::string& operating_pb_port_name,
|
||||
const int& physical_pin_rotate_offset) {
|
||||
std::map<std::string, BasicPort>::const_iterator it = operating_pb_type_ports_.find(operating_pb_port_name);
|
||||
/* Give a warning if the interconnection name already exist */
|
||||
if (it == operating_pb_type_ports_.end()) {
|
||||
VTR_LOG_ERROR("Operating pb type port '%s' does not exist! Ignore physical pin rotate offset '%d'\n",
|
||||
operating_pb_port_name.c_str(), physical_pin_rotate_offset);
|
||||
return;
|
||||
}
|
||||
|
||||
physical_pin_rotate_offsets_[operating_pb_port_name] = physical_pin_rotate_offset;
|
||||
}
|
||||
|
||||
void PbTypeAnnotation::add_interconnect_circuit_model_pair(const std::string& interc_name,
|
||||
const std::string& circuit_model_name) {
|
||||
std::map<std::string, std::string>::const_iterator it = interconnect_circuit_model_names_.find(interc_name);
|
||||
/* Give a warning if the interconnection name already exist */
|
||||
if (it != interconnect_circuit_model_names_.end()) {
|
||||
VTR_LOG_WARN("Redefine interconnect '%s' with circuit model '%s'\n",
|
||||
interc_name.c_str(), circuit_model_name.c_str());
|
||||
}
|
||||
|
||||
interconnect_circuit_model_names_[interc_name] = circuit_model_name;
|
||||
}
|
||||
|
||||
} /* namespace openfpga ends */
|
|
@ -0,0 +1,160 @@
|
|||
#ifndef PB_TYPE_ANNOTATION_H
|
||||
#define PB_TYPE_ANNOTATION_H
|
||||
|
||||
/********************************************************************
|
||||
* Include header files required by the data structure definition
|
||||
*******************************************************************/
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include "openfpga_port.h"
|
||||
|
||||
/* namespace openfpga begins */
|
||||
namespace openfpga {
|
||||
|
||||
/********************************************************************
|
||||
* This file include the declaration of data structures
|
||||
* to store physical pb_type annotation, including
|
||||
* 1. the binding between operating pb_type and physical_pb_type
|
||||
* this also cover the binding between pins of any pair of pb_types
|
||||
* 2. the binding between physical pb_type and circuit models
|
||||
* 3. the binding between interconnect under pb_types and circuit models
|
||||
* This is only applicable to physical pb_types
|
||||
*
|
||||
* Each PhysicalPbAnnotation includes the binding for ONLY a pb_type
|
||||
* defined in the architecture XML
|
||||
*
|
||||
* Note:
|
||||
* 1. Keep this data structure as general as possible. It is supposed
|
||||
* to contain the raw data from architecture XML! If you want to link
|
||||
* to other data structures, please create another one in other header files
|
||||
*******************************************************************/
|
||||
class PbTypeAnnotation {
|
||||
public: /* Constructor */
|
||||
PbTypeAnnotation();
|
||||
public: /* Public accessors */
|
||||
std::string operating_pb_type_name() const;
|
||||
std::vector<std::string> operating_parent_pb_type_names() const;
|
||||
std::vector<std::string> operating_parent_mode_names() const;
|
||||
bool is_operating_pb_type() const;
|
||||
std::string physical_pb_type_name() const;
|
||||
std::vector<std::string> physical_parent_pb_type_names() const;
|
||||
std::vector<std::string> physical_parent_mode_names() const;
|
||||
bool is_physical_pb_type() const;
|
||||
std::string physical_mode_name() const;
|
||||
std::string idle_mode_name() const;
|
||||
std::string mode_bits() const;
|
||||
std::string circuit_model_name() const;
|
||||
int physical_pb_type_index_factor() const;
|
||||
int physical_pb_type_index_offset() const;
|
||||
std::vector<std::string> port_names() const;
|
||||
BasicPort physical_pb_type_port(const std::string& port_name) const;
|
||||
int physical_pin_rotate_offset(const std::string& port_name) const;
|
||||
std::vector<std::string> interconnect_names() const;
|
||||
std::string interconnect_circuit_model_name(const std::string& interc_name) const;
|
||||
public: /* Public mutators */
|
||||
void set_operating_pb_type_name(const std::string& name);
|
||||
void set_operating_parent_pb_type_names(const std::vector<std::string>& names);
|
||||
void set_operating_parent_mode_names(const std::vector<std::string>& names);
|
||||
void set_physical_pb_type_name(const std::string& name);
|
||||
void set_physical_parent_pb_type_names(const std::vector<std::string>& names);
|
||||
void set_physical_parent_mode_names(const std::vector<std::string>& names);
|
||||
void set_physical_mode_name(const std::string& name);
|
||||
void set_idle_mode_name(const std::string& name);
|
||||
void set_mode_bits(const std::string& mode_bits);
|
||||
void set_circuit_model_name(const std::string& name);
|
||||
void set_physical_pb_type_index_factor(const int& value);
|
||||
void set_physical_pb_type_index_offset(const int& value);
|
||||
void add_pb_type_port_pair(const std::string& operating_pb_port_name,
|
||||
const BasicPort& physical_pb_port);
|
||||
void set_physical_pin_rotate_offset(const std::string& operating_pb_port_name,
|
||||
const int& physical_pin_rotate_offset);
|
||||
void add_interconnect_circuit_model_pair(const std::string& interc_name,
|
||||
const std::string& circuit_model_name);
|
||||
private: /* Internal data */
|
||||
/* Binding between physical pb_type and operating pb_type
|
||||
* both operating and physial pb_type names contain the full names
|
||||
* defined in the hierarchy of pb_types
|
||||
* e.g.
|
||||
* clb.fle[frac_logic].frac_lut6
|
||||
* ^
|
||||
* |
|
||||
* mode_name
|
||||
*
|
||||
* The pb_type name 'frac_lut6' will be stored in
|
||||
* either operating or physical pb_type_name
|
||||
* The parent pb_type and mode names will be stored in
|
||||
* either operating or physical parent_pb_type_name and parent_mode_names
|
||||
*
|
||||
*/
|
||||
std::string operating_pb_type_name_;
|
||||
std::vector<std::string> operating_parent_pb_type_names_;
|
||||
std::vector<std::string> operating_parent_mode_names_;
|
||||
|
||||
std::string physical_pb_type_name_;
|
||||
std::vector<std::string> physical_parent_pb_type_names_;
|
||||
std::vector<std::string> physical_parent_mode_names_;
|
||||
|
||||
/* Identify which mode is the physical implementation of an operating pb_type */
|
||||
std::string physical_mode_name_;
|
||||
|
||||
/* Identify in which mode is the pb_type will operate when it is not used */
|
||||
std::string idle_mode_name_;
|
||||
|
||||
/* Configuration bits to select an operting mode for the circuit mode name */
|
||||
std::string mode_bits_;
|
||||
|
||||
/* Circuit mode name linked to a physical pb_type.
|
||||
* This is only applicable to the physical pb_type
|
||||
*/
|
||||
std::string circuit_model_name_;
|
||||
|
||||
/* The factor aims to align the indices for pb_type between operating and physical modes,
|
||||
* especially when an operating mode contains multiple pb_type (num_pb>1)
|
||||
* that are linked to the same physical pb_type.
|
||||
* When number of physical_pb_type is larger than 1,
|
||||
* the index of pb_type will be multipled by the given factor.
|
||||
*
|
||||
* For example, a factor of 2 is used to map
|
||||
* operating pb_type adder[5] with a full path clb.fle[arith].adder[5]
|
||||
* to physical pb_type adder[10] with a full path clb.fle[physical].adder[10]
|
||||
*/
|
||||
int physical_pb_type_index_factor_;
|
||||
|
||||
/* The offset aims to align the indices for pb_type between operating and physical modes,
|
||||
* especially when an operating mode contains multiple pb_type (num_pb>1)
|
||||
* that are linked to the same physical pb_type.
|
||||
* When number of physical_pb_type is larger than 1,
|
||||
* the index of pb_type will be shifted by the given factor.
|
||||
*
|
||||
* For example, an offset of 1 is used to map
|
||||
* operating pb_type adder[0] with a full path clb.fle[arith].adder[0]
|
||||
* to physical pb_type adder[1] with a full path clb.fle[physical].adder[1]
|
||||
*/
|
||||
int physical_pb_type_index_offset_;
|
||||
|
||||
/* Link from the pins under an operating pb_type to physical pb_type */
|
||||
std::map<std::string, BasicPort> operating_pb_type_ports_;
|
||||
|
||||
/* The offset aims to align the pin indices for port of pb_type
|
||||
* between operating and physical modes, especially when an operating
|
||||
* mode contains multiple pb_type (num_pb>1) that are linked to
|
||||
* the same physical pb_type.
|
||||
* When physical_mode_pin_rotate_offset is larger than zero,
|
||||
* the pin index of pb_type (whose index is large than 1)
|
||||
* will be shifted by the given offset.
|
||||
*
|
||||
* For example, an offset of 1 is used to map
|
||||
* operating pb_type adder[0].pin[0] with a full path clb.fle[arith].adder[0]
|
||||
* to physical pb_type adder[0].pin[1] with a full path clb.fle[physical].adder[0]
|
||||
*/
|
||||
std::map<std::string, int> physical_pin_rotate_offsets_;
|
||||
|
||||
/* Link between the interconnects under this pb_type and circuit model names */
|
||||
std::map<std::string, std::string> interconnect_circuit_model_names_;
|
||||
};
|
||||
|
||||
} /* namespace openfpga ends */
|
||||
|
||||
#endif
|
||||
|
|
@ -21,6 +21,7 @@
|
|||
#include "read_xml_simulation_setting.h"
|
||||
#include "read_xml_config_protocol.h"
|
||||
#include "read_xml_routing_circuit.h"
|
||||
#include "read_xml_pb_type_annotation.h"
|
||||
#include "read_xml_openfpga_arch.h"
|
||||
#include "openfpga_arch_linker.h"
|
||||
|
||||
|
@ -85,10 +86,13 @@ openfpga::Arch read_xml_openfpga_arch(const char* arch_file_name) {
|
|||
openfpga_arch.routing_seg2circuit = read_xml_routing_segment_circuit(xml_openfpga_arch, loc_data,
|
||||
openfpga_arch.circuit_lib);
|
||||
|
||||
/* Parse the routing segment circuit definition */
|
||||
/* Parse the direct circuit definition */
|
||||
openfpga_arch.direct2circuit = read_xml_direct_circuit(xml_openfpga_arch, loc_data,
|
||||
openfpga_arch.circuit_lib);
|
||||
|
||||
/* Parse the pb_type annotation */
|
||||
openfpga_arch.pb_type_annotations = read_xml_pb_type_annotations(xml_openfpga_arch, loc_data);
|
||||
|
||||
/* Second node should be <openfpga_simulation_setting> */
|
||||
auto xml_simulation_settings = get_single_child(doc, "openfpga_simulation_setting", loc_data);
|
||||
|
||||
|
|
|
@ -0,0 +1,190 @@
|
|||
/********************************************************************
|
||||
* 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_port_parser.h"
|
||||
#include "openfpga_pb_parser.h"
|
||||
|
||||
/* Headers from libarchfpga */
|
||||
#include "arch_error.h"
|
||||
#include "read_xml_util.h"
|
||||
|
||||
#include "read_xml_pb_type_annotation.h"
|
||||
|
||||
/********************************************************************
|
||||
* Parse XML description for an interconnection annotation
|
||||
* under a <pb_type> XML node
|
||||
*******************************************************************/
|
||||
static
|
||||
void read_xml_interc_annotation(pugi::xml_node& xml_interc,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
openfpga::PbTypeAnnotation& pb_type_annotation) {
|
||||
/* We have two mandatory XML attribute
|
||||
* 1. name of the interconnect
|
||||
* 2. circuit model name of the interconnect
|
||||
*/
|
||||
const std::string& name_attr = get_attribute(xml_interc, "name", loc_data).as_string();
|
||||
const std::string& circuit_model_name_attr = get_attribute(xml_interc, "circuit_model_name", loc_data).as_string();
|
||||
|
||||
pb_type_annotation.add_interconnect_circuit_model_pair(name_attr, circuit_model_name_attr);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Parse XML description for a pb_type port annotation
|
||||
* under a <pb_type> XML node
|
||||
*******************************************************************/
|
||||
static
|
||||
void read_xml_pb_port_annotation(pugi::xml_node& xml_port,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
openfpga::PbTypeAnnotation& pb_type_annotation) {
|
||||
/* We have two mandatory XML attribute
|
||||
* 1. name of the port
|
||||
* 2. name of the port to be binded in physical mode
|
||||
*/
|
||||
const std::string& name_attr = get_attribute(xml_port, "name", loc_data).as_string();
|
||||
const std::string& physical_mode_port_attr = get_attribute(xml_port, "physical_mode_port", loc_data).as_string();
|
||||
|
||||
/* Parse the mode port using openfpga port parser */
|
||||
openfpga::PortParser port_parser(physical_mode_port_attr);
|
||||
pb_type_annotation.add_pb_type_port_pair(name_attr, port_parser.port());
|
||||
|
||||
/* We have an optional attribute: physical_mode_pin_rotate_offset */
|
||||
pb_type_annotation.set_physical_pin_rotate_offset(name_attr, get_attribute(xml_port, "physical_mode_pin_rotate_offset", loc_data, pugiutil::ReqOpt::OPTIONAL).as_int(0));
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Parse XML description for a pb_type annotation under a <pb_type> XML node
|
||||
*******************************************************************/
|
||||
static
|
||||
void read_xml_pb_type_annotation(pugi::xml_node& xml_pb_type,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
std::vector<openfpga::PbTypeAnnotation>& pb_type_annotations) {
|
||||
openfpga::PbTypeAnnotation pb_type_annotation;
|
||||
|
||||
/* Find the name of pb_type */
|
||||
const std::string& name_attr = get_attribute(xml_pb_type, "name", loc_data).as_string();
|
||||
const std::string& physical_name_attr = get_attribute(xml_pb_type, "physical_pb_type_name", loc_data, pugiutil::ReqOpt::OPTIONAL).as_string();
|
||||
|
||||
/* If both names are not empty, this is a operating pb_type */
|
||||
if ( (false == name_attr.empty())
|
||||
&& (false == physical_name_attr.empty()) ) {
|
||||
/* Parse the attributes for operating pb_type */
|
||||
openfpga::PbParser operating_pb_parser(name_attr);
|
||||
pb_type_annotation.set_operating_pb_type_name(operating_pb_parser.leaf());
|
||||
if (0 < operating_pb_parser.parents().size()) {
|
||||
pb_type_annotation.set_operating_parent_pb_type_names(operating_pb_parser.parents());
|
||||
}
|
||||
if (0 < operating_pb_parser.modes().size()) {
|
||||
pb_type_annotation.set_operating_parent_mode_names(operating_pb_parser.modes());
|
||||
}
|
||||
|
||||
openfpga::PbParser physical_pb_parser(physical_name_attr);
|
||||
pb_type_annotation.set_physical_pb_type_name(physical_pb_parser.leaf());
|
||||
if (0 < physical_pb_parser.parents().size()) {
|
||||
pb_type_annotation.set_physical_parent_pb_type_names(physical_pb_parser.parents());
|
||||
}
|
||||
if (0 < physical_pb_parser.modes().size()) {
|
||||
pb_type_annotation.set_physical_parent_mode_names(physical_pb_parser.modes());
|
||||
}
|
||||
}
|
||||
|
||||
/* If there is only a name, this is a physical pb_type */
|
||||
if ( (false == name_attr.empty())
|
||||
&& (true == physical_name_attr.empty()) ) {
|
||||
openfpga::PbParser physical_pb_parser(name_attr);
|
||||
pb_type_annotation.set_physical_pb_type_name(physical_pb_parser.leaf());
|
||||
if (0 < physical_pb_parser.parents().size()) {
|
||||
pb_type_annotation.set_physical_parent_pb_type_names(physical_pb_parser.parents());
|
||||
}
|
||||
if (0 < physical_pb_parser.modes().size()) {
|
||||
pb_type_annotation.set_physical_parent_mode_names(physical_pb_parser.modes());
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse physical mode name which are applied to both pb_types */
|
||||
pb_type_annotation.set_physical_mode_name(get_attribute(xml_pb_type, "physical_mode_name", loc_data, pugiutil::ReqOpt::OPTIONAL).as_string());
|
||||
|
||||
/* Parse idle mode name which are applied to both pb_types */
|
||||
pb_type_annotation.set_idle_mode_name(get_attribute(xml_pb_type, "idle_mode_name", loc_data, pugiutil::ReqOpt::OPTIONAL).as_string());
|
||||
|
||||
/* Parse mode bits which are applied to both pb_types */
|
||||
pb_type_annotation.set_mode_bits(get_attribute(xml_pb_type, "mode_bits", loc_data, pugiutil::ReqOpt::OPTIONAL).as_string());
|
||||
|
||||
/* If this is a physical pb_type, circuit model name is an optional attribute,
|
||||
* which is applicable to leaf pb_type in the hierarchy
|
||||
*/
|
||||
if (true == pb_type_annotation.is_physical_pb_type()) {
|
||||
pb_type_annotation.set_circuit_model_name(get_attribute(xml_pb_type, "circuit_model_name", loc_data, pugiutil::ReqOpt::OPTIONAL).as_string());
|
||||
}
|
||||
|
||||
/* If this is an operating pb_type, index factor and offset may be optional needed */
|
||||
if (true == pb_type_annotation.is_operating_pb_type()) {
|
||||
pb_type_annotation.set_physical_pb_type_index_factor(get_attribute(xml_pb_type, "physical_pb_type_index_factor", loc_data, pugiutil::ReqOpt::OPTIONAL).as_int(1));
|
||||
pb_type_annotation.set_physical_pb_type_index_offset(get_attribute(xml_pb_type, "physical_pb_type_index_offset", loc_data, pugiutil::ReqOpt::OPTIONAL).as_int(0));
|
||||
}
|
||||
|
||||
/* Parse all the interconnect-to-circuit binding under this node
|
||||
* All the bindings are defined in child node <interconnect>
|
||||
*/
|
||||
size_t num_intercs = count_children(xml_pb_type, "interconnect", loc_data, pugiutil::ReqOpt::OPTIONAL);
|
||||
if (0 < num_intercs) {
|
||||
pugi::xml_node xml_interc = get_first_child(xml_pb_type, "interconnect", loc_data);
|
||||
while (xml_interc) {
|
||||
read_xml_interc_annotation(xml_interc, loc_data, pb_type_annotation);
|
||||
xml_interc = xml_interc.next_sibling(xml_interc.name());
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse all the port-to-port binding from operating pb_type to physical pb_type under this node
|
||||
* All the bindings are defined in child node <port>
|
||||
* This is only applicable to operating pb_type
|
||||
*/
|
||||
if (true == pb_type_annotation.is_operating_pb_type()) {
|
||||
size_t num_ports = count_children(xml_pb_type, "port", loc_data, pugiutil::ReqOpt::OPTIONAL);
|
||||
if (0 < num_ports) {
|
||||
pugi::xml_node xml_port = get_first_child(xml_pb_type, "port", loc_data);
|
||||
while (xml_port) {
|
||||
read_xml_pb_port_annotation(xml_port, loc_data, pb_type_annotation);
|
||||
xml_port = xml_port.next_sibling(xml_port.name());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Finish parsing and add it to the vector */
|
||||
pb_type_annotations.push_back(pb_type_annotation);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Top function to parse XML description about pb_type annotation
|
||||
*******************************************************************/
|
||||
std::vector<openfpga::PbTypeAnnotation> read_xml_pb_type_annotations(pugi::xml_node& Node,
|
||||
const pugiutil::loc_data& loc_data) {
|
||||
std::vector<openfpga::PbTypeAnnotation> pb_type_annotations;
|
||||
|
||||
/* Parse configuration protocol root node */
|
||||
pugi::xml_node xml_annotations = get_single_child(Node, "pb_type_annotations", loc_data);
|
||||
|
||||
/* Iterate over the children under this node,
|
||||
* each child should be named after <pb_type>
|
||||
*/
|
||||
for (pugi::xml_node xml_pb_type : xml_annotations.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, xml_annotations, {"pb_type"});
|
||||
}
|
||||
read_xml_pb_type_annotation(xml_pb_type, loc_data, pb_type_annotations);
|
||||
}
|
||||
|
||||
return pb_type_annotations;
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
#ifndef READ_XML_PB_TYPE_ANNOTATION_H
|
||||
#define READ_XML_PB_TYPE_ANNOTATION_H
|
||||
|
||||
/********************************************************************
|
||||
* Include header files that are required by function declaration
|
||||
*******************************************************************/
|
||||
#include "pugixml_util.hpp"
|
||||
#include "pugixml.hpp"
|
||||
#include "pb_type_annotation.h"
|
||||
|
||||
/********************************************************************
|
||||
* Function declaration
|
||||
*******************************************************************/
|
||||
std::vector<openfpga::PbTypeAnnotation> read_xml_pb_type_annotations(pugi::xml_node& Node,
|
||||
const pugiutil::loc_data& loc_data);
|
||||
|
||||
#endif
|
|
@ -16,6 +16,7 @@
|
|||
#include "write_xml_simulation_setting.h"
|
||||
#include "write_xml_config_protocol.h"
|
||||
#include "write_xml_routing_circuit.h"
|
||||
#include "write_xml_pb_type_annotation.h"
|
||||
#include "write_xml_openfpga_arch.h"
|
||||
|
||||
/********************************************************************
|
||||
|
@ -57,6 +58,10 @@ void write_xml_openfpga_arch(const char* fname,
|
|||
/* Write the direct connection circuit definition */
|
||||
write_xml_direct_circuit(fp, fname, openfpga_arch.circuit_lib, openfpga_arch.direct2circuit);
|
||||
|
||||
|
||||
/* Write the pb_type annotations */
|
||||
openfpga::write_xml_pb_type_annotations(fp, fname, openfpga_arch. pb_type_annotations);
|
||||
|
||||
fp << "</openfpga_architecture>" << "\n";
|
||||
|
||||
/* Write the simulation */
|
||||
|
|
|
@ -0,0 +1,224 @@
|
|||
/********************************************************************
|
||||
* This file includes functions that outputs pb_type annotations 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_pb_type_annotation.h"
|
||||
|
||||
/* namespace openfpga begins */
|
||||
namespace openfpga {
|
||||
|
||||
/********************************************************************
|
||||
* Generate the full hierarchy name for a operating pb_type
|
||||
*******************************************************************/
|
||||
static
|
||||
std::string generate_operating_pb_type_hierarchy_name(const PbTypeAnnotation& pb_type_annotation) {
|
||||
/* Iterate over the parent_pb_type and modes names, they should well match */
|
||||
VTR_ASSERT_SAFE(pb_type_annotation.operating_parent_pb_type_names().size() == pb_type_annotation.operating_parent_mode_names().size());
|
||||
|
||||
std::string hie_name;
|
||||
|
||||
for (size_t i = 0 ; i < pb_type_annotation.operating_parent_pb_type_names().size(); ++i) {
|
||||
hie_name += pb_type_annotation.operating_parent_pb_type_names()[i];
|
||||
hie_name += std::string("[");
|
||||
hie_name += pb_type_annotation.operating_parent_mode_names()[i];
|
||||
hie_name += std::string("]");
|
||||
hie_name += std::string(".");
|
||||
}
|
||||
|
||||
/* Add the leaf pb_type */
|
||||
hie_name += pb_type_annotation.operating_pb_type_name();
|
||||
|
||||
return hie_name;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Generate the full hierarchy name for a operating pb_type
|
||||
*******************************************************************/
|
||||
static
|
||||
std::string generate_physical_pb_type_hierarchy_name(const PbTypeAnnotation& pb_type_annotation) {
|
||||
/* Iterate over the parent_pb_type and modes names, they should well match */
|
||||
VTR_ASSERT_SAFE(pb_type_annotation.physical_parent_pb_type_names().size() == pb_type_annotation.physical_parent_mode_names().size());
|
||||
|
||||
std::string hie_name;
|
||||
|
||||
for (size_t i = 0 ; i < pb_type_annotation.physical_parent_pb_type_names().size(); ++i) {
|
||||
hie_name += pb_type_annotation.physical_parent_pb_type_names()[i];
|
||||
hie_name += std::string("[");
|
||||
hie_name += pb_type_annotation.physical_parent_mode_names()[i];
|
||||
hie_name += std::string("]");
|
||||
hie_name += std::string(".");
|
||||
}
|
||||
|
||||
/* Add the leaf pb_type */
|
||||
hie_name += pb_type_annotation.physical_pb_type_name();
|
||||
|
||||
return hie_name;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Generate the full hierarchy name for a operating pb_type
|
||||
*******************************************************************/
|
||||
static
|
||||
std::string generate_physical_pb_port_name(const BasicPort& pb_port) {
|
||||
std::string port_name;
|
||||
|
||||
/* Output format: <port_name>[<LSB>:<MSB>] */
|
||||
port_name += pb_port.get_name();
|
||||
port_name += std::string("[");
|
||||
port_name += std::to_string(pb_port.get_lsb());
|
||||
port_name += std::string(":");
|
||||
port_name += std::to_string(pb_port.get_msb());
|
||||
port_name += std::string("]");
|
||||
|
||||
return port_name;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* A writer to output an pb_type interconnection annotation to XML format
|
||||
*******************************************************************/
|
||||
static
|
||||
void write_xml_interconnect_annotation(std::fstream& fp,
|
||||
const char* fname,
|
||||
const openfpga::PbTypeAnnotation& pb_type_annotation,
|
||||
const std::string& interc_name) {
|
||||
/* Validate the file stream */
|
||||
openfpga::check_file_stream(fname, fp);
|
||||
|
||||
fp << "\t\t\t" << "<interconnect";
|
||||
|
||||
write_xml_attribute(fp, "name", interc_name.c_str());
|
||||
write_xml_attribute(fp, "circuit_model_name", pb_type_annotation.interconnect_circuit_model_name(interc_name).c_str());
|
||||
|
||||
fp << "/>" << "\n";
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* A writer to output an pb_type port annotation to XML format
|
||||
*******************************************************************/
|
||||
static
|
||||
void write_xml_pb_port_annotation(std::fstream& fp,
|
||||
const char* fname,
|
||||
const openfpga::PbTypeAnnotation& pb_type_annotation,
|
||||
const std::string& port_name) {
|
||||
/* Validate the file stream */
|
||||
openfpga::check_file_stream(fname, fp);
|
||||
|
||||
fp << "\t\t\t" << "<port";
|
||||
|
||||
write_xml_attribute(fp, "name", port_name.c_str());
|
||||
write_xml_attribute(fp, "physical_mode_port", generate_physical_pb_port_name(pb_type_annotation.physical_pb_type_port(port_name)).c_str());
|
||||
write_xml_attribute(fp, "physical_mode_pin_rotate_offset", pb_type_annotation.physical_pin_rotate_offset(port_name));
|
||||
|
||||
fp << "/>" << "\n";
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* A writer to output a device variation in a technology library to XML format
|
||||
*******************************************************************/
|
||||
static
|
||||
void write_xml_pb_type_annotation(std::fstream& fp,
|
||||
const char* fname,
|
||||
const openfpga::PbTypeAnnotation& pb_type_annotation) {
|
||||
/* Validate the file stream */
|
||||
openfpga::check_file_stream(fname, fp);
|
||||
|
||||
fp << "\t\t" << "<pb_type";
|
||||
|
||||
/* Write up name of the pb_type, which is different by the type of pb_type
|
||||
* 1. operating pb_type, we output name, physical_pb_type_name
|
||||
* 1. physical pb_type, we output name
|
||||
*/
|
||||
if (true == pb_type_annotation.is_operating_pb_type()) {
|
||||
write_xml_attribute(fp, "name", generate_operating_pb_type_hierarchy_name(pb_type_annotation).c_str());
|
||||
write_xml_attribute(fp, "physical_pb_type_name", generate_physical_pb_type_hierarchy_name(pb_type_annotation).c_str());
|
||||
}
|
||||
|
||||
if (true == pb_type_annotation.is_physical_pb_type()) {
|
||||
write_xml_attribute(fp, "name", generate_physical_pb_type_hierarchy_name(pb_type_annotation).c_str());
|
||||
}
|
||||
|
||||
/* Output physical mode name */
|
||||
if (!pb_type_annotation.physical_mode_name().empty()) {
|
||||
write_xml_attribute(fp, "physical_mode_name", pb_type_annotation.physical_mode_name().c_str());
|
||||
}
|
||||
|
||||
/* Output idle mode name */
|
||||
if (!pb_type_annotation.idle_mode_name().empty()) {
|
||||
write_xml_attribute(fp, "idle_mode_name", pb_type_annotation.idle_mode_name().c_str());
|
||||
}
|
||||
|
||||
/* Output mode_bits */
|
||||
if (!pb_type_annotation.mode_bits().empty()) {
|
||||
write_xml_attribute(fp, "mode_bits", pb_type_annotation.mode_bits().c_str());
|
||||
}
|
||||
|
||||
/* Output circuit model name */
|
||||
if (!pb_type_annotation.circuit_model_name().empty()) {
|
||||
write_xml_attribute(fp, "circuit_model_name", pb_type_annotation.circuit_model_name().c_str());
|
||||
}
|
||||
|
||||
/* Output physical mode index factor and offset, only applicable to operating mode */
|
||||
if (true == pb_type_annotation.is_operating_pb_type()) {
|
||||
write_xml_attribute(fp, "physical_pb_type_index_factor", pb_type_annotation.physical_pb_type_index_factor());
|
||||
write_xml_attribute(fp, "physical_pb_type_index_offset", pb_type_annotation.physical_pb_type_index_offset());
|
||||
}
|
||||
|
||||
/* If there are interconnect definition or port definition, output them
|
||||
* Otherwise we can finish here
|
||||
*/
|
||||
if ( (0 == pb_type_annotation.interconnect_names().size())
|
||||
&& (0 == pb_type_annotation.port_names().size()) ) {
|
||||
fp << "/>" << "\n";
|
||||
return;
|
||||
}
|
||||
|
||||
fp << ">" << "\n";
|
||||
|
||||
/* Output interconnects if there are any */
|
||||
for (const std::string& interc_name : pb_type_annotation.interconnect_names()) {
|
||||
write_xml_interconnect_annotation(fp, fname, pb_type_annotation, interc_name);
|
||||
}
|
||||
|
||||
/* Output pb_type ports if there are any */
|
||||
for (const std::string& port_name : pb_type_annotation.port_names()) {
|
||||
write_xml_pb_port_annotation(fp, fname, pb_type_annotation, port_name);
|
||||
}
|
||||
|
||||
fp << "\t\t</pb_type>" << "\n";
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* A writer to output a number of pb_type annotations to XML format
|
||||
*******************************************************************/
|
||||
void write_xml_pb_type_annotations(std::fstream& fp,
|
||||
const char* fname,
|
||||
const std::vector<PbTypeAnnotation>& pb_type_annotations) {
|
||||
/* Validate the file stream */
|
||||
openfpga::check_file_stream(fname, fp);
|
||||
|
||||
/* Write the root node for pb_type annotations,
|
||||
* we apply a tab becuase pb_type annotations is just a subnode
|
||||
* under the root node <openfpga_arch>
|
||||
*/
|
||||
fp << "\t" << "<pb_type_annotations>" << "\n";
|
||||
|
||||
/* Write device model one by one */
|
||||
for (const PbTypeAnnotation& pb_type_annotation : pb_type_annotations) {
|
||||
write_xml_pb_type_annotation(fp, fname, pb_type_annotation);
|
||||
}
|
||||
|
||||
/* Write the root node for pb_type annotations */
|
||||
fp << "\t" << "</pb_type_annotations>" << "\n";
|
||||
}
|
||||
|
||||
} /* namespace openfpga ends */
|
|
@ -0,0 +1,22 @@
|
|||
#ifndef WRITE_XML_PB_TYPE_ANNOTATION_H
|
||||
#define WRITE_XML_PB_TYPE_ANNOTATION_H
|
||||
|
||||
/********************************************************************
|
||||
* Include header files that are required by function declaration
|
||||
*******************************************************************/
|
||||
#include <fstream>
|
||||
#include "pb_type_annotation.h"
|
||||
|
||||
/********************************************************************
|
||||
* Function declaration
|
||||
*******************************************************************/
|
||||
/* namespace openfpga begins */
|
||||
namespace openfpga {
|
||||
|
||||
void write_xml_pb_type_annotations(std::fstream& fp,
|
||||
const char* fname,
|
||||
const std::vector<PbTypeAnnotation>& pb_type_annotations);
|
||||
|
||||
} /* namespace openfpga ends */
|
||||
|
||||
#endif
|
|
@ -46,6 +46,21 @@ void write_xml_attribute(std::fstream& fp,
|
|||
fp << "\"";
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* A most utilized function to write an XML attribute to file
|
||||
* This accepts the value as a float
|
||||
*******************************************************************/
|
||||
void write_xml_attribute(std::fstream& fp,
|
||||
const char* attr,
|
||||
const int& value) {
|
||||
/* Validate the file stream */
|
||||
openfpga::valid_file_stream(fp);
|
||||
|
||||
fp << " " << attr << "=\"";
|
||||
fp << value;
|
||||
fp << "\"";
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* A most utilized function to write an XML attribute to file
|
||||
* This accepts the value as a float
|
||||
|
|
|
@ -18,6 +18,10 @@ void write_xml_attribute(std::fstream& fp,
|
|||
const char* attr,
|
||||
const bool& value);
|
||||
|
||||
void write_xml_attribute(std::fstream& fp,
|
||||
const char* attr,
|
||||
const int& value);
|
||||
|
||||
void write_xml_attribute(std::fstream& fp,
|
||||
const char* attr,
|
||||
const float& value);
|
||||
|
|
|
@ -0,0 +1,118 @@
|
|||
/************************************************************************
|
||||
* Member functions for Pb parsers
|
||||
***********************************************************************/
|
||||
#include <cstring>
|
||||
|
||||
#include "vtr_assert.h"
|
||||
|
||||
#include "openfpga_tokenizer.h"
|
||||
|
||||
#include "openfpga_pb_parser.h"
|
||||
|
||||
/* namespace openfpga begins */
|
||||
namespace openfpga {
|
||||
|
||||
/************************************************************************
|
||||
* Member functions for PbParser class
|
||||
***********************************************************************/
|
||||
|
||||
/************************************************************************
|
||||
* Constructors
|
||||
***********************************************************************/
|
||||
PbParser::PbParser (const std::string& data) {
|
||||
set_default_bracket();
|
||||
set_default_delim();
|
||||
set_data(data);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Public Accessors
|
||||
***********************************************************************/
|
||||
/* Get the data string */
|
||||
std::string PbParser::data() const {
|
||||
return data_;
|
||||
}
|
||||
|
||||
std::string PbParser::leaf() const {
|
||||
return leaf_;
|
||||
}
|
||||
|
||||
std::vector<std::string> PbParser::parents() const {
|
||||
return parents_;
|
||||
}
|
||||
|
||||
std::vector<std::string> PbParser::modes() const {
|
||||
return modes_;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Public Mutators
|
||||
***********************************************************************/
|
||||
void PbParser::set_data(const std::string& data) {
|
||||
data_ = data;
|
||||
parse();
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Internal Mutators
|
||||
***********************************************************************/
|
||||
/* Parse the data */
|
||||
void PbParser::parse() {
|
||||
/* Create a tokenizer */
|
||||
StringToken tokenizer(data_);
|
||||
|
||||
/* Split the data into <pb_type>[<mode>] */
|
||||
std::vector<std::string> pb_tokens = tokenizer.split(delim_);
|
||||
|
||||
/* The last pb is the leaf node.
|
||||
* It should NOT be empty and should NOT contain any brackets!
|
||||
*/
|
||||
VTR_ASSERT(0 < pb_tokens.size());
|
||||
VTR_ASSERT(false == pb_tokens.back().empty());
|
||||
VTR_ASSERT(pb_tokens.back().find(bracket_.x()) == std::string::npos);
|
||||
VTR_ASSERT(pb_tokens.back().find(bracket_.y()) == std::string::npos);
|
||||
/* Pass the check, we assign the value */
|
||||
leaf_ = pb_tokens.back();
|
||||
|
||||
/* Split the rest of pb_tokens, split the pb_type and mode_name */
|
||||
for (size_t itok = 0; itok < pb_tokens.size() - 1; ++itok) {
|
||||
/* Create a tokenizer */
|
||||
StringToken pb_tokenizer(pb_tokens[itok]);
|
||||
std::vector<std::string> tokens = pb_tokenizer.split(bracket_.x());
|
||||
/* Make sure we have a port name! */
|
||||
VTR_ASSERT_SAFE ((1 == tokens.size()) || (2 == tokens.size()));
|
||||
/* Store the pb_type name */
|
||||
parents_.push_back(tokens[0]);
|
||||
|
||||
/* If we only have one token, the mode name is the default mode
|
||||
* Here we use the default keyword 'default'
|
||||
* from VPR function ProcessMode() in libarchfpga
|
||||
*/
|
||||
if (1 == tokens.size()) {
|
||||
modes_.push_back(std::string("default"));
|
||||
continue; /* We can finish here */
|
||||
}
|
||||
|
||||
/* If there is a mode name, extract it */
|
||||
VTR_ASSERT_SAFE (2 == tokens.size());
|
||||
|
||||
/* Chomp the ']' */
|
||||
pb_tokenizer.set_data(tokens[1]);
|
||||
std::vector<std::string> mode_tokens = pb_tokenizer.split(bracket_.y());
|
||||
|
||||
/* Make sure we have only one mode name inside */
|
||||
VTR_ASSERT(1 == mode_tokens.size());
|
||||
modes_.push_back(mode_tokens[0]);
|
||||
}
|
||||
}
|
||||
|
||||
void PbParser::set_default_bracket() {
|
||||
bracket_.set_x('[');
|
||||
bracket_.set_y(']');
|
||||
}
|
||||
|
||||
void PbParser::set_default_delim() {
|
||||
delim_ = '.';
|
||||
}
|
||||
|
||||
} /* namespace openfpga ends */
|
|
@ -0,0 +1,56 @@
|
|||
#ifndef OPENFPGA_PB_PARSER_H
|
||||
#define OPENFPGA_PB_PARSER_H
|
||||
|
||||
/********************************************************************
|
||||
* Include header files that are required by data structure declaration
|
||||
*******************************************************************/
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "vtr_geometry.h"
|
||||
|
||||
#include "openfpga_tokenizer.h"
|
||||
|
||||
/************************************************************************
|
||||
* This file includes parsers for pb_type definition in the architecture XML
|
||||
* language.
|
||||
***********************************************************************/
|
||||
|
||||
/* namespace openfpga begins */
|
||||
namespace openfpga {
|
||||
|
||||
/************************************************************************
|
||||
* Class PbParser: pb_type name with full hierarchy parser
|
||||
* Supported pb_type definition:
|
||||
* 1. <pb_type>[<mode>].<sub_pb_type>[<mode>] ... .<leaf_pb_type>
|
||||
* 2. <pb_type>.<sub_pb_type> ... .<leaf_pb_type>
|
||||
* where each pb_type may be specified by a mode or use the default mode
|
||||
* (mode name not given)
|
||||
***********************************************************************/
|
||||
class PbParser{
|
||||
public : /* Constructors*/
|
||||
PbParser (const std::string& data);
|
||||
public : /* Public Accessors */
|
||||
std::string data() const;
|
||||
std::string leaf() const;
|
||||
std::vector<std::string> parents() const;
|
||||
std::vector<std::string> modes() const;
|
||||
public : /* Public Mutators */
|
||||
void set_data(const std::string& data);
|
||||
private : /* Private Mutators */
|
||||
void parse();
|
||||
void set_default_bracket();
|
||||
void set_default_delim();
|
||||
private: /* Internal data */
|
||||
std::string data_; /* Lines to be splited */
|
||||
vtr::Point<char> bracket_;
|
||||
char delim_;
|
||||
std::vector<std::string> parents_;
|
||||
std::vector<std::string> modes_;
|
||||
std::string leaf_;
|
||||
};
|
||||
|
||||
} /* namespace openfpga ends */
|
||||
|
||||
#endif
|
||||
|
|
@ -64,7 +64,7 @@ void PortParser::parse() {
|
|||
|
||||
/* If we only have one token */
|
||||
if (1 == port_tokens.size()) {
|
||||
port_.set_width(0);
|
||||
port_.set_width(1);
|
||||
return; /* We can finish here */
|
||||
}
|
||||
|
||||
|
@ -75,21 +75,22 @@ void PortParser::parse() {
|
|||
VTR_ASSERT_SAFE (1 == port_tokens.size());
|
||||
|
||||
/* Split the pin string now */
|
||||
tokenizer.set_data(port_tokens[0]);
|
||||
tokenizer.set_data(pin_tokens[0]);
|
||||
pin_tokens = tokenizer.split(delim_);
|
||||
|
||||
/* Check if we have LSB and MSB or just one */
|
||||
if ( 1 == pin_tokens.size() ) {
|
||||
/* Single pin */
|
||||
port_.set_width(stoi(pin_tokens[0]), stoi(pin_tokens[0]));
|
||||
port_.set_width(std::stoi(pin_tokens[0]), std::stoi(pin_tokens[0]));
|
||||
} else if ( 2 == pin_tokens.size() ) {
|
||||
/* A number of pin */
|
||||
port_.set_width(stoi(pin_tokens[0]), stoi(pin_tokens[1]));
|
||||
}
|
||||
|
||||
/* Re-order to ensure LSB <= MSB */
|
||||
if (false == port_.is_valid()) {
|
||||
port_.revert();
|
||||
/* A number of pins.
|
||||
* Note that we always use the LSB for token[0] and MSB for token[1]
|
||||
*/
|
||||
if (std::stoi(pin_tokens[1]) < std::stoi(pin_tokens[0])) {
|
||||
port_.set_width(std::stoi(pin_tokens[1]), std::stoi(pin_tokens[0]));
|
||||
} else {
|
||||
port_.set_width(std::stoi(pin_tokens[0]), std::stoi(pin_tokens[1]));
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
|
|
Loading…
Reference in New Issue