[engine] update source files subject to code formatting rules
This commit is contained in:
parent
b8c59db9e9
commit
6d31b319a2
|
@ -1,7 +1,7 @@
|
|||
#include "vtr_assert.h"
|
||||
|
||||
#include "arch_direct.h"
|
||||
|
||||
#include "vtr_assert.h"
|
||||
|
||||
/************************************************************************
|
||||
* Member functions for class ArchDirect
|
||||
***********************************************************************/
|
||||
|
@ -9,9 +9,7 @@
|
|||
/************************************************************************
|
||||
* Constructors
|
||||
***********************************************************************/
|
||||
ArchDirect::ArchDirect() {
|
||||
return;
|
||||
}
|
||||
ArchDirect::ArchDirect() { return; }
|
||||
|
||||
/************************************************************************
|
||||
* Public Accessors : aggregates
|
||||
|
@ -21,7 +19,7 @@ ArchDirect::arch_direct_range ArchDirect::directs() const {
|
|||
}
|
||||
|
||||
/************************************************************************
|
||||
* Public Accessors
|
||||
* Public Accessors
|
||||
***********************************************************************/
|
||||
ArchDirectId ArchDirect::direct(const std::string& name) const {
|
||||
if (0 < direct_name2ids_.count(name)) {
|
||||
|
@ -33,31 +31,31 @@ ArchDirectId ArchDirect::direct(const std::string& name) const {
|
|||
std::string ArchDirect::name(const ArchDirectId& direct_id) const {
|
||||
/* validate the direct_id */
|
||||
VTR_ASSERT(valid_direct_id(direct_id));
|
||||
return names_[direct_id];
|
||||
return names_[direct_id];
|
||||
}
|
||||
|
||||
CircuitModelId ArchDirect::circuit_model(const ArchDirectId& direct_id) const {
|
||||
/* validate the direct_id */
|
||||
VTR_ASSERT(valid_direct_id(direct_id));
|
||||
return circuit_models_[direct_id];
|
||||
return circuit_models_[direct_id];
|
||||
}
|
||||
|
||||
e_direct_type ArchDirect::type(const ArchDirectId& direct_id) const {
|
||||
/* validate the direct_id */
|
||||
VTR_ASSERT(valid_direct_id(direct_id));
|
||||
return types_[direct_id];
|
||||
return types_[direct_id];
|
||||
}
|
||||
|
||||
e_direct_direction ArchDirect::x_dir(const ArchDirectId& direct_id) const {
|
||||
/* validate the direct_id */
|
||||
VTR_ASSERT(valid_direct_id(direct_id));
|
||||
return directions_[direct_id].x();
|
||||
return directions_[direct_id].x();
|
||||
}
|
||||
|
||||
e_direct_direction ArchDirect::y_dir(const ArchDirectId& direct_id) const {
|
||||
/* validate the direct_id */
|
||||
VTR_ASSERT(valid_direct_id(direct_id));
|
||||
return directions_[direct_id].y();
|
||||
return directions_[direct_id].y();
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
|
@ -74,24 +72,27 @@ ArchDirectId ArchDirect::add_direct(const std::string& name) {
|
|||
names_.push_back(name);
|
||||
circuit_models_.push_back(CircuitModelId::INVALID());
|
||||
types_.emplace_back(NUM_DIRECT_TYPES);
|
||||
directions_.emplace_back(vtr::Point<e_direct_direction>(NUM_DIRECT_DIRECTIONS, NUM_DIRECT_DIRECTIONS));
|
||||
directions_.emplace_back(vtr::Point<e_direct_direction>(
|
||||
NUM_DIRECT_DIRECTIONS, NUM_DIRECT_DIRECTIONS));
|
||||
|
||||
/* Register in the name-to-id map */
|
||||
direct_name2ids_[name] = direct;
|
||||
|
||||
|
||||
return direct;
|
||||
}
|
||||
|
||||
void ArchDirect::set_circuit_model(const ArchDirectId& direct_id, const CircuitModelId& circuit_model) {
|
||||
void ArchDirect::set_circuit_model(const ArchDirectId& direct_id,
|
||||
const CircuitModelId& circuit_model) {
|
||||
/* validate the direct_id */
|
||||
VTR_ASSERT(valid_direct_id(direct_id));
|
||||
circuit_models_[direct_id] = circuit_model;
|
||||
circuit_models_[direct_id] = circuit_model;
|
||||
}
|
||||
|
||||
void ArchDirect::set_type(const ArchDirectId& direct_id, const e_direct_type& type) {
|
||||
void ArchDirect::set_type(const ArchDirectId& direct_id,
|
||||
const e_direct_type& type) {
|
||||
/* validate the direct_id */
|
||||
VTR_ASSERT(valid_direct_id(direct_id));
|
||||
types_[direct_id] = type;
|
||||
types_[direct_id] = type;
|
||||
}
|
||||
|
||||
void ArchDirect::set_direction(const ArchDirectId& direct_id,
|
||||
|
@ -99,14 +100,15 @@ void ArchDirect::set_direction(const ArchDirectId& direct_id,
|
|||
const e_direct_direction& y_dir) {
|
||||
/* validate the direct_id */
|
||||
VTR_ASSERT(valid_direct_id(direct_id));
|
||||
directions_[direct_id].set_x(x_dir);
|
||||
directions_[direct_id].set_y(y_dir);
|
||||
directions_[direct_id].set_x(x_dir);
|
||||
directions_[direct_id].set_y(y_dir);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Internal invalidators/validators
|
||||
* Internal invalidators/validators
|
||||
***********************************************************************/
|
||||
/* Validators */
|
||||
bool ArchDirect::valid_direct_id(const ArchDirectId& direct_id) const {
|
||||
return ( size_t(direct_id) < direct_ids_.size() ) && ( direct_id == direct_ids_[direct_id] );
|
||||
return (size_t(direct_id) < direct_ids_.size()) &&
|
||||
(direct_id == direct_ids_[direct_id]);
|
||||
}
|
||||
|
|
|
@ -1,17 +1,16 @@
|
|||
#ifndef ARCH_DIRECT_H
|
||||
#define ARCH_DIRECT_H
|
||||
|
||||
#include <map>
|
||||
#include <array>
|
||||
#include <map>
|
||||
|
||||
#include "vtr_vector.h"
|
||||
#include "vtr_geometry.h"
|
||||
|
||||
#include "circuit_library_fwd.h"
|
||||
#include "arch_direct_fwd.h"
|
||||
#include "circuit_library_fwd.h"
|
||||
#include "vtr_geometry.h"
|
||||
#include "vtr_vector.h"
|
||||
|
||||
/********************************************************************
|
||||
* Define the types of point to point connection between CLBs
|
||||
* Define the types of point to point connection between CLBs
|
||||
* These types are supplementary to the original VPR direct connections
|
||||
* Here we extend to the cross-row and cross-column connections
|
||||
********************************************************************/
|
||||
|
@ -22,83 +21,88 @@ enum e_direct_type {
|
|||
INTER_ROW,
|
||||
NUM_DIRECT_TYPES
|
||||
};
|
||||
constexpr std::array<const char*, NUM_DIRECT_TYPES> DIRECT_TYPE_STRING = {{"inner_column", "inner_row", "inter_column", "inter_row"}};
|
||||
constexpr std::array<const char*, NUM_DIRECT_TYPES> DIRECT_TYPE_STRING = {
|
||||
{"inner_column", "inner_row", "inter_column", "inter_row"}};
|
||||
|
||||
enum e_direct_direction {
|
||||
POSITIVE_DIR,
|
||||
NEGATIVE_DIR,
|
||||
NUM_DIRECT_DIRECTIONS
|
||||
};
|
||||
constexpr std::array<const char*, NUM_DIRECT_DIRECTIONS> DIRECT_DIRECTION_STRING = {{"positive", "negative"}};
|
||||
enum e_direct_direction { POSITIVE_DIR, NEGATIVE_DIR, NUM_DIRECT_DIRECTIONS };
|
||||
constexpr std::array<const char*, NUM_DIRECT_DIRECTIONS>
|
||||
DIRECT_DIRECTION_STRING = {{"positive", "negative"}};
|
||||
|
||||
/********************************************************************
|
||||
* A data base to describe the direct connection in OpenFPGA architecture
|
||||
* For each direct connection, it will include
|
||||
* - name: the identifier to annotate the original direct connection in VPR architecture
|
||||
* - name: the identifier to annotate the original direct connection in VPR
|
||||
*architecture
|
||||
* - circuit model: the circuit model to used to implement this connection
|
||||
* - type: if this connection should be cross-column or cross-row
|
||||
* - x-direction: how this connection is going to be applied to adjacent columns
|
||||
* - x-direction: how this connection is going to be applied to adjacent columns
|
||||
* a positive x-direction means that column A will be connected
|
||||
* to the column B on the right side of column A
|
||||
* - y-direction: how this connection is going to be applied to adjacent rows
|
||||
* - y-direction: how this connection is going to be applied to adjacent rows
|
||||
* a positive y-direction means that row A will be connected
|
||||
* to the row B on the bottom side of row A
|
||||
*
|
||||
* Note that: this is the data structure to be used when parsing the XML
|
||||
* Note that: this is the data structure to be used when parsing the XML
|
||||
* this is NOT the data structure to be use in core engine
|
||||
********************************************************************/
|
||||
class ArchDirect {
|
||||
public: /* Types */
|
||||
typedef vtr::vector<ArchDirectId, ArchDirectId>::const_iterator arch_direct_iterator;
|
||||
/* Create range */
|
||||
typedef vtr::Range<arch_direct_iterator> arch_direct_range;
|
||||
public: /* Types */
|
||||
typedef vtr::vector<ArchDirectId, ArchDirectId>::const_iterator
|
||||
arch_direct_iterator;
|
||||
/* Create range */
|
||||
typedef vtr::Range<arch_direct_iterator> arch_direct_range;
|
||||
|
||||
public: /* Constructors */
|
||||
ArchDirect();
|
||||
public: /* Constructors */
|
||||
ArchDirect();
|
||||
|
||||
public: /* Accessors: aggregates */
|
||||
arch_direct_range directs() const;
|
||||
public: /* Accessors: aggregates */
|
||||
arch_direct_range directs() const;
|
||||
|
||||
public: /* Public Accessors: Basic data query on directs */
|
||||
ArchDirectId direct(const std::string& name) const;
|
||||
std::string name(const ArchDirectId& direct_id) const;
|
||||
CircuitModelId circuit_model(const ArchDirectId& direct_id) const;
|
||||
e_direct_type type(const ArchDirectId& direct_id) const;
|
||||
e_direct_direction x_dir(const ArchDirectId& direct_id) const;
|
||||
e_direct_direction y_dir(const ArchDirectId& direct_id) const;
|
||||
public: /* Public Mutators */
|
||||
ArchDirectId add_direct(const std::string& name);
|
||||
void set_circuit_model(const ArchDirectId& direct_id, const CircuitModelId& circuit_model);
|
||||
void set_type(const ArchDirectId& direct_id, const e_direct_type& type);
|
||||
void set_direction(const ArchDirectId& direct_id,
|
||||
const e_direct_direction& x_dir,
|
||||
const e_direct_direction& y_dir);
|
||||
public: /* Public invalidators/validators */
|
||||
bool valid_direct_id(const ArchDirectId& direct_id) const;
|
||||
private: /* Internal data */
|
||||
vtr::vector<ArchDirectId, ArchDirectId> direct_ids_;
|
||||
|
||||
/* Unique name: the identifier to annotate the original direct connection in VPR architecture */
|
||||
vtr::vector<ArchDirectId, std::string> names_;
|
||||
public: /* Public Accessors: Basic data query on directs */
|
||||
ArchDirectId direct(const std::string& name) const;
|
||||
std::string name(const ArchDirectId& direct_id) const;
|
||||
CircuitModelId circuit_model(const ArchDirectId& direct_id) const;
|
||||
e_direct_type type(const ArchDirectId& direct_id) const;
|
||||
e_direct_direction x_dir(const ArchDirectId& direct_id) const;
|
||||
e_direct_direction y_dir(const ArchDirectId& direct_id) const;
|
||||
|
||||
/* circuit model: the circuit model to used to implement this connection */
|
||||
vtr::vector<ArchDirectId, CircuitModelId> circuit_models_;
|
||||
public: /* Public Mutators */
|
||||
ArchDirectId add_direct(const std::string& name);
|
||||
void set_circuit_model(const ArchDirectId& direct_id,
|
||||
const CircuitModelId& circuit_model);
|
||||
void set_type(const ArchDirectId& direct_id, const e_direct_type& type);
|
||||
void set_direction(const ArchDirectId& direct_id,
|
||||
const e_direct_direction& x_dir,
|
||||
const e_direct_direction& y_dir);
|
||||
|
||||
/* type: if this connection should be cross-column or cross-row */
|
||||
vtr::vector<ArchDirectId, e_direct_type> types_;
|
||||
public: /* Public invalidators/validators */
|
||||
bool valid_direct_id(const ArchDirectId& direct_id) const;
|
||||
|
||||
/*
|
||||
* x-direction: how this connection is going to be applied to adjacent columns
|
||||
* a positive x-direction means that column A will be connected
|
||||
* to the column B on the right side of column A
|
||||
* y-direction: how this connection is going to be applied to adjacent rows
|
||||
* a positive y-direction means that row A will be connected
|
||||
* to the row B on the bottom side of row A
|
||||
*/
|
||||
vtr::vector<ArchDirectId, vtr::Point<e_direct_direction>> directions_;
|
||||
private: /* Internal data */
|
||||
vtr::vector<ArchDirectId, ArchDirectId> direct_ids_;
|
||||
|
||||
/* Fast look-up */
|
||||
std::map<std::string, ArchDirectId> direct_name2ids_;
|
||||
/* Unique name: the identifier to annotate the original direct connection in
|
||||
* VPR architecture */
|
||||
vtr::vector<ArchDirectId, std::string> names_;
|
||||
|
||||
/* circuit model: the circuit model to used to implement this connection */
|
||||
vtr::vector<ArchDirectId, CircuitModelId> circuit_models_;
|
||||
|
||||
/* type: if this connection should be cross-column or cross-row */
|
||||
vtr::vector<ArchDirectId, e_direct_type> types_;
|
||||
|
||||
/*
|
||||
* x-direction: how this connection is going to be applied to adjacent columns
|
||||
* a positive x-direction means that column A will be connected
|
||||
* to the column B on the right side of column A
|
||||
* y-direction: how this connection is going to be applied to adjacent rows
|
||||
* a positive y-direction means that row A will be connected
|
||||
* to the row B on the bottom side of row A
|
||||
*/
|
||||
vtr::vector<ArchDirectId, vtr::Point<e_direct_direction>> directions_;
|
||||
|
||||
/* Fast look-up */
|
||||
std::map<std::string, ArchDirectId> direct_name2ids_;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/************************************************************************
|
||||
* A header file for ArchDirect class, including critical data declaration
|
||||
* Please include this file only for using any TechnologyLibrary data structure
|
||||
* Refer to arch_direct.h for more details
|
||||
* Refer to arch_direct.h for more details
|
||||
***********************************************************************/
|
||||
|
||||
/************************************************************************
|
||||
* Create strong id for ArchDirect to avoid illegal type casting
|
||||
* Create strong id for ArchDirect to avoid illegal type casting
|
||||
***********************************************************************/
|
||||
#ifndef ARCH_DIRECT_FWD_H
|
||||
#define ARCH_DIRECT_FWD_H
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#include "vtr_assert.h"
|
||||
|
||||
#include "bitstream_setting.h"
|
||||
|
||||
#include "vtr_assert.h"
|
||||
|
||||
/* namespace openfpga begins */
|
||||
namespace openfpga {
|
||||
|
||||
|
@ -12,88 +12,106 @@ namespace openfpga {
|
|||
/************************************************************************
|
||||
* Public Accessors : aggregates
|
||||
***********************************************************************/
|
||||
BitstreamSetting::bitstream_pb_type_setting_range BitstreamSetting::pb_type_settings() const {
|
||||
return vtr::make_range(pb_type_setting_ids_.begin(), pb_type_setting_ids_.end());
|
||||
BitstreamSetting::bitstream_pb_type_setting_range
|
||||
BitstreamSetting::pb_type_settings() const {
|
||||
return vtr::make_range(pb_type_setting_ids_.begin(),
|
||||
pb_type_setting_ids_.end());
|
||||
}
|
||||
|
||||
BitstreamSetting::bitstream_interconnect_setting_range BitstreamSetting::interconnect_settings() const {
|
||||
return vtr::make_range(interconnect_setting_ids_.begin(), interconnect_setting_ids_.end());
|
||||
BitstreamSetting::bitstream_interconnect_setting_range
|
||||
BitstreamSetting::interconnect_settings() const {
|
||||
return vtr::make_range(interconnect_setting_ids_.begin(),
|
||||
interconnect_setting_ids_.end());
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Constructors
|
||||
***********************************************************************/
|
||||
BitstreamSetting::BitstreamSetting() {
|
||||
return;
|
||||
}
|
||||
BitstreamSetting::BitstreamSetting() { return; }
|
||||
|
||||
/************************************************************************
|
||||
* Public Accessors
|
||||
***********************************************************************/
|
||||
std::string BitstreamSetting::pb_type_name(const BitstreamPbTypeSettingId& pb_type_setting_id) const {
|
||||
std::string BitstreamSetting::pb_type_name(
|
||||
const BitstreamPbTypeSettingId& pb_type_setting_id) const {
|
||||
VTR_ASSERT(true == valid_bitstream_pb_type_setting_id(pb_type_setting_id));
|
||||
return pb_type_names_[pb_type_setting_id];
|
||||
}
|
||||
|
||||
std::vector<std::string> BitstreamSetting::parent_pb_type_names(const BitstreamPbTypeSettingId& pb_type_setting_id) const {
|
||||
std::vector<std::string> BitstreamSetting::parent_pb_type_names(
|
||||
const BitstreamPbTypeSettingId& pb_type_setting_id) const {
|
||||
VTR_ASSERT(true == valid_bitstream_pb_type_setting_id(pb_type_setting_id));
|
||||
return parent_pb_type_names_[pb_type_setting_id];
|
||||
}
|
||||
|
||||
std::vector<std::string> BitstreamSetting::parent_mode_names(const BitstreamPbTypeSettingId& pb_type_setting_id) const {
|
||||
std::vector<std::string> BitstreamSetting::parent_mode_names(
|
||||
const BitstreamPbTypeSettingId& pb_type_setting_id) const {
|
||||
VTR_ASSERT(true == valid_bitstream_pb_type_setting_id(pb_type_setting_id));
|
||||
return parent_mode_names_[pb_type_setting_id];
|
||||
}
|
||||
|
||||
std::string BitstreamSetting::pb_type_bitstream_source(const BitstreamPbTypeSettingId& pb_type_setting_id) const {
|
||||
std::string BitstreamSetting::pb_type_bitstream_source(
|
||||
const BitstreamPbTypeSettingId& pb_type_setting_id) const {
|
||||
VTR_ASSERT(true == valid_bitstream_pb_type_setting_id(pb_type_setting_id));
|
||||
return pb_type_bitstream_sources_[pb_type_setting_id];
|
||||
}
|
||||
|
||||
std::string BitstreamSetting::pb_type_bitstream_content(const BitstreamPbTypeSettingId& pb_type_setting_id) const {
|
||||
std::string BitstreamSetting::pb_type_bitstream_content(
|
||||
const BitstreamPbTypeSettingId& pb_type_setting_id) const {
|
||||
VTR_ASSERT(true == valid_bitstream_pb_type_setting_id(pb_type_setting_id));
|
||||
return pb_type_bitstream_contents_[pb_type_setting_id];
|
||||
}
|
||||
|
||||
bool BitstreamSetting::is_mode_select_bitstream(const BitstreamPbTypeSettingId& pb_type_setting_id) const {
|
||||
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 {
|
||||
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];
|
||||
}
|
||||
|
||||
std::string BitstreamSetting::interconnect_name(const BitstreamInterconnectSettingId& interconnect_setting_id) const {
|
||||
VTR_ASSERT(true == valid_bitstream_interconnect_setting_id(interconnect_setting_id));
|
||||
std::string BitstreamSetting::interconnect_name(
|
||||
const BitstreamInterconnectSettingId& interconnect_setting_id) const {
|
||||
VTR_ASSERT(true ==
|
||||
valid_bitstream_interconnect_setting_id(interconnect_setting_id));
|
||||
return interconnect_names_[interconnect_setting_id];
|
||||
}
|
||||
|
||||
std::vector<std::string> BitstreamSetting::parent_pb_type_names(const BitstreamInterconnectSettingId& interconnect_setting_id) const {
|
||||
VTR_ASSERT(true == valid_bitstream_interconnect_setting_id(interconnect_setting_id));
|
||||
std::vector<std::string> BitstreamSetting::parent_pb_type_names(
|
||||
const BitstreamInterconnectSettingId& interconnect_setting_id) const {
|
||||
VTR_ASSERT(true ==
|
||||
valid_bitstream_interconnect_setting_id(interconnect_setting_id));
|
||||
return interconnect_parent_pb_type_names_[interconnect_setting_id];
|
||||
}
|
||||
|
||||
std::vector<std::string> BitstreamSetting::parent_mode_names(const BitstreamInterconnectSettingId& interconnect_setting_id) const {
|
||||
VTR_ASSERT(true == valid_bitstream_interconnect_setting_id(interconnect_setting_id));
|
||||
std::vector<std::string> BitstreamSetting::parent_mode_names(
|
||||
const BitstreamInterconnectSettingId& interconnect_setting_id) const {
|
||||
VTR_ASSERT(true ==
|
||||
valid_bitstream_interconnect_setting_id(interconnect_setting_id));
|
||||
return interconnect_parent_mode_names_[interconnect_setting_id];
|
||||
}
|
||||
|
||||
std::string BitstreamSetting::default_path(const BitstreamInterconnectSettingId& interconnect_setting_id) const {
|
||||
VTR_ASSERT(true == valid_bitstream_interconnect_setting_id(interconnect_setting_id));
|
||||
std::string BitstreamSetting::default_path(
|
||||
const BitstreamInterconnectSettingId& interconnect_setting_id) const {
|
||||
VTR_ASSERT(true ==
|
||||
valid_bitstream_interconnect_setting_id(interconnect_setting_id));
|
||||
return interconnect_default_paths_[interconnect_setting_id];
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Public Mutators
|
||||
***********************************************************************/
|
||||
BitstreamPbTypeSettingId BitstreamSetting::add_bitstream_pb_type_setting(const std::string& pb_type_name,
|
||||
const std::vector<std::string>& parent_pb_type_names,
|
||||
const std::vector<std::string>& parent_mode_names,
|
||||
const std::string& bitstream_source,
|
||||
const std::string& bitstream_content) {
|
||||
BitstreamPbTypeSettingId pb_type_setting_id = BitstreamPbTypeSettingId(pb_type_setting_ids_.size());
|
||||
BitstreamPbTypeSettingId BitstreamSetting::add_bitstream_pb_type_setting(
|
||||
const std::string& pb_type_name,
|
||||
const std::vector<std::string>& parent_pb_type_names,
|
||||
const std::vector<std::string>& parent_mode_names,
|
||||
const std::string& bitstream_source, const std::string& bitstream_content) {
|
||||
BitstreamPbTypeSettingId pb_type_setting_id =
|
||||
BitstreamPbTypeSettingId(pb_type_setting_ids_.size());
|
||||
pb_type_setting_ids_.push_back(pb_type_setting_id);
|
||||
pb_type_names_.push_back(pb_type_name);
|
||||
parent_pb_type_names_.push_back(parent_pb_type_names);
|
||||
|
@ -106,23 +124,27 @@ BitstreamPbTypeSettingId BitstreamSetting::add_bitstream_pb_type_setting(const s
|
|||
return pb_type_setting_id;
|
||||
}
|
||||
|
||||
void BitstreamSetting::set_mode_select_bitstream(const BitstreamPbTypeSettingId& pb_type_setting_id,
|
||||
const bool& is_mode_select_bitstream) {
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
|
||||
BitstreamInterconnectSettingId BitstreamSetting::add_bitstream_interconnect_setting(const std::string& interconnect_name,
|
||||
const std::vector<std::string>& parent_pb_type_names,
|
||||
const std::vector<std::string>& parent_mode_names,
|
||||
const std::string& default_path) {
|
||||
BitstreamInterconnectSettingId interc_setting_id = BitstreamInterconnectSettingId(interconnect_setting_ids_.size());
|
||||
BitstreamInterconnectSettingId
|
||||
BitstreamSetting::add_bitstream_interconnect_setting(
|
||||
const std::string& interconnect_name,
|
||||
const std::vector<std::string>& parent_pb_type_names,
|
||||
const std::vector<std::string>& parent_mode_names,
|
||||
const std::string& default_path) {
|
||||
BitstreamInterconnectSettingId interc_setting_id =
|
||||
BitstreamInterconnectSettingId(interconnect_setting_ids_.size());
|
||||
interconnect_setting_ids_.push_back(interc_setting_id);
|
||||
interconnect_names_.push_back(interconnect_name);
|
||||
interconnect_parent_pb_type_names_.push_back(parent_pb_type_names);
|
||||
|
@ -135,12 +157,17 @@ BitstreamInterconnectSettingId BitstreamSetting::add_bitstream_interconnect_sett
|
|||
/************************************************************************
|
||||
* Public Validators
|
||||
***********************************************************************/
|
||||
bool BitstreamSetting::valid_bitstream_pb_type_setting_id(const BitstreamPbTypeSettingId& pb_type_setting_id) const {
|
||||
return ( size_t(pb_type_setting_id) < pb_type_setting_ids_.size() ) && ( pb_type_setting_id == pb_type_setting_ids_[pb_type_setting_id] );
|
||||
bool BitstreamSetting::valid_bitstream_pb_type_setting_id(
|
||||
const BitstreamPbTypeSettingId& pb_type_setting_id) const {
|
||||
return (size_t(pb_type_setting_id) < pb_type_setting_ids_.size()) &&
|
||||
(pb_type_setting_id == pb_type_setting_ids_[pb_type_setting_id]);
|
||||
}
|
||||
|
||||
bool BitstreamSetting::valid_bitstream_interconnect_setting_id(const BitstreamInterconnectSettingId& interconnect_setting_id) const {
|
||||
return ( size_t(interconnect_setting_id) < interconnect_setting_ids_.size() ) && ( interconnect_setting_id == interconnect_setting_ids_[interconnect_setting_id] );
|
||||
bool BitstreamSetting::valid_bitstream_interconnect_setting_id(
|
||||
const BitstreamInterconnectSettingId& interconnect_setting_id) const {
|
||||
return (size_t(interconnect_setting_id) < interconnect_setting_ids_.size()) &&
|
||||
(interconnect_setting_id ==
|
||||
interconnect_setting_ids_[interconnect_setting_id]);
|
||||
}
|
||||
|
||||
} /* namespace openfpga ends */
|
||||
} // namespace openfpga
|
||||
|
|
|
@ -3,23 +3,24 @@
|
|||
|
||||
/********************************************************************
|
||||
* This file include the declaration of simulation settings
|
||||
* which are used by OpenFPGA
|
||||
* which are used by OpenFPGA
|
||||
*******************************************************************/
|
||||
#include <string>
|
||||
|
||||
#include "vtr_vector.h"
|
||||
|
||||
#include "bitstream_setting_fwd.h"
|
||||
#include "bitstream_setting_fwd.h"
|
||||
#include "vtr_vector.h"
|
||||
|
||||
/* namespace openfpga begins */
|
||||
namespace openfpga {
|
||||
|
||||
/********************************************************************
|
||||
* A data structure to describe bitstream settings
|
||||
*
|
||||
*
|
||||
* This data structure includes following types of settings:
|
||||
* - Pb type: include definiting hard coded bitstream for pb_types (LUT or configurable pb_type for mode selection)
|
||||
* - Interconnect: include defining default paths for routing multiplexers in pb_types
|
||||
* - Pb type: include definiting hard coded bitstream for pb_types (LUT or
|
||||
*configurable pb_type for mode selection)
|
||||
* - Interconnect: include defining default paths for routing multiplexers in
|
||||
*pb_types
|
||||
*
|
||||
* Typical usage:
|
||||
* --------------
|
||||
|
@ -29,74 +30,111 @@ namespace openfpga {
|
|||
*
|
||||
*******************************************************************/
|
||||
class BitstreamSetting {
|
||||
public: /* Types */
|
||||
typedef vtr::vector<BitstreamPbTypeSettingId, BitstreamPbTypeSettingId>::const_iterator bitstream_pb_type_setting_iterator;
|
||||
typedef vtr::vector<BitstreamInterconnectSettingId, BitstreamInterconnectSettingId>::const_iterator bitstream_interconnect_setting_iterator;
|
||||
/* Create range */
|
||||
typedef vtr::Range<bitstream_pb_type_setting_iterator> bitstream_pb_type_setting_range;
|
||||
typedef vtr::Range<bitstream_interconnect_setting_iterator> bitstream_interconnect_setting_range;
|
||||
public: /* Constructors */
|
||||
BitstreamSetting();
|
||||
public: /* Accessors: aggregates */
|
||||
bitstream_pb_type_setting_range pb_type_settings() const;
|
||||
bitstream_interconnect_setting_range interconnect_settings() const;
|
||||
public: /* Public Accessors */
|
||||
std::string pb_type_name(const BitstreamPbTypeSettingId& pb_type_setting_id) const;
|
||||
std::vector<std::string> parent_pb_type_names(const BitstreamPbTypeSettingId& pb_type_setting_id) const;
|
||||
std::vector<std::string> parent_mode_names(const BitstreamPbTypeSettingId& pb_type_setting_id) const;
|
||||
std::string pb_type_bitstream_source(const BitstreamPbTypeSettingId& pb_type_setting_id) const;
|
||||
std::string pb_type_bitstream_content(const BitstreamPbTypeSettingId& pb_type_setting_id) const;
|
||||
bool is_mode_select_bitstream(const BitstreamPbTypeSettingId& pb_type_setting_id) const;
|
||||
size_t bitstream_offset(const BitstreamPbTypeSettingId& pb_type_setting_id) const;
|
||||
std::string interconnect_name(const BitstreamInterconnectSettingId& interconnect_setting_id) const;
|
||||
std::vector<std::string> parent_pb_type_names(const BitstreamInterconnectSettingId& interconnect_setting_id) const;
|
||||
std::vector<std::string> parent_mode_names(const BitstreamInterconnectSettingId& interconnect_setting_id) const;
|
||||
std::string default_path(const BitstreamInterconnectSettingId& interconnect_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: /* Types */
|
||||
typedef vtr::vector<BitstreamPbTypeSettingId,
|
||||
BitstreamPbTypeSettingId>::const_iterator
|
||||
bitstream_pb_type_setting_iterator;
|
||||
typedef vtr::vector<BitstreamInterconnectSettingId,
|
||||
BitstreamInterconnectSettingId>::const_iterator
|
||||
bitstream_interconnect_setting_iterator;
|
||||
/* Create range */
|
||||
typedef vtr::Range<bitstream_pb_type_setting_iterator>
|
||||
bitstream_pb_type_setting_range;
|
||||
typedef vtr::Range<bitstream_interconnect_setting_iterator>
|
||||
bitstream_interconnect_setting_range;
|
||||
|
||||
BitstreamInterconnectSettingId add_bitstream_interconnect_setting(const std::string& interconnect_name,
|
||||
const std::vector<std::string>& parent_pb_type_names,
|
||||
const std::vector<std::string>& parent_mode_names,
|
||||
const std::string& default_path);
|
||||
public: /* Public Validators */
|
||||
bool valid_bitstream_pb_type_setting_id(const BitstreamPbTypeSettingId& pb_type_setting_id) const;
|
||||
bool valid_bitstream_interconnect_setting_id(const BitstreamInterconnectSettingId& interconnect_setting_id) const;
|
||||
private: /* Internal data */
|
||||
/* Pb type -related settings
|
||||
* - Paths to a pb_type in the pb_graph
|
||||
* - Bitstream source, data_type, offsets etc.
|
||||
*/
|
||||
vtr::vector<BitstreamPbTypeSettingId, BitstreamPbTypeSettingId> pb_type_setting_ids_;
|
||||
vtr::vector<BitstreamPbTypeSettingId, std::string> pb_type_names_;
|
||||
vtr::vector<BitstreamPbTypeSettingId, std::vector<std::string>> parent_pb_type_names_;
|
||||
vtr::vector<BitstreamPbTypeSettingId, std::vector<std::string>> parent_mode_names_;
|
||||
vtr::vector<BitstreamPbTypeSettingId, std::string> pb_type_bitstream_sources_;
|
||||
vtr::vector<BitstreamPbTypeSettingId, std::string> pb_type_bitstream_contents_;
|
||||
/* 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_;
|
||||
public: /* Constructors */
|
||||
BitstreamSetting();
|
||||
|
||||
/* Interconnect-related settings:
|
||||
* - Name of interconnect under a given pb_type
|
||||
* - The default path to be considered for a given interconnect during bitstream generation
|
||||
*/
|
||||
vtr::vector<BitstreamInterconnectSettingId, BitstreamInterconnectSettingId> interconnect_setting_ids_;
|
||||
vtr::vector<BitstreamInterconnectSettingId, std::string> interconnect_names_;
|
||||
vtr::vector<BitstreamInterconnectSettingId, std::vector<std::string>> interconnect_parent_pb_type_names_;
|
||||
vtr::vector<BitstreamInterconnectSettingId, std::vector<std::string>> interconnect_parent_mode_names_;
|
||||
vtr::vector<BitstreamInterconnectSettingId, std::string> interconnect_default_paths_;
|
||||
public: /* Accessors: aggregates */
|
||||
bitstream_pb_type_setting_range pb_type_settings() const;
|
||||
bitstream_interconnect_setting_range interconnect_settings() const;
|
||||
|
||||
public: /* Public Accessors */
|
||||
std::string pb_type_name(
|
||||
const BitstreamPbTypeSettingId& pb_type_setting_id) const;
|
||||
std::vector<std::string> parent_pb_type_names(
|
||||
const BitstreamPbTypeSettingId& pb_type_setting_id) const;
|
||||
std::vector<std::string> parent_mode_names(
|
||||
const BitstreamPbTypeSettingId& pb_type_setting_id) const;
|
||||
std::string pb_type_bitstream_source(
|
||||
const BitstreamPbTypeSettingId& pb_type_setting_id) const;
|
||||
std::string pb_type_bitstream_content(
|
||||
const BitstreamPbTypeSettingId& pb_type_setting_id) const;
|
||||
bool is_mode_select_bitstream(
|
||||
const BitstreamPbTypeSettingId& pb_type_setting_id) const;
|
||||
size_t bitstream_offset(
|
||||
const BitstreamPbTypeSettingId& pb_type_setting_id) const;
|
||||
std::string interconnect_name(
|
||||
const BitstreamInterconnectSettingId& interconnect_setting_id) const;
|
||||
std::vector<std::string> parent_pb_type_names(
|
||||
const BitstreamInterconnectSettingId& interconnect_setting_id) const;
|
||||
std::vector<std::string> parent_mode_names(
|
||||
const BitstreamInterconnectSettingId& interconnect_setting_id) const;
|
||||
std::string default_path(
|
||||
const BitstreamInterconnectSettingId& interconnect_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);
|
||||
|
||||
BitstreamInterconnectSettingId add_bitstream_interconnect_setting(
|
||||
const std::string& interconnect_name,
|
||||
const std::vector<std::string>& parent_pb_type_names,
|
||||
const std::vector<std::string>& parent_mode_names,
|
||||
const std::string& default_path);
|
||||
|
||||
public: /* Public Validators */
|
||||
bool valid_bitstream_pb_type_setting_id(
|
||||
const BitstreamPbTypeSettingId& pb_type_setting_id) const;
|
||||
bool valid_bitstream_interconnect_setting_id(
|
||||
const BitstreamInterconnectSettingId& interconnect_setting_id) const;
|
||||
|
||||
private: /* Internal data */
|
||||
/* Pb type -related settings
|
||||
* - Paths to a pb_type in the pb_graph
|
||||
* - Bitstream source, data_type, offsets etc.
|
||||
*/
|
||||
vtr::vector<BitstreamPbTypeSettingId, BitstreamPbTypeSettingId>
|
||||
pb_type_setting_ids_;
|
||||
vtr::vector<BitstreamPbTypeSettingId, std::string> pb_type_names_;
|
||||
vtr::vector<BitstreamPbTypeSettingId, std::vector<std::string>>
|
||||
parent_pb_type_names_;
|
||||
vtr::vector<BitstreamPbTypeSettingId, std::vector<std::string>>
|
||||
parent_mode_names_;
|
||||
vtr::vector<BitstreamPbTypeSettingId, std::string> pb_type_bitstream_sources_;
|
||||
vtr::vector<BitstreamPbTypeSettingId, std::string>
|
||||
pb_type_bitstream_contents_;
|
||||
/* 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_;
|
||||
|
||||
/* Interconnect-related settings:
|
||||
* - Name of interconnect under a given pb_type
|
||||
* - The default path to be considered for a given interconnect during
|
||||
* bitstream generation
|
||||
*/
|
||||
vtr::vector<BitstreamInterconnectSettingId, BitstreamInterconnectSettingId>
|
||||
interconnect_setting_ids_;
|
||||
vtr::vector<BitstreamInterconnectSettingId, std::string> interconnect_names_;
|
||||
vtr::vector<BitstreamInterconnectSettingId, std::vector<std::string>>
|
||||
interconnect_parent_pb_type_names_;
|
||||
vtr::vector<BitstreamInterconnectSettingId, std::vector<std::string>>
|
||||
interconnect_parent_mode_names_;
|
||||
vtr::vector<BitstreamInterconnectSettingId, std::string>
|
||||
interconnect_default_paths_;
|
||||
};
|
||||
|
||||
} /* namespace openfpga ends */
|
||||
} // namespace openfpga
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
/************************************************************************
|
||||
* A header file for BitstreamSetting class, including critical data declaration
|
||||
* Please include this file only for using any BitstreamSetting data structure
|
||||
* Refer to bitstream_setting.h for more details
|
||||
* Refer to bitstream_setting.h for more details
|
||||
***********************************************************************/
|
||||
|
||||
/************************************************************************
|
||||
* Create strong id for the pb_type annotation in Bitstream setting to avoid illegal type casting
|
||||
* Create strong id for the pb_type annotation in Bitstream setting to avoid
|
||||
*illegal type casting
|
||||
***********************************************************************/
|
||||
#ifndef BITSTREAM_SETTING_FWD_H
|
||||
#define BITSTREAM_SETTING_FWD_H
|
||||
|
@ -15,8 +16,10 @@
|
|||
struct bitstream_pb_type_setting_id_tag;
|
||||
struct bitstream_interconnect_setting_id_tag;
|
||||
|
||||
typedef vtr::StrongId<bitstream_pb_type_setting_id_tag> BitstreamPbTypeSettingId;
|
||||
typedef vtr::StrongId<bitstream_interconnect_setting_id_tag> BitstreamInterconnectSettingId;
|
||||
typedef vtr::StrongId<bitstream_pb_type_setting_id_tag>
|
||||
BitstreamPbTypeSettingId;
|
||||
typedef vtr::StrongId<bitstream_interconnect_setting_id_tag>
|
||||
BitstreamInterconnectSettingId;
|
||||
|
||||
/* Short declaration of class */
|
||||
class BitstreamSetting;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,37 +1,36 @@
|
|||
/* IMPORTANT:
|
||||
* The following preprocessing flags are added to
|
||||
* avoid compilation error when this headers are included in more than 1 times
|
||||
* The following preprocessing flags are added to
|
||||
* avoid compilation error when this headers are included in more than 1 times
|
||||
*/
|
||||
#ifndef CHECK_CIRCUIT_LIBRARY_H
|
||||
#define CHECK_CIRCUIT_LIBRARY_H
|
||||
|
||||
/*
|
||||
* Notes in include header files in a head file
|
||||
* Only include the neccessary header files
|
||||
* Notes in include header files in a head file
|
||||
* Only include the neccessary header files
|
||||
* that is required by the data types in the function/class declarations!
|
||||
*/
|
||||
/* Header files should be included in a sequence */
|
||||
/* Standard header files required go first */
|
||||
#include <vector>
|
||||
#include "circuit_types.h"
|
||||
|
||||
#include "circuit_library.h"
|
||||
#include "circuit_types.h"
|
||||
|
||||
/* Check points to make sure we have a valid circuit library */
|
||||
size_t check_one_circuit_model_port_required(const CircuitLibrary& circuit_lib,
|
||||
const CircuitModelId& circuit_model,
|
||||
const std::vector<enum e_circuit_model_port_type>& port_types_to_check);
|
||||
size_t check_one_circuit_model_port_required(
|
||||
const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model,
|
||||
const std::vector<enum e_circuit_model_port_type>& port_types_to_check);
|
||||
|
||||
size_t check_one_circuit_model_port_size_required(const CircuitLibrary& circuit_lib,
|
||||
const CircuitModelId& circuit_model,
|
||||
const CircuitPortId& circuit_port,
|
||||
const size_t& port_size_to_check);
|
||||
size_t check_one_circuit_model_port_size_required(
|
||||
const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model,
|
||||
const CircuitPortId& circuit_port, const size_t& port_size_to_check);
|
||||
|
||||
size_t check_one_circuit_model_port_type_and_size_required(const CircuitLibrary& circuit_lib,
|
||||
const CircuitModelId& circuit_model,
|
||||
const enum e_circuit_model_port_type& port_type_to_check,
|
||||
const size_t& num_ports_to_check,
|
||||
const size_t& port_size_to_check,
|
||||
const bool& include_global_ports);
|
||||
size_t check_one_circuit_model_port_type_and_size_required(
|
||||
const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model,
|
||||
const enum e_circuit_model_port_type& port_type_to_check,
|
||||
const size_t& num_ports_to_check, const size_t& port_size_to_check,
|
||||
const bool& include_global_ports);
|
||||
|
||||
size_t check_ff_circuit_model_ports(const CircuitLibrary& circuit_lib,
|
||||
const CircuitModelId& circuit_model);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,11 +1,11 @@
|
|||
/************************************************************************
|
||||
* A header file for CircuitLibrary class, including critical data declaration
|
||||
* Please include this file only for using any CircuitLibrary data structure
|
||||
* Refer to circuit_library.h for more details
|
||||
* Refer to circuit_library.h for more details
|
||||
***********************************************************************/
|
||||
|
||||
/************************************************************************
|
||||
* Create strong id for Circuit Models/Ports to avoid illegal type casting
|
||||
* Create strong id for Circuit Models/Ports to avoid illegal type casting
|
||||
***********************************************************************/
|
||||
#ifndef CIRCUIT_LIBRARY_FWD_H
|
||||
#define CIRCUIT_LIBRARY_FWD_H
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
/* IMPORTANT:
|
||||
* The following preprocessing flags are added to
|
||||
* avoid compilation error when this headers are included in more than 1 times
|
||||
* The following preprocessing flags are added to
|
||||
* avoid compilation error when this headers are included in more than 1 times
|
||||
*/
|
||||
#ifndef CIRCUIT_TYPES_H
|
||||
#define CIRCUIT_TYPES_H
|
||||
|
||||
#include <string>
|
||||
#include <array>
|
||||
#include <string>
|
||||
|
||||
/************************************************************************
|
||||
* This file includes basic enumeration types for circuit models
|
||||
***********************************************************************/
|
||||
/*
|
||||
* Notes in include header files in a head file
|
||||
* Only include the neccessary header files
|
||||
* Notes in include header files in a head file
|
||||
* Only include the neccessary header files
|
||||
* that is required by the data types in the function/class declarations!
|
||||
*/
|
||||
/* Header files should be included in a sequence */
|
||||
|
@ -21,81 +21,90 @@
|
|||
|
||||
/*Struct for a CIRCUIT model of a module*/
|
||||
enum e_circuit_model_type {
|
||||
CIRCUIT_MODEL_CHAN_WIRE,
|
||||
CIRCUIT_MODEL_WIRE,
|
||||
CIRCUIT_MODEL_MUX,
|
||||
CIRCUIT_MODEL_LUT,
|
||||
CIRCUIT_MODEL_FF,
|
||||
CIRCUIT_MODEL_SRAM,
|
||||
CIRCUIT_MODEL_CHAN_WIRE,
|
||||
CIRCUIT_MODEL_WIRE,
|
||||
CIRCUIT_MODEL_MUX,
|
||||
CIRCUIT_MODEL_LUT,
|
||||
CIRCUIT_MODEL_FF,
|
||||
CIRCUIT_MODEL_SRAM,
|
||||
CIRCUIT_MODEL_HARDLOGIC,
|
||||
CIRCUIT_MODEL_CCFF,
|
||||
CIRCUIT_MODEL_IOPAD,
|
||||
CIRCUIT_MODEL_INVBUF,
|
||||
CIRCUIT_MODEL_PASSGATE,
|
||||
CIRCUIT_MODEL_IOPAD,
|
||||
CIRCUIT_MODEL_INVBUF,
|
||||
CIRCUIT_MODEL_PASSGATE,
|
||||
CIRCUIT_MODEL_GATE,
|
||||
NUM_CIRCUIT_MODEL_TYPES
|
||||
};
|
||||
/* Strings correspond to each port type */
|
||||
constexpr std::array<const char*, NUM_CIRCUIT_MODEL_TYPES> CIRCUIT_MODEL_TYPE_STRING = {{"chan_wire", "wire", "mux", "lut", "ff", "sram", "hard_logic", "ccff", "iopad", "inv_buf", "pass_gate", "gate"}};
|
||||
constexpr std::array<const char*, NUM_CIRCUIT_MODEL_TYPES>
|
||||
CIRCUIT_MODEL_TYPE_STRING = {{"chan_wire", "wire", "mux", "lut", "ff", "sram",
|
||||
"hard_logic", "ccff", "iopad", "inv_buf",
|
||||
"pass_gate", "gate"}};
|
||||
|
||||
enum e_circuit_model_design_tech {
|
||||
CIRCUIT_MODEL_DESIGN_CMOS,
|
||||
CIRCUIT_MODEL_DESIGN_CMOS,
|
||||
CIRCUIT_MODEL_DESIGN_RRAM,
|
||||
NUM_CIRCUIT_MODEL_DESIGN_TECH_TYPES
|
||||
};
|
||||
/* Strings correspond to each design technology type */
|
||||
constexpr std::array<const char*, NUM_CIRCUIT_MODEL_DESIGN_TECH_TYPES> CIRCUIT_MODEL_DESIGN_TECH_TYPE_STRING = {{"cmos", "rram"}};
|
||||
constexpr std::array<const char*, NUM_CIRCUIT_MODEL_DESIGN_TECH_TYPES>
|
||||
CIRCUIT_MODEL_DESIGN_TECH_TYPE_STRING = {{"cmos", "rram"}};
|
||||
|
||||
enum e_circuit_model_structure {
|
||||
CIRCUIT_MODEL_STRUCTURE_TREE,
|
||||
CIRCUIT_MODEL_STRUCTURE_ONELEVEL,
|
||||
CIRCUIT_MODEL_STRUCTURE_MULTILEVEL,
|
||||
CIRCUIT_MODEL_STRUCTURE_TREE,
|
||||
CIRCUIT_MODEL_STRUCTURE_ONELEVEL,
|
||||
CIRCUIT_MODEL_STRUCTURE_MULTILEVEL,
|
||||
CIRCUIT_MODEL_STRUCTURE_CROSSBAR,
|
||||
NUM_CIRCUIT_MODEL_STRUCTURE_TYPES
|
||||
};
|
||||
/* Strings correspond to each type of mux structure */
|
||||
constexpr std::array<const char*, NUM_CIRCUIT_MODEL_STRUCTURE_TYPES> CIRCUIT_MODEL_STRUCTURE_TYPE_STRING = {{"tree", "one_level", "multi_level", "crossbar"}};
|
||||
constexpr std::array<const char*, NUM_CIRCUIT_MODEL_STRUCTURE_TYPES>
|
||||
CIRCUIT_MODEL_STRUCTURE_TYPE_STRING = {
|
||||
{"tree", "one_level", "multi_level", "crossbar"}};
|
||||
|
||||
enum e_circuit_model_buffer_type {
|
||||
CIRCUIT_MODEL_BUF_INV,
|
||||
CIRCUIT_MODEL_BUF_INV,
|
||||
CIRCUIT_MODEL_BUF_BUF,
|
||||
NUM_CIRCUIT_MODEL_BUF_TYPES
|
||||
};
|
||||
/* Strings correspond to each type of buffer */
|
||||
constexpr std::array<const char*, NUM_CIRCUIT_MODEL_BUF_TYPES> CIRCUIT_MODEL_BUFFER_TYPE_STRING = {{"inverter", "buffer"}};
|
||||
constexpr std::array<const char*, NUM_CIRCUIT_MODEL_BUF_TYPES>
|
||||
CIRCUIT_MODEL_BUFFER_TYPE_STRING = {{"inverter", "buffer"}};
|
||||
|
||||
enum e_circuit_model_pass_gate_logic_type {
|
||||
CIRCUIT_MODEL_PASS_GATE_TRANSMISSION,
|
||||
CIRCUIT_MODEL_PASS_GATE_TRANSMISSION,
|
||||
CIRCUIT_MODEL_PASS_GATE_TRANSISTOR,
|
||||
CIRCUIT_MODEL_PASS_GATE_RRAM, /* RRAM can be treated as a special type of pass-gate logic */
|
||||
CIRCUIT_MODEL_PASS_GATE_STDCELL, /* Standard cell as a special type of pass-gate logic */
|
||||
CIRCUIT_MODEL_PASS_GATE_RRAM, /* RRAM can be treated as a special type of
|
||||
pass-gate logic */
|
||||
CIRCUIT_MODEL_PASS_GATE_STDCELL, /* Standard cell as a special type of
|
||||
pass-gate logic */
|
||||
NUM_CIRCUIT_MODEL_PASS_GATE_TYPES
|
||||
};
|
||||
/* Strings correspond to each type of buffer */
|
||||
constexpr std::array<const char*, NUM_CIRCUIT_MODEL_PASS_GATE_TYPES> CIRCUIT_MODEL_PASSGATE_TYPE_STRING = {{"transmission_gate", "pass_transistor", "rram", "standard_cell"}};
|
||||
constexpr std::array<const char*, NUM_CIRCUIT_MODEL_PASS_GATE_TYPES>
|
||||
CIRCUIT_MODEL_PASSGATE_TYPE_STRING = {
|
||||
{"transmission_gate", "pass_transistor", "rram", "standard_cell"}};
|
||||
|
||||
enum e_circuit_model_gate_type {
|
||||
CIRCUIT_MODEL_GATE_AND,
|
||||
CIRCUIT_MODEL_GATE_AND,
|
||||
CIRCUIT_MODEL_GATE_OR,
|
||||
CIRCUIT_MODEL_GATE_MUX2,
|
||||
NUM_CIRCUIT_MODEL_GATE_TYPES
|
||||
};
|
||||
/* Strings correspond to each type of logic gate */
|
||||
constexpr std::array<const char*, NUM_CIRCUIT_MODEL_GATE_TYPES> CIRCUIT_MODEL_GATE_TYPE_STRING = {{"AND", "OR", "MUX2"}};
|
||||
constexpr std::array<const char*, NUM_CIRCUIT_MODEL_GATE_TYPES>
|
||||
CIRCUIT_MODEL_GATE_TYPE_STRING = {{"AND", "OR", "MUX2"}};
|
||||
|
||||
enum e_wire_model_type {
|
||||
WIRE_MODEL_PI,
|
||||
WIRE_MODEL_T,
|
||||
NUM_WIRE_MODEL_TYPES
|
||||
};
|
||||
enum e_wire_model_type { WIRE_MODEL_PI, WIRE_MODEL_T, NUM_WIRE_MODEL_TYPES };
|
||||
/* Strings correspond to each type of logic gate */
|
||||
constexpr std::array<const char*, NUM_WIRE_MODEL_TYPES> WIRE_MODEL_TYPE_STRING = {{"pi", "t"}};
|
||||
constexpr std::array<const char*, NUM_WIRE_MODEL_TYPES> WIRE_MODEL_TYPE_STRING =
|
||||
{{"pi", "t"}};
|
||||
|
||||
enum e_circuit_model_port_type {
|
||||
CIRCUIT_MODEL_PORT_INPUT,
|
||||
CIRCUIT_MODEL_PORT_OUTPUT,
|
||||
CIRCUIT_MODEL_PORT_INOUT,
|
||||
CIRCUIT_MODEL_PORT_CLOCK,
|
||||
CIRCUIT_MODEL_PORT_INPUT,
|
||||
CIRCUIT_MODEL_PORT_OUTPUT,
|
||||
CIRCUIT_MODEL_PORT_INOUT,
|
||||
CIRCUIT_MODEL_PORT_CLOCK,
|
||||
CIRCUIT_MODEL_PORT_SRAM,
|
||||
CIRCUIT_MODEL_PORT_BL,
|
||||
CIRCUIT_MODEL_PORT_BLB,
|
||||
|
@ -105,32 +114,37 @@ enum e_circuit_model_port_type {
|
|||
NUM_CIRCUIT_MODEL_PORT_TYPES
|
||||
};
|
||||
/* Strings correspond to each port type */
|
||||
constexpr std::array<const char*, NUM_CIRCUIT_MODEL_PORT_TYPES> CIRCUIT_MODEL_PORT_TYPE_STRING = {{"input", "output", "inout", "clock", "sram", "bl", "blb", "wl", "wlb", "wlr"}};
|
||||
constexpr std::array<const char*, NUM_CIRCUIT_MODEL_PORT_TYPES>
|
||||
CIRCUIT_MODEL_PORT_TYPE_STRING = {{"input", "output", "inout", "clock",
|
||||
"sram", "bl", "blb", "wl", "wlb", "wlr"}};
|
||||
|
||||
enum e_circuit_model_delay_type {
|
||||
CIRCUIT_MODEL_DELAY_RISE,
|
||||
CIRCUIT_MODEL_DELAY_RISE,
|
||||
CIRCUIT_MODEL_DELAY_FALL,
|
||||
NUM_CIRCUIT_MODEL_DELAY_TYPES
|
||||
};
|
||||
/* Strings correspond to each delay type */
|
||||
constexpr std::array<const char*, NUM_CIRCUIT_MODEL_DELAY_TYPES> CIRCUIT_MODEL_DELAY_TYPE_STRING = {{"rise", "fall"}};
|
||||
constexpr std::array<const char*, NUM_CIRCUIT_MODEL_DELAY_TYPES>
|
||||
CIRCUIT_MODEL_DELAY_TYPE_STRING = {{"rise", "fall"}};
|
||||
|
||||
/********************************************************************
|
||||
* Types of configuration protocol
|
||||
* 1. configurable memories are organized and accessed as standalone elements
|
||||
* 1. configurable memories are organized and accessed as standalone elements
|
||||
* 2. configurable memories are organized and accessed by a scan-chain
|
||||
* 3. configurable memories are organized and accessed by memory bank
|
||||
* 4. configurable memories are organized and accessed by frames
|
||||
* 3. configurable memories are organized and accessed by memory bank
|
||||
* 4. configurable memories are organized and accessed by frames
|
||||
*/
|
||||
enum e_config_protocol_type {
|
||||
CONFIG_MEM_STANDALONE,
|
||||
CONFIG_MEM_SCAN_CHAIN,
|
||||
CONFIG_MEM_MEMORY_BANK,
|
||||
CONFIG_MEM_QL_MEMORY_BANK,
|
||||
CONFIG_MEM_FRAME_BASED,
|
||||
CONFIG_MEM_STANDALONE,
|
||||
CONFIG_MEM_SCAN_CHAIN,
|
||||
CONFIG_MEM_MEMORY_BANK,
|
||||
CONFIG_MEM_QL_MEMORY_BANK,
|
||||
CONFIG_MEM_FRAME_BASED,
|
||||
NUM_CONFIG_PROTOCOL_TYPES
|
||||
};
|
||||
|
||||
constexpr std::array<const char*, NUM_CONFIG_PROTOCOL_TYPES> CONFIG_PROTOCOL_TYPE_STRING = {{"standalone", "scan_chain", "memory_bank", "ql_memory_bank", "frame_based"}};
|
||||
constexpr std::array<const char*, NUM_CONFIG_PROTOCOL_TYPES>
|
||||
CONFIG_PROTOCOL_TYPE_STRING = {{"standalone", "scan_chain", "memory_bank",
|
||||
"ql_memory_bank", "frame_based"}};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
#include "config_protocol.h"
|
||||
|
||||
#include "vtr_assert.h"
|
||||
#include "vtr_log.h"
|
||||
|
||||
#include "config_protocol.h"
|
||||
|
||||
/************************************************************************
|
||||
* Member functions for class ConfigProtocol
|
||||
***********************************************************************/
|
||||
|
@ -10,28 +10,20 @@
|
|||
/************************************************************************
|
||||
* Constructors
|
||||
***********************************************************************/
|
||||
ConfigProtocol::ConfigProtocol() {
|
||||
return;
|
||||
}
|
||||
ConfigProtocol::ConfigProtocol() { return; }
|
||||
|
||||
/************************************************************************
|
||||
* Public Accessors
|
||||
***********************************************************************/
|
||||
e_config_protocol_type ConfigProtocol::type() const {
|
||||
return type_;
|
||||
}
|
||||
e_config_protocol_type ConfigProtocol::type() const { return type_; }
|
||||
|
||||
std::string ConfigProtocol::memory_model_name() const {
|
||||
return memory_model_name_;
|
||||
}
|
||||
|
||||
CircuitModelId ConfigProtocol::memory_model() const {
|
||||
return memory_model_;
|
||||
}
|
||||
CircuitModelId ConfigProtocol::memory_model() const { return memory_model_; }
|
||||
|
||||
int ConfigProtocol::num_regions() const {
|
||||
return num_regions_;
|
||||
}
|
||||
int ConfigProtocol::num_regions() const { return num_regions_; }
|
||||
|
||||
e_blwl_protocol_type ConfigProtocol::bl_protocol_type() const {
|
||||
return bl_protocol_type_;
|
||||
|
@ -45,9 +37,7 @@ CircuitModelId ConfigProtocol::bl_memory_model() const {
|
|||
return bl_memory_model_;
|
||||
}
|
||||
|
||||
size_t ConfigProtocol::bl_num_banks() const {
|
||||
return bl_num_banks_;
|
||||
}
|
||||
size_t ConfigProtocol::bl_num_banks() const { return bl_num_banks_; }
|
||||
|
||||
e_blwl_protocol_type ConfigProtocol::wl_protocol_type() const {
|
||||
return wl_protocol_type_;
|
||||
|
@ -61,9 +51,7 @@ CircuitModelId ConfigProtocol::wl_memory_model() const {
|
|||
return wl_memory_model_;
|
||||
}
|
||||
|
||||
size_t ConfigProtocol::wl_num_banks() const {
|
||||
return wl_num_banks_;
|
||||
}
|
||||
size_t ConfigProtocol::wl_num_banks() const { return wl_num_banks_; }
|
||||
|
||||
/************************************************************************
|
||||
* Public Mutators
|
||||
|
@ -72,7 +60,8 @@ void ConfigProtocol::set_type(const e_config_protocol_type& type) {
|
|||
type_ = type;
|
||||
}
|
||||
|
||||
void ConfigProtocol::set_memory_model_name(const std::string& memory_model_name) {
|
||||
void ConfigProtocol::set_memory_model_name(
|
||||
const std::string& memory_model_name) {
|
||||
memory_model_name_ = memory_model_name;
|
||||
}
|
||||
|
||||
|
@ -86,15 +75,20 @@ void ConfigProtocol::set_num_regions(const int& num_regions) {
|
|||
|
||||
void ConfigProtocol::set_bl_protocol_type(const e_blwl_protocol_type& type) {
|
||||
if (CONFIG_MEM_QL_MEMORY_BANK != type_) {
|
||||
VTR_LOG_ERROR("BL protocol type is only applicable for configuration protocol '%d'", CONFIG_PROTOCOL_TYPE_STRING[type_]);
|
||||
VTR_LOG_ERROR(
|
||||
"BL protocol type is only applicable for configuration protocol '%d'",
|
||||
CONFIG_PROTOCOL_TYPE_STRING[type_]);
|
||||
return;
|
||||
}
|
||||
bl_protocol_type_ = type;
|
||||
}
|
||||
|
||||
void ConfigProtocol::set_bl_memory_model_name(const std::string& memory_model_name) {
|
||||
void ConfigProtocol::set_bl_memory_model_name(
|
||||
const std::string& memory_model_name) {
|
||||
if (BLWL_PROTOCOL_SHIFT_REGISTER != bl_protocol_type_) {
|
||||
VTR_LOG_ERROR("BL protocol memory model is only applicable when '%d' is defined", BLWL_PROTOCOL_TYPE_STRING[bl_protocol_type_]);
|
||||
VTR_LOG_ERROR(
|
||||
"BL protocol memory model is only applicable when '%d' is defined",
|
||||
BLWL_PROTOCOL_TYPE_STRING[bl_protocol_type_]);
|
||||
return;
|
||||
}
|
||||
bl_memory_model_name_ = memory_model_name;
|
||||
|
@ -102,7 +96,9 @@ void ConfigProtocol::set_bl_memory_model_name(const std::string& memory_model_na
|
|||
|
||||
void ConfigProtocol::set_bl_memory_model(const CircuitModelId& memory_model) {
|
||||
if (BLWL_PROTOCOL_SHIFT_REGISTER != bl_protocol_type_) {
|
||||
VTR_LOG_ERROR("BL protocol memory model is only applicable when '%d' is defined", BLWL_PROTOCOL_TYPE_STRING[bl_protocol_type_]);
|
||||
VTR_LOG_ERROR(
|
||||
"BL protocol memory model is only applicable when '%d' is defined",
|
||||
BLWL_PROTOCOL_TYPE_STRING[bl_protocol_type_]);
|
||||
return;
|
||||
}
|
||||
bl_memory_model_ = memory_model;
|
||||
|
@ -110,24 +106,30 @@ void ConfigProtocol::set_bl_memory_model(const CircuitModelId& memory_model) {
|
|||
|
||||
void ConfigProtocol::set_bl_num_banks(const size_t& num_banks) {
|
||||
if (BLWL_PROTOCOL_SHIFT_REGISTER != bl_protocol_type_) {
|
||||
VTR_LOG_ERROR("BL protocol memory model is only applicable when '%d' is defined", BLWL_PROTOCOL_TYPE_STRING[bl_protocol_type_]);
|
||||
VTR_LOG_ERROR(
|
||||
"BL protocol memory model is only applicable when '%d' is defined",
|
||||
BLWL_PROTOCOL_TYPE_STRING[bl_protocol_type_]);
|
||||
return;
|
||||
}
|
||||
bl_num_banks_ = num_banks;
|
||||
}
|
||||
|
||||
|
||||
void ConfigProtocol::set_wl_protocol_type(const e_blwl_protocol_type& type) {
|
||||
if (CONFIG_MEM_QL_MEMORY_BANK != type_) {
|
||||
VTR_LOG_ERROR("WL protocol type is only applicable for configuration protocol '%d'", CONFIG_PROTOCOL_TYPE_STRING[type_]);
|
||||
VTR_LOG_ERROR(
|
||||
"WL protocol type is only applicable for configuration protocol '%d'",
|
||||
CONFIG_PROTOCOL_TYPE_STRING[type_]);
|
||||
return;
|
||||
}
|
||||
wl_protocol_type_ = type;
|
||||
}
|
||||
|
||||
void ConfigProtocol::set_wl_memory_model_name(const std::string& memory_model_name) {
|
||||
void ConfigProtocol::set_wl_memory_model_name(
|
||||
const std::string& memory_model_name) {
|
||||
if (BLWL_PROTOCOL_SHIFT_REGISTER != wl_protocol_type_) {
|
||||
VTR_LOG_ERROR("WL protocol memory model is only applicable when '%d' is defined", BLWL_PROTOCOL_TYPE_STRING[wl_protocol_type_]);
|
||||
VTR_LOG_ERROR(
|
||||
"WL protocol memory model is only applicable when '%d' is defined",
|
||||
BLWL_PROTOCOL_TYPE_STRING[wl_protocol_type_]);
|
||||
return;
|
||||
}
|
||||
wl_memory_model_name_ = memory_model_name;
|
||||
|
@ -135,7 +137,9 @@ void ConfigProtocol::set_wl_memory_model_name(const std::string& memory_model_na
|
|||
|
||||
void ConfigProtocol::set_wl_memory_model(const CircuitModelId& memory_model) {
|
||||
if (BLWL_PROTOCOL_SHIFT_REGISTER != wl_protocol_type_) {
|
||||
VTR_LOG_ERROR("WL protocol memory model is only applicable when '%d' is defined", BLWL_PROTOCOL_TYPE_STRING[wl_protocol_type_]);
|
||||
VTR_LOG_ERROR(
|
||||
"WL protocol memory model is only applicable when '%d' is defined",
|
||||
BLWL_PROTOCOL_TYPE_STRING[wl_protocol_type_]);
|
||||
return;
|
||||
}
|
||||
wl_memory_model_ = memory_model;
|
||||
|
@ -143,9 +147,10 @@ void ConfigProtocol::set_wl_memory_model(const CircuitModelId& memory_model) {
|
|||
|
||||
void ConfigProtocol::set_wl_num_banks(const size_t& num_banks) {
|
||||
if (BLWL_PROTOCOL_SHIFT_REGISTER != wl_protocol_type_) {
|
||||
VTR_LOG_ERROR("WL protocol memory model is only applicable when '%d' is defined", BLWL_PROTOCOL_TYPE_STRING[wl_protocol_type_]);
|
||||
VTR_LOG_ERROR(
|
||||
"WL protocol memory model is only applicable when '%d' is defined",
|
||||
BLWL_PROTOCOL_TYPE_STRING[wl_protocol_type_]);
|
||||
return;
|
||||
}
|
||||
wl_num_banks_ = num_banks;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,8 +2,9 @@
|
|||
#define CONFIG_PROTOCOL_H
|
||||
|
||||
#include <string>
|
||||
#include "circuit_types.h"
|
||||
|
||||
#include "circuit_library_fwd.h"
|
||||
#include "circuit_types.h"
|
||||
|
||||
/* Data type to define the protocol through which BL/WL can be manipulated */
|
||||
enum e_blwl_protocol_type {
|
||||
|
@ -12,71 +13,80 @@ enum e_blwl_protocol_type {
|
|||
BLWL_PROTOCOL_SHIFT_REGISTER,
|
||||
NUM_BLWL_PROTOCOL_TYPES
|
||||
};
|
||||
constexpr std::array<const char*, NUM_BLWL_PROTOCOL_TYPES> BLWL_PROTOCOL_TYPE_STRING = {{"flatten", "decoder", "shift_register"}};
|
||||
constexpr std::array<const char*, NUM_BLWL_PROTOCOL_TYPES>
|
||||
BLWL_PROTOCOL_TYPE_STRING = {{"flatten", "decoder", "shift_register"}};
|
||||
|
||||
/********************************************************************
|
||||
* A data structure to store configuration protocol information
|
||||
*******************************************************************/
|
||||
class ConfigProtocol {
|
||||
public: /* Constructors */
|
||||
ConfigProtocol();
|
||||
public: /* Public Accessors */
|
||||
e_config_protocol_type type() const;
|
||||
std::string memory_model_name() const;
|
||||
CircuitModelId memory_model() const;
|
||||
int num_regions() const;
|
||||
public: /* Constructors */
|
||||
ConfigProtocol();
|
||||
|
||||
e_blwl_protocol_type bl_protocol_type() const;
|
||||
std::string bl_memory_model_name() const;
|
||||
CircuitModelId bl_memory_model() const;
|
||||
size_t bl_num_banks() const;
|
||||
e_blwl_protocol_type wl_protocol_type() const;
|
||||
std::string wl_memory_model_name() const;
|
||||
CircuitModelId wl_memory_model() const;
|
||||
size_t wl_num_banks() const;
|
||||
public: /* Public Mutators */
|
||||
void set_type(const e_config_protocol_type& type);
|
||||
void set_memory_model_name(const std::string& memory_model_name);
|
||||
void set_memory_model(const CircuitModelId& memory_model);
|
||||
void set_num_regions(const int& num_regions);
|
||||
public: /* Public Accessors */
|
||||
e_config_protocol_type type() const;
|
||||
std::string memory_model_name() const;
|
||||
CircuitModelId memory_model() const;
|
||||
int num_regions() const;
|
||||
|
||||
void set_bl_protocol_type(const e_blwl_protocol_type& type);
|
||||
void set_bl_memory_model_name(const std::string& memory_model_name);
|
||||
void set_bl_memory_model(const CircuitModelId& memory_model);
|
||||
void set_bl_num_banks(const size_t& num_banks);
|
||||
void set_wl_protocol_type(const e_blwl_protocol_type& type);
|
||||
void set_wl_memory_model_name(const std::string& memory_model_name);
|
||||
void set_wl_memory_model(const CircuitModelId& memory_model);
|
||||
void set_wl_num_banks(const size_t& num_banks);
|
||||
private: /* Internal data */
|
||||
/* The type of configuration protocol.
|
||||
* In other words, it is about how to organize and access each configurable memory
|
||||
*/
|
||||
e_config_protocol_type type_;
|
||||
e_blwl_protocol_type bl_protocol_type() const;
|
||||
std::string bl_memory_model_name() const;
|
||||
CircuitModelId bl_memory_model() const;
|
||||
size_t bl_num_banks() const;
|
||||
e_blwl_protocol_type wl_protocol_type() const;
|
||||
std::string wl_memory_model_name() const;
|
||||
CircuitModelId wl_memory_model() const;
|
||||
size_t wl_num_banks() const;
|
||||
|
||||
/* The circuit model of configuration memory to be used in the protocol */
|
||||
std::string memory_model_name_;
|
||||
CircuitModelId memory_model_;
|
||||
public: /* Public Mutators */
|
||||
void set_type(const e_config_protocol_type& type);
|
||||
void set_memory_model_name(const std::string& memory_model_name);
|
||||
void set_memory_model(const CircuitModelId& memory_model);
|
||||
void set_num_regions(const int& num_regions);
|
||||
|
||||
/* Number of configurable regions */
|
||||
int num_regions_;
|
||||
void set_bl_protocol_type(const e_blwl_protocol_type& type);
|
||||
void set_bl_memory_model_name(const std::string& memory_model_name);
|
||||
void set_bl_memory_model(const CircuitModelId& memory_model);
|
||||
void set_bl_num_banks(const size_t& num_banks);
|
||||
void set_wl_protocol_type(const e_blwl_protocol_type& type);
|
||||
void set_wl_memory_model_name(const std::string& memory_model_name);
|
||||
void set_wl_memory_model(const CircuitModelId& memory_model);
|
||||
void set_wl_num_banks(const size_t& num_banks);
|
||||
|
||||
/* BL & WL protocol: This is only applicable to memory-bank configuration protocols
|
||||
* - type: defines which protocol to be used. By default, we consider decoders
|
||||
* - bl/wl_memory_model: defines the circuit model to be used when building shift register chains for BL/WL configuration.
|
||||
* It must be a valid CCFF circuit model. This is only applicable when shift-register protocol is selected
|
||||
* for BL or WL.
|
||||
* - bl/wl_num_banks: defines the number of independent shift register chains (with separated head and tail ports)
|
||||
* for a given BL protocol per configuration region
|
||||
*/
|
||||
e_blwl_protocol_type bl_protocol_type_ = BLWL_PROTOCOL_DECODER;
|
||||
std::string bl_memory_model_name_;
|
||||
CircuitModelId bl_memory_model_;
|
||||
size_t bl_num_banks_;
|
||||
e_blwl_protocol_type wl_protocol_type_ = BLWL_PROTOCOL_DECODER;
|
||||
std::string wl_memory_model_name_;
|
||||
CircuitModelId wl_memory_model_;
|
||||
size_t wl_num_banks_;
|
||||
private: /* Internal data */
|
||||
/* The type of configuration protocol.
|
||||
* In other words, it is about how to organize and access each configurable
|
||||
* memory
|
||||
*/
|
||||
e_config_protocol_type type_;
|
||||
|
||||
/* The circuit model of configuration memory to be used in the protocol */
|
||||
std::string memory_model_name_;
|
||||
CircuitModelId memory_model_;
|
||||
|
||||
/* Number of configurable regions */
|
||||
int num_regions_;
|
||||
|
||||
/* BL & WL protocol: This is only applicable to memory-bank configuration
|
||||
* protocols
|
||||
* - type: defines which protocol to be used. By default, we
|
||||
* consider decoders
|
||||
* - bl/wl_memory_model: defines the circuit model to be used when building
|
||||
* shift register chains for BL/WL configuration. It must be a valid CCFF
|
||||
* circuit model. This is only applicable when shift-register protocol is
|
||||
* selected for BL or WL.
|
||||
* - bl/wl_num_banks: defines the number of independent shift register
|
||||
* chains (with separated head and tail ports) for a given BL protocol per
|
||||
* configuration region
|
||||
*/
|
||||
e_blwl_protocol_type bl_protocol_type_ = BLWL_PROTOCOL_DECODER;
|
||||
std::string bl_memory_model_name_;
|
||||
CircuitModelId bl_memory_model_;
|
||||
size_t bl_num_banks_;
|
||||
e_blwl_protocol_type wl_protocol_type_ = BLWL_PROTOCOL_DECODER;
|
||||
std::string wl_memory_model_name_;
|
||||
CircuitModelId wl_memory_model_;
|
||||
size_t wl_num_banks_;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
#ifndef OPENFPGA_ARCH_H
|
||||
#define OPENFPGA_ARCH_H
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include "circuit_library.h"
|
||||
#include "technology_library.h"
|
||||
#include "config_protocol.h"
|
||||
#include "arch_direct.h"
|
||||
#include "tile_annotation.h"
|
||||
#include "circuit_library.h"
|
||||
#include "config_protocol.h"
|
||||
#include "pb_type_annotation.h"
|
||||
#include "technology_library.h"
|
||||
#include "tile_annotation.h"
|
||||
|
||||
/* namespace openfpga begins */
|
||||
namespace openfpga {
|
||||
|
@ -17,7 +17,7 @@ namespace openfpga {
|
|||
/* A unified data structure to store circuit-level settings,
|
||||
* including circuit library, technology library and simulation parameters
|
||||
*
|
||||
* Note:
|
||||
* Note:
|
||||
* Once this struct is built by function read_xml_openfpga_arch()
|
||||
* It should be READ-ONLY! Any modification should not be applied later
|
||||
* This is to keep everything well modularized
|
||||
|
@ -25,44 +25,44 @@ namespace openfpga {
|
|||
struct Arch {
|
||||
/* Circuit models */
|
||||
CircuitLibrary circuit_lib;
|
||||
|
||||
|
||||
/* Technology devices */
|
||||
TechnologyLibrary tech_lib;
|
||||
|
||||
/* Binding between circuit models and technology models */
|
||||
std::map<CircuitModelId, TechnologyModelId> circuit_tech_binding;
|
||||
std::map<CircuitModelId, TechnologyModelId> circuit_tech_binding;
|
||||
|
||||
/* Configuration protocol settings */
|
||||
ConfigProtocol config_protocol;
|
||||
|
||||
/* Mapping from the names of routing switches
|
||||
* to circuit models in circuit library
|
||||
/* Mapping from the names of routing switches
|
||||
* to circuit models in circuit library
|
||||
*/
|
||||
std::map<std::string, CircuitModelId> cb_switch2circuit;
|
||||
std::map<std::string, CircuitModelId> sb_switch2circuit;
|
||||
|
||||
/* Mapping from the names of routing segments
|
||||
* to circuit models in circuit library
|
||||
* to circuit models in circuit library
|
||||
*/
|
||||
std::map<std::string, CircuitModelId> routing_seg2circuit;
|
||||
|
||||
/* Mapping from the names of direct connection
|
||||
* to circuit models in circuit library
|
||||
* to circuit models in circuit library
|
||||
*/
|
||||
ArchDirect arch_direct;
|
||||
|
||||
/* Physical tile annotations:
|
||||
* Global port definition for tile ports
|
||||
*/
|
||||
*/
|
||||
TileAnnotation tile_annotations;
|
||||
|
||||
/* Pb type annotations
|
||||
/* Pb type annotations
|
||||
* Bind from operating to physical
|
||||
* Bind from physical to circuit model
|
||||
*/
|
||||
std::vector<PbTypeAnnotation> pb_type_annotations;
|
||||
};
|
||||
|
||||
} /* namespace openfpga ends */
|
||||
} // namespace openfpga
|
||||
|
||||
#endif
|
||||
|
|
|
@ -2,48 +2,56 @@
|
|||
* This file includes the functions that build links between
|
||||
* data structures inside the openfpga arch data structure
|
||||
*******************************************************************/
|
||||
#include "vtr_log.h"
|
||||
#include "vtr_assert.h"
|
||||
|
||||
#include "openfpga_arch_linker.h"
|
||||
|
||||
#include "vtr_assert.h"
|
||||
#include "vtr_log.h"
|
||||
|
||||
/********************************************************************
|
||||
* Link the circuit model inside configuration protocol
|
||||
* to these circuit models defined in circuit library
|
||||
*******************************************************************/
|
||||
void link_config_protocol_to_circuit_library(openfpga::Arch& openfpga_arch) {
|
||||
CircuitModelId config_memory_model = openfpga_arch.circuit_lib.model(openfpga_arch.config_protocol.memory_model_name());
|
||||
CircuitModelId config_memory_model = openfpga_arch.circuit_lib.model(
|
||||
openfpga_arch.config_protocol.memory_model_name());
|
||||
|
||||
/* Error out if the circuit model id is invalid */
|
||||
if (CircuitModelId::INVALID() == config_memory_model) {
|
||||
VTR_LOG("Invalid memory model name '%s' defined in <configuration_protocol>!",
|
||||
openfpga_arch.config_protocol.memory_model_name().c_str());
|
||||
VTR_LOG(
|
||||
"Invalid memory model name '%s' defined in <configuration_protocol>!",
|
||||
openfpga_arch.config_protocol.memory_model_name().c_str());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
openfpga_arch.config_protocol.set_memory_model(config_memory_model);
|
||||
openfpga_arch.config_protocol.set_memory_model(config_memory_model);
|
||||
|
||||
/* Optional: we need to bind the memory model for BL/WL protocols */
|
||||
if (!openfpga_arch.config_protocol.bl_memory_model_name().empty()) {
|
||||
CircuitModelId bl_memory_model = openfpga_arch.circuit_lib.model(openfpga_arch.config_protocol.bl_memory_model_name());
|
||||
CircuitModelId bl_memory_model = openfpga_arch.circuit_lib.model(
|
||||
openfpga_arch.config_protocol.bl_memory_model_name());
|
||||
/* Error out if the circuit model id is invalid */
|
||||
if (CircuitModelId::INVALID() == bl_memory_model) {
|
||||
VTR_LOG("Invalid bl memory model name '%s' defined in <configuration_protocol>!",
|
||||
openfpga_arch.config_protocol.bl_memory_model_name().c_str());
|
||||
VTR_LOG(
|
||||
"Invalid bl memory model name '%s' defined in "
|
||||
"<configuration_protocol>!",
|
||||
openfpga_arch.config_protocol.bl_memory_model_name().c_str());
|
||||
exit(1);
|
||||
}
|
||||
openfpga_arch.config_protocol.set_bl_memory_model(bl_memory_model);
|
||||
openfpga_arch.config_protocol.set_bl_memory_model(bl_memory_model);
|
||||
}
|
||||
|
||||
if (!openfpga_arch.config_protocol.wl_memory_model_name().empty()) {
|
||||
CircuitModelId wl_memory_model = openfpga_arch.circuit_lib.model(openfpga_arch.config_protocol.wl_memory_model_name());
|
||||
CircuitModelId wl_memory_model = openfpga_arch.circuit_lib.model(
|
||||
openfpga_arch.config_protocol.wl_memory_model_name());
|
||||
/* Error out if the circuit model id is invalid */
|
||||
if (CircuitModelId::INVALID() == wl_memory_model) {
|
||||
VTR_LOG("Invalid wl memory model name '%s' defined in <configuration_protocol>!",
|
||||
openfpga_arch.config_protocol.wl_memory_model_name().c_str());
|
||||
VTR_LOG(
|
||||
"Invalid wl memory model name '%s' defined in "
|
||||
"<configuration_protocol>!",
|
||||
openfpga_arch.config_protocol.wl_memory_model_name().c_str());
|
||||
exit(1);
|
||||
}
|
||||
openfpga_arch.config_protocol.set_wl_memory_model(wl_memory_model);
|
||||
openfpga_arch.config_protocol.set_wl_memory_model(wl_memory_model);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -55,13 +63,16 @@ void bind_circuit_model_to_technology_model(openfpga::Arch& openfpga_arch) {
|
|||
/* Ensure a clean start */
|
||||
openfpga_arch.circuit_tech_binding.clear();
|
||||
|
||||
for (const CircuitModelId& circuit_model : openfpga_arch.circuit_lib.models()) {
|
||||
const std::string device_model_name = openfpga_arch.circuit_lib.device_model_name(circuit_model);
|
||||
for (const CircuitModelId& circuit_model :
|
||||
openfpga_arch.circuit_lib.models()) {
|
||||
const std::string device_model_name =
|
||||
openfpga_arch.circuit_lib.device_model_name(circuit_model);
|
||||
if (true == device_model_name.empty()) {
|
||||
continue;
|
||||
}
|
||||
/* Try to find the device model name in technology library */
|
||||
TechnologyModelId tech_model = openfpga_arch.tech_lib.model(device_model_name);
|
||||
TechnologyModelId tech_model =
|
||||
openfpga_arch.tech_lib.model(device_model_name);
|
||||
if (false == openfpga_arch.tech_lib.valid_model_id(tech_model)) {
|
||||
VTR_LOG("Invalid device model name '%s' defined in circuit model '%s'!",
|
||||
device_model_name.c_str(),
|
||||
|
@ -78,10 +89,10 @@ void bind_circuit_model_to_technology_model(openfpga::Arch& openfpga_arch) {
|
|||
* to a default SRAM circuit model.
|
||||
* This function aims to ease the XML writing, allowing users to skip
|
||||
* the circuit model definition for SRAM ports that are used by default
|
||||
* TODO: Maybe deprecated as we prefer strict definition
|
||||
* TODO: Maybe deprecated as we prefer strict definition
|
||||
*******************************************************************/
|
||||
void config_circuit_models_sram_port_to_default_sram_model(CircuitLibrary& circuit_lib,
|
||||
const CircuitModelId& default_sram_model) {
|
||||
void config_circuit_models_sram_port_to_default_sram_model(
|
||||
CircuitLibrary& circuit_lib, const CircuitModelId& default_sram_model) {
|
||||
VTR_ASSERT(CircuitModelId::INVALID() != default_sram_model);
|
||||
|
||||
for (const auto& model : circuit_lib.models()) {
|
||||
|
@ -94,26 +105,32 @@ void config_circuit_models_sram_port_to_default_sram_model(CircuitLibrary& circu
|
|||
/* Write for the default SRAM SPICE model! */
|
||||
circuit_lib.set_port_tri_state_model_id(port, default_sram_model);
|
||||
|
||||
/* Only show warning when we try to override the given spice_model_name ! */
|
||||
if (true == circuit_lib.port_tri_state_model_name(port).empty()) {
|
||||
VTR_LOG("Use the default configurable memory model '%s' for circuit model '%s' port '%s')\n",
|
||||
circuit_lib.model_name(default_sram_model).c_str(),
|
||||
circuit_lib.model_name(model).c_str(),
|
||||
circuit_lib.port_prefix(port).c_str());
|
||||
/* Only show warning when we try to override the given spice_model_name !
|
||||
*/
|
||||
if (true == circuit_lib.port_tri_state_model_name(port).empty()) {
|
||||
VTR_LOG(
|
||||
"Use the default configurable memory model '%s' for circuit model "
|
||||
"'%s' port '%s')\n",
|
||||
circuit_lib.model_name(default_sram_model).c_str(),
|
||||
circuit_lib.model_name(model).c_str(),
|
||||
circuit_lib.port_prefix(port).c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Give a warning !!! */
|
||||
if (circuit_lib.model_name(default_sram_model) != circuit_lib.port_tri_state_model_name(port)) {
|
||||
VTR_LOG_WARN("Overwrite SRAM circuit model for circuit model port (name:%s, port:%s) to be the correct one (name:%s)!\n",
|
||||
circuit_lib.model_name(model).c_str(),
|
||||
circuit_lib.port_prefix(port).c_str(),
|
||||
circuit_lib.model_name(default_sram_model).c_str());
|
||||
if (circuit_lib.model_name(default_sram_model) !=
|
||||
circuit_lib.port_tri_state_model_name(port)) {
|
||||
VTR_LOG_WARN(
|
||||
"Overwrite SRAM circuit model for circuit model port (name:%s, "
|
||||
"port:%s) to be the correct one (name:%s)!\n",
|
||||
circuit_lib.model_name(model).c_str(),
|
||||
circuit_lib.port_prefix(port).c_str(),
|
||||
circuit_lib.model_name(default_sram_model).c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Rebuild the submodels for circuit_library
|
||||
* because we have created links for ports
|
||||
* because we have created links for ports
|
||||
*/
|
||||
circuit_lib.build_model_links();
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ void link_config_protocol_to_circuit_library(openfpga::Arch& openfpga_arch);
|
|||
|
||||
void bind_circuit_model_to_technology_model(openfpga::Arch& openfpga_arch);
|
||||
|
||||
void config_circuit_models_sram_port_to_default_sram_model(CircuitLibrary& circuit_lib,
|
||||
const CircuitModelId& default_sram_model);
|
||||
void config_circuit_models_sram_port_to_default_sram_model(
|
||||
CircuitLibrary& circuit_lib, const CircuitModelId& default_sram_model);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
/************************************************************************
|
||||
* Member functions for class PbTypeAnnotation
|
||||
***********************************************************************/
|
||||
#include <algorithm>
|
||||
#include "vtr_log.h"
|
||||
#include "vtr_assert.h"
|
||||
#include "pb_type_annotation.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "vtr_assert.h"
|
||||
#include "vtr_log.h"
|
||||
|
||||
/* namespace openfpga begins */
|
||||
namespace openfpga {
|
||||
|
||||
/************************************************************************
|
||||
* Constructors
|
||||
***********************************************************************/
|
||||
PbTypeAnnotation::PbTypeAnnotation() {
|
||||
return;
|
||||
}
|
||||
PbTypeAnnotation::PbTypeAnnotation() { return; }
|
||||
|
||||
/************************************************************************
|
||||
* Public Accessors
|
||||
|
@ -23,7 +23,8 @@ std::string PbTypeAnnotation::operating_pb_type_name() const {
|
|||
return operating_pb_type_name_;
|
||||
}
|
||||
|
||||
std::vector<std::string> PbTypeAnnotation::operating_parent_pb_type_names() const {
|
||||
std::vector<std::string> PbTypeAnnotation::operating_parent_pb_type_names()
|
||||
const {
|
||||
return operating_parent_pb_type_names_;
|
||||
}
|
||||
|
||||
|
@ -32,16 +33,16 @@ std::vector<std::string> PbTypeAnnotation::operating_parent_mode_names() const {
|
|||
}
|
||||
|
||||
bool PbTypeAnnotation::is_operating_pb_type() const {
|
||||
return (false == operating_pb_type_name_.empty())
|
||||
&& (false == physical_pb_type_name_.empty());
|
||||
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 {
|
||||
std::vector<std::string> PbTypeAnnotation::physical_parent_pb_type_names()
|
||||
const {
|
||||
return physical_parent_pb_type_names_;
|
||||
}
|
||||
|
||||
|
@ -50,21 +51,17 @@ std::vector<std::string> PbTypeAnnotation::physical_parent_mode_names() const {
|
|||
}
|
||||
|
||||
bool PbTypeAnnotation::is_physical_pb_type() const {
|
||||
return (true == operating_pb_type_name_.empty())
|
||||
&& (false == physical_pb_type_name_.empty());
|
||||
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::idle_mode_name() const { return idle_mode_name_; }
|
||||
|
||||
std::vector<size_t> PbTypeAnnotation::mode_bits() const {
|
||||
return mode_bits_;
|
||||
}
|
||||
std::vector<size_t> PbTypeAnnotation::mode_bits() const { return mode_bits_; }
|
||||
|
||||
std::string PbTypeAnnotation::circuit_model_name() const {
|
||||
return circuit_model_name_;
|
||||
|
@ -86,8 +83,10 @@ std::vector<std::string> PbTypeAnnotation::port_names() const {
|
|||
return keys;
|
||||
}
|
||||
|
||||
std::map<BasicPort, std::array<int, 3>> PbTypeAnnotation::physical_pb_type_port(const std::string& port_name) const {
|
||||
std::map<std::string, std::map<BasicPort, std::array<int, 3>>>::const_iterator it = operating_pb_type_ports_.find(port_name);
|
||||
std::map<BasicPort, std::array<int, 3>> PbTypeAnnotation::physical_pb_type_port(
|
||||
const std::string& port_name) const {
|
||||
std::map<std::string, std::map<BasicPort, std::array<int, 3>>>::const_iterator
|
||||
it = operating_pb_type_ports_.find(port_name);
|
||||
if (it == operating_pb_type_ports_.end()) {
|
||||
/* Return an empty port */
|
||||
return std::map<BasicPort, std::array<int, 3>>();
|
||||
|
@ -103,8 +102,10 @@ std::vector<std::string> PbTypeAnnotation::interconnect_names() const {
|
|||
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);
|
||||
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();
|
||||
}
|
||||
|
@ -119,11 +120,13 @@ 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) {
|
||||
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) {
|
||||
void PbTypeAnnotation::set_operating_parent_mode_names(
|
||||
const std::vector<std::string>& names) {
|
||||
operating_parent_mode_names_ = names;
|
||||
}
|
||||
|
||||
|
@ -131,11 +134,13 @@ 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) {
|
||||
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) {
|
||||
void PbTypeAnnotation::set_physical_parent_mode_names(
|
||||
const std::vector<std::string>& names) {
|
||||
physical_parent_mode_names_ = names;
|
||||
}
|
||||
|
||||
|
@ -166,28 +171,35 @@ void PbTypeAnnotation::set_physical_pb_type_index_offset(const int& value) {
|
|||
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) {
|
||||
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, std::map<BasicPort, std::array<int, 3>>>::const_iterator it = operating_pb_type_ports_.find(operating_pb_port_name);
|
||||
std::map<std::string, std::map<BasicPort, std::array<int, 3>>>::const_iterator
|
||||
it = operating_pb_type_ports_.find(operating_pb_port_name);
|
||||
|
||||
/* If not exist, initialize and set a default value */
|
||||
if (it == operating_pb_type_ports_.end()) {
|
||||
operating_pb_type_ports_[operating_pb_port_name][physical_pb_port] = {0, 0, 0};
|
||||
operating_pb_type_ports_[operating_pb_port_name][physical_pb_port] = {0, 0,
|
||||
0};
|
||||
/* We can return early */
|
||||
return;
|
||||
}
|
||||
|
||||
/* If the physical port is not in the list, we create one and set a default value */
|
||||
if (0 == operating_pb_type_ports_[operating_pb_port_name].count(physical_pb_port)) {
|
||||
operating_pb_type_ports_[operating_pb_port_name][physical_pb_port] = {0, 0, 0};
|
||||
/* If the physical port is not in the list, we create one and set a default
|
||||
* value */
|
||||
if (0 == operating_pb_type_ports_[operating_pb_port_name].count(
|
||||
physical_pb_port)) {
|
||||
operating_pb_type_ports_[operating_pb_port_name][physical_pb_port] = {0, 0,
|
||||
0};
|
||||
}
|
||||
}
|
||||
|
||||
void PbTypeAnnotation::set_physical_pin_initial_offset(const std::string& operating_pb_port_name,
|
||||
const BasicPort& physical_pb_port,
|
||||
const int& physical_pin_initial_offset) {
|
||||
std::map<std::string, std::map<BasicPort, std::array<int, 3>>>::const_iterator it = operating_pb_type_ports_.find(operating_pb_port_name);
|
||||
void PbTypeAnnotation::set_physical_pin_initial_offset(
|
||||
const std::string& operating_pb_port_name, const BasicPort& physical_pb_port,
|
||||
const int& physical_pin_initial_offset) {
|
||||
std::map<std::string, std::map<BasicPort, std::array<int, 3>>>::const_iterator
|
||||
it = operating_pb_type_ports_.find(operating_pb_port_name);
|
||||
|
||||
if (it == operating_pb_type_ports_.end()) {
|
||||
VTR_LOG_ERROR("The operating pb_type port '%s' is not valid!\n",
|
||||
|
@ -195,22 +207,25 @@ void PbTypeAnnotation::set_physical_pin_initial_offset(const std::string& operat
|
|||
exit(1);
|
||||
}
|
||||
|
||||
if (operating_pb_type_ports_[operating_pb_port_name].end() == operating_pb_type_ports_[operating_pb_port_name].find(physical_pb_port)) {
|
||||
VTR_LOG_ERROR("The physical pb_type port '%s[%lu:%lu]' definition for operating pb_type port '%s' is not valid!\n",
|
||||
physical_pb_port.get_name().c_str(),
|
||||
physical_pb_port.get_lsb(),
|
||||
physical_pb_port.get_msb(),
|
||||
operating_pb_port_name.c_str());
|
||||
if (operating_pb_type_ports_[operating_pb_port_name].end() ==
|
||||
operating_pb_type_ports_[operating_pb_port_name].find(physical_pb_port)) {
|
||||
VTR_LOG_ERROR(
|
||||
"The physical pb_type port '%s[%lu:%lu]' definition for operating "
|
||||
"pb_type port '%s' is not valid!\n",
|
||||
physical_pb_port.get_name().c_str(), physical_pb_port.get_lsb(),
|
||||
physical_pb_port.get_msb(), operating_pb_port_name.c_str());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
operating_pb_type_ports_[operating_pb_port_name][physical_pb_port][0] = physical_pin_initial_offset;
|
||||
operating_pb_type_ports_[operating_pb_port_name][physical_pb_port][0] =
|
||||
physical_pin_initial_offset;
|
||||
}
|
||||
|
||||
void PbTypeAnnotation::set_physical_pin_rotate_offset(const std::string& operating_pb_port_name,
|
||||
const BasicPort& physical_pb_port,
|
||||
const int& physical_pin_rotate_offset) {
|
||||
std::map<std::string, std::map<BasicPort, std::array<int, 3>>>::const_iterator it = operating_pb_type_ports_.find(operating_pb_port_name);
|
||||
void PbTypeAnnotation::set_physical_pin_rotate_offset(
|
||||
const std::string& operating_pb_port_name, const BasicPort& physical_pb_port,
|
||||
const int& physical_pin_rotate_offset) {
|
||||
std::map<std::string, std::map<BasicPort, std::array<int, 3>>>::const_iterator
|
||||
it = operating_pb_type_ports_.find(operating_pb_port_name);
|
||||
|
||||
if (it == operating_pb_type_ports_.end()) {
|
||||
VTR_LOG_ERROR("The operating pb_type port '%s' is not valid!\n",
|
||||
|
@ -218,22 +233,25 @@ void PbTypeAnnotation::set_physical_pin_rotate_offset(const std::string& operati
|
|||
exit(1);
|
||||
}
|
||||
|
||||
if (operating_pb_type_ports_[operating_pb_port_name].end() == operating_pb_type_ports_[operating_pb_port_name].find(physical_pb_port)) {
|
||||
VTR_LOG_ERROR("The physical pb_type port '%s[%lu:%lu]' definition for operating pb_type port '%s' is not valid!\n",
|
||||
physical_pb_port.get_name().c_str(),
|
||||
physical_pb_port.get_lsb(),
|
||||
physical_pb_port.get_msb(),
|
||||
operating_pb_port_name.c_str());
|
||||
if (operating_pb_type_ports_[operating_pb_port_name].end() ==
|
||||
operating_pb_type_ports_[operating_pb_port_name].find(physical_pb_port)) {
|
||||
VTR_LOG_ERROR(
|
||||
"The physical pb_type port '%s[%lu:%lu]' definition for operating "
|
||||
"pb_type port '%s' is not valid!\n",
|
||||
physical_pb_port.get_name().c_str(), physical_pb_port.get_lsb(),
|
||||
physical_pb_port.get_msb(), operating_pb_port_name.c_str());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
operating_pb_type_ports_[operating_pb_port_name][physical_pb_port][1] = physical_pin_rotate_offset;
|
||||
operating_pb_type_ports_[operating_pb_port_name][physical_pb_port][1] =
|
||||
physical_pin_rotate_offset;
|
||||
}
|
||||
|
||||
void PbTypeAnnotation::set_physical_port_rotate_offset(const std::string& operating_pb_port_name,
|
||||
const BasicPort& physical_pb_port,
|
||||
const int& physical_port_rotate_offset) {
|
||||
std::map<std::string, std::map<BasicPort, std::array<int, 3>>>::const_iterator it = operating_pb_type_ports_.find(operating_pb_port_name);
|
||||
void PbTypeAnnotation::set_physical_port_rotate_offset(
|
||||
const std::string& operating_pb_port_name, const BasicPort& physical_pb_port,
|
||||
const int& physical_port_rotate_offset) {
|
||||
std::map<std::string, std::map<BasicPort, std::array<int, 3>>>::const_iterator
|
||||
it = operating_pb_type_ports_.find(operating_pb_port_name);
|
||||
|
||||
if (it == operating_pb_type_ports_.end()) {
|
||||
VTR_LOG_ERROR("The operating pb_type port '%s' is not valid!\n",
|
||||
|
@ -241,22 +259,24 @@ void PbTypeAnnotation::set_physical_port_rotate_offset(const std::string& operat
|
|||
exit(1);
|
||||
}
|
||||
|
||||
if (operating_pb_type_ports_[operating_pb_port_name].end() == operating_pb_type_ports_[operating_pb_port_name].find(physical_pb_port)) {
|
||||
VTR_LOG_ERROR("The physical pb_type port '%s[%lu:%lu]' definition for operating pb_type port '%s' is not valid!\n",
|
||||
physical_pb_port.get_name().c_str(),
|
||||
physical_pb_port.get_lsb(),
|
||||
physical_pb_port.get_msb(),
|
||||
operating_pb_port_name.c_str());
|
||||
if (operating_pb_type_ports_[operating_pb_port_name].end() ==
|
||||
operating_pb_type_ports_[operating_pb_port_name].find(physical_pb_port)) {
|
||||
VTR_LOG_ERROR(
|
||||
"The physical pb_type port '%s[%lu:%lu]' definition for operating "
|
||||
"pb_type port '%s' is not valid!\n",
|
||||
physical_pb_port.get_name().c_str(), physical_pb_port.get_lsb(),
|
||||
physical_pb_port.get_msb(), operating_pb_port_name.c_str());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
operating_pb_type_ports_[operating_pb_port_name][physical_pb_port][2] = physical_port_rotate_offset;
|
||||
operating_pb_type_ports_[operating_pb_port_name][physical_pb_port][2] =
|
||||
physical_port_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);
|
||||
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",
|
||||
|
@ -266,4 +286,4 @@ void PbTypeAnnotation::add_interconnect_circuit_model_pair(const std::string& in
|
|||
interconnect_circuit_model_names_[interc_name] = circuit_model_name;
|
||||
}
|
||||
|
||||
} /* namespace openfpga ends */
|
||||
} // namespace openfpga
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
/********************************************************************
|
||||
* Include header files required by the data structure definition
|
||||
*******************************************************************/
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <array>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include "openfpga_port.h"
|
||||
|
||||
|
@ -31,157 +31,165 @@ namespace openfpga {
|
|||
* 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::vector<size_t> mode_bits() const;
|
||||
std::string circuit_model_name() const;
|
||||
float physical_pb_type_index_factor() const;
|
||||
int physical_pb_type_index_offset() const;
|
||||
std::vector<std::string> port_names() const;
|
||||
std::map<BasicPort, std::array<int, 3>> physical_pb_type_port(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::vector<size_t>& mode_bits);
|
||||
void set_circuit_model_name(const std::string& name);
|
||||
void set_physical_pb_type_index_factor(const float& 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_initial_offset(const std::string& operating_pb_port_name,
|
||||
const BasicPort& physical_pb_port,
|
||||
const int& physical_pin_initial_offset);
|
||||
void set_physical_pin_rotate_offset(const std::string& operating_pb_port_name,
|
||||
const BasicPort& physical_pb_port,
|
||||
const int& physical_pin_rotate_offset);
|
||||
void set_physical_port_rotate_offset(const std::string& operating_pb_port_name,
|
||||
const BasicPort& physical_pb_port,
|
||||
const int& physical_port_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_;
|
||||
public: /* Constructor */
|
||||
PbTypeAnnotation();
|
||||
|
||||
std::string physical_pb_type_name_;
|
||||
std::vector<std::string> physical_parent_pb_type_names_;
|
||||
std::vector<std::string> physical_parent_mode_names_;
|
||||
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::vector<size_t> mode_bits() const;
|
||||
std::string circuit_model_name() const;
|
||||
float physical_pb_type_index_factor() const;
|
||||
int physical_pb_type_index_offset() const;
|
||||
std::vector<std::string> port_names() const;
|
||||
std::map<BasicPort, std::array<int, 3>> physical_pb_type_port(
|
||||
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;
|
||||
|
||||
/* Identify which mode is the physical implementation of an operating pb_type */
|
||||
std::string physical_mode_name_;
|
||||
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::vector<size_t>& mode_bits);
|
||||
void set_circuit_model_name(const std::string& name);
|
||||
void set_physical_pb_type_index_factor(const float& 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_initial_offset(
|
||||
const std::string& operating_pb_port_name,
|
||||
const BasicPort& physical_pb_port, const int& physical_pin_initial_offset);
|
||||
void set_physical_pin_rotate_offset(const std::string& operating_pb_port_name,
|
||||
const BasicPort& physical_pb_port,
|
||||
const int& physical_pin_rotate_offset);
|
||||
void set_physical_port_rotate_offset(
|
||||
const std::string& operating_pb_port_name,
|
||||
const BasicPort& physical_pb_port, const int& physical_port_rotate_offset);
|
||||
void add_interconnect_circuit_model_pair(
|
||||
const std::string& interc_name, const std::string& circuit_model_name);
|
||||
|
||||
/* Identify in which mode is the pb_type will operate when it is not used */
|
||||
std::string idle_mode_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_;
|
||||
|
||||
/* Configuration bits to select an operting mode for the circuit mode name */
|
||||
std::vector<size_t> mode_bits_;
|
||||
std::string physical_pb_type_name_;
|
||||
std::vector<std::string> physical_parent_pb_type_names_;
|
||||
std::vector<std::string> physical_parent_mode_names_;
|
||||
|
||||
/* Circuit mode name linked to a physical pb_type.
|
||||
* This is only applicable to the physical pb_type
|
||||
*/
|
||||
std::string circuit_model_name_;
|
||||
/* Identify which mode is the physical implementation of an operating pb_type
|
||||
*/
|
||||
std::string physical_mode_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]
|
||||
*/
|
||||
float physical_pb_type_index_factor_;
|
||||
/* Identify in which mode is the pb_type will operate when it is not used */
|
||||
std::string idle_mode_name_;
|
||||
|
||||
/* 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_;
|
||||
/* Configuration bits to select an operting mode for the circuit mode name */
|
||||
std::vector<size_t> mode_bits_;
|
||||
|
||||
/* Link from the pins under an operating pb_type to pairs of
|
||||
* its physical pb_type and
|
||||
* - its pin initial offset: the first element of the std::array
|
||||
* - pin-level rotating offset: the second element of the std::array
|
||||
* - port-level rotating offset: the third element of the std::array
|
||||
*
|
||||
* The offsets aim 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 initial offset of -32 is used to map
|
||||
* operating pb_type bram[0].dout[32] with a full path memory[dual_port].bram[0]
|
||||
* operating pb_type bram[0].dout[33] with a full path memory[dual_port].bram[0]
|
||||
* to
|
||||
* physical pb_type bram[0].dout_a[0] with a full path memory[physical].bram[0]
|
||||
* physical pb_type bram[0].dout_a[1] with a full path memory[physical].bram[0]
|
||||
*
|
||||
* For example, a pin-level rotating offset of 9 is used to map
|
||||
* operating pb_type mult_9x9[0].a[0] with a full path mult[frac].mult_9x9[0]
|
||||
* operating pb_type mult_9x9[0].a[1] with a full path mult[frac].mult_9x9[1]
|
||||
* to
|
||||
* physical pb_type mult_36x36.a[0] with a full path mult[physical].mult_36x36[0]
|
||||
* physical pb_type mult_36x36.a[9] with a full path mult[physical].mult_36x36[0]
|
||||
*
|
||||
* For example, a port-level rotating offset of 9 is used to map
|
||||
* operating pb_type mult_9x9[0].a[0:8] with a full path mult[frac].mult_9x9[0]
|
||||
* operating pb_type mult_9x9[1].a[0:8] with a full path mult[frac].mult_9x9[1]
|
||||
* to
|
||||
* physical pb_type mult_36x36.a[0:8] with a full path mult[physical].mult_36x36[0]
|
||||
* physical pb_type mult_36x36.a[9:17] with a full path mult[physical].mult_36x36[0]
|
||||
*/
|
||||
std::map<std::string, std::map<BasicPort, std::array<int, 3>>> operating_pb_type_ports_;
|
||||
/* Circuit mode name linked to a physical pb_type.
|
||||
* This is only applicable to the physical pb_type
|
||||
*/
|
||||
std::string circuit_model_name_;
|
||||
|
||||
/* Link between the interconnects under this pb_type and circuit model names */
|
||||
std::map<std::string, std::string> interconnect_circuit_model_names_;
|
||||
/* 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]
|
||||
*/
|
||||
float 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 pairs of
|
||||
* its physical pb_type and
|
||||
* - its pin initial offset: the first element of the std::array
|
||||
* - pin-level rotating offset: the second element of the std::array
|
||||
* - port-level rotating offset: the third element of the std::array
|
||||
*
|
||||
* The offsets aim 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 initial offset of -32 is used to map
|
||||
* operating pb_type bram[0].dout[32] with a full path
|
||||
* memory[dual_port].bram[0] operating pb_type bram[0].dout[33] with a full
|
||||
* path memory[dual_port].bram[0] to physical pb_type bram[0].dout_a[0] with a
|
||||
* full path memory[physical].bram[0] physical pb_type bram[0].dout_a[1] with
|
||||
* a full path memory[physical].bram[0]
|
||||
*
|
||||
* For example, a pin-level rotating offset of 9 is used to map
|
||||
* operating pb_type mult_9x9[0].a[0] with a full path
|
||||
* mult[frac].mult_9x9[0] operating pb_type mult_9x9[0].a[1] with a full path
|
||||
* mult[frac].mult_9x9[1] to physical pb_type mult_36x36.a[0] with a full path
|
||||
* mult[physical].mult_36x36[0] physical pb_type mult_36x36.a[9] with a full
|
||||
* path mult[physical].mult_36x36[0]
|
||||
*
|
||||
* For example, a port-level rotating offset of 9 is used to map
|
||||
* operating pb_type mult_9x9[0].a[0:8] with a full path
|
||||
* mult[frac].mult_9x9[0] operating pb_type mult_9x9[1].a[0:8] with a full
|
||||
* path mult[frac].mult_9x9[1] to physical pb_type mult_36x36.a[0:8] with a
|
||||
* full path mult[physical].mult_36x36[0] physical pb_type mult_36x36.a[9:17]
|
||||
* with a full path mult[physical].mult_36x36[0]
|
||||
*/
|
||||
std::map<std::string, std::map<BasicPort, std::array<int, 3>>>
|
||||
operating_pb_type_ports_;
|
||||
|
||||
/* 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 */
|
||||
} // namespace openfpga
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -17,64 +17,70 @@
|
|||
|
||||
/* Headers from libarchfpga */
|
||||
#include "arch_error.h"
|
||||
#include "read_xml_util.h"
|
||||
|
||||
#include "read_xml_bitstream_setting.h"
|
||||
#include "read_xml_util.h"
|
||||
|
||||
/********************************************************************
|
||||
* Parse XML description for a pb_type annotation under a <pb_type> XML node
|
||||
*******************************************************************/
|
||||
static
|
||||
void read_xml_bitstream_pb_type_setting(pugi::xml_node& xml_pb_type,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
openfpga::BitstreamSetting& bitstream_setting) {
|
||||
const std::string& name_attr = get_attribute(xml_pb_type, "name", loc_data).as_string();
|
||||
const std::string& source_attr = get_attribute(xml_pb_type, "source", loc_data).as_string();
|
||||
const std::string& content_attr = get_attribute(xml_pb_type, "content", loc_data).as_string();
|
||||
static void read_xml_bitstream_pb_type_setting(
|
||||
pugi::xml_node& xml_pb_type, const pugiutil::loc_data& loc_data,
|
||||
openfpga::BitstreamSetting& bitstream_setting) {
|
||||
const std::string& name_attr =
|
||||
get_attribute(xml_pb_type, "name", loc_data).as_string();
|
||||
const std::string& source_attr =
|
||||
get_attribute(xml_pb_type, "source", loc_data).as_string();
|
||||
const std::string& content_attr =
|
||||
get_attribute(xml_pb_type, "content", loc_data).as_string();
|
||||
|
||||
/* Parse the attributes for operating pb_type */
|
||||
openfpga::PbParser operating_pb_parser(name_attr);
|
||||
|
||||
/* Add to bitstream setting */
|
||||
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);
|
||||
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 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);
|
||||
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);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Parse XML description for a pb_type annotation under a <interconect> XML node
|
||||
*******************************************************************/
|
||||
static
|
||||
void read_xml_bitstream_interconnect_setting(pugi::xml_node& xml_pb_type,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
openfpga::BitstreamSetting& bitstream_setting) {
|
||||
const std::string& name_attr = get_attribute(xml_pb_type, "name", loc_data).as_string();
|
||||
const std::string& default_path_attr = get_attribute(xml_pb_type, "default_path", loc_data).as_string();
|
||||
static void read_xml_bitstream_interconnect_setting(
|
||||
pugi::xml_node& xml_pb_type, const pugiutil::loc_data& loc_data,
|
||||
openfpga::BitstreamSetting& bitstream_setting) {
|
||||
const std::string& name_attr =
|
||||
get_attribute(xml_pb_type, "name", loc_data).as_string();
|
||||
const std::string& default_path_attr =
|
||||
get_attribute(xml_pb_type, "default_path", loc_data).as_string();
|
||||
|
||||
/* Parse the attributes for operating pb_type */
|
||||
openfpga::PbParser operating_pb_parser(name_attr);
|
||||
|
||||
/* Add to bitstream setting */
|
||||
bitstream_setting.add_bitstream_interconnect_setting(operating_pb_parser.leaf(),
|
||||
operating_pb_parser.parents(),
|
||||
operating_pb_parser.modes(),
|
||||
default_path_attr);
|
||||
bitstream_setting.add_bitstream_interconnect_setting(
|
||||
operating_pb_parser.leaf(), operating_pb_parser.parents(),
|
||||
operating_pb_parser.modes(), default_path_attr);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Parse XML codes about <openfpga_bitstream_setting> to an object
|
||||
*******************************************************************/
|
||||
openfpga::BitstreamSetting read_xml_bitstream_setting(pugi::xml_node& Node,
|
||||
const pugiutil::loc_data& loc_data) {
|
||||
openfpga::BitstreamSetting read_xml_bitstream_setting(
|
||||
pugi::xml_node& Node, const pugiutil::loc_data& loc_data) {
|
||||
openfpga::BitstreamSetting bitstream_setting;
|
||||
|
||||
/* Iterate over the children under this node,
|
||||
|
@ -82,18 +88,20 @@ openfpga::BitstreamSetting read_xml_bitstream_setting(pugi::xml_node& Node,
|
|||
*/
|
||||
for (pugi::xml_node xml_child : Node.children()) {
|
||||
/* Error out if the XML child has an invalid name! */
|
||||
if ( (xml_child.name() != std::string("pb_type"))
|
||||
&& (xml_child.name() != std::string("interconnect")) ) {
|
||||
if ((xml_child.name() != std::string("pb_type")) &&
|
||||
(xml_child.name() != std::string("interconnect"))) {
|
||||
bad_tag(xml_child, loc_data, Node, {"pb_type | interconnect"});
|
||||
}
|
||||
|
||||
if (xml_child.name() == std::string("pb_type")) {
|
||||
read_xml_bitstream_pb_type_setting(xml_child, loc_data, bitstream_setting);
|
||||
read_xml_bitstream_pb_type_setting(xml_child, loc_data,
|
||||
bitstream_setting);
|
||||
} else {
|
||||
VTR_ASSERT_SAFE(xml_child.name() == std::string("interconnect"));
|
||||
read_xml_bitstream_interconnect_setting(xml_child, loc_data, bitstream_setting);
|
||||
read_xml_bitstream_interconnect_setting(xml_child, loc_data,
|
||||
bitstream_setting);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bitstream_setting;
|
||||
}
|
||||
|
|
|
@ -4,15 +4,15 @@
|
|||
/********************************************************************
|
||||
* Include header files that are required by function declaration
|
||||
*******************************************************************/
|
||||
#include "pugixml_util.hpp"
|
||||
#include "pugixml.hpp"
|
||||
#include "bitstream_setting.h"
|
||||
#include "pugixml.hpp"
|
||||
#include "pugixml_util.hpp"
|
||||
|
||||
/********************************************************************
|
||||
* Function declaration
|
||||
*******************************************************************/
|
||||
|
||||
openfpga::BitstreamSetting read_xml_bitstream_setting(pugi::xml_node& Node,
|
||||
const pugiutil::loc_data& loc_data);
|
||||
openfpga::BitstreamSetting read_xml_bitstream_setting(
|
||||
pugi::xml_node& Node, const pugiutil::loc_data& loc_data);
|
||||
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -4,9 +4,9 @@
|
|||
/********************************************************************
|
||||
* Include header files that are required by function declaration
|
||||
*******************************************************************/
|
||||
#include "pugixml_util.hpp"
|
||||
#include "pugixml.hpp"
|
||||
#include "circuit_library.h"
|
||||
#include "pugixml.hpp"
|
||||
#include "pugixml_util.hpp"
|
||||
|
||||
/********************************************************************
|
||||
* Function declaration
|
||||
|
|
|
@ -14,19 +14,17 @@
|
|||
|
||||
/* Headers from libarchfpga */
|
||||
#include "arch_error.h"
|
||||
#include "read_xml_util.h"
|
||||
|
||||
#include "read_xml_config_protocol.h"
|
||||
#include "read_xml_util.h"
|
||||
|
||||
/********************************************************************
|
||||
* Convert string to the enumerate of configuration protocol type
|
||||
*******************************************************************/
|
||||
static
|
||||
e_config_protocol_type string_to_config_protocol_type(const std::string& type_string) {
|
||||
|
||||
static e_config_protocol_type string_to_config_protocol_type(
|
||||
const std::string& type_string) {
|
||||
for (size_t itype = 0; itype < NUM_CONFIG_PROTOCOL_TYPES; ++itype) {
|
||||
if (std::string(CONFIG_PROTOCOL_TYPE_STRING[itype]) == type_string) {
|
||||
return static_cast<e_config_protocol_type>(itype);
|
||||
return static_cast<e_config_protocol_type>(itype);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -36,12 +34,11 @@ e_config_protocol_type string_to_config_protocol_type(const std::string& type_st
|
|||
/********************************************************************
|
||||
* Convert string to the enumerate of BL/WL protocol type
|
||||
*******************************************************************/
|
||||
static
|
||||
e_blwl_protocol_type string_to_blwl_protocol_type(const std::string& type_string) {
|
||||
|
||||
static e_blwl_protocol_type string_to_blwl_protocol_type(
|
||||
const std::string& type_string) {
|
||||
for (size_t itype = 0; itype < NUM_BLWL_PROTOCOL_TYPES; ++itype) {
|
||||
if (std::string(BLWL_PROTOCOL_TYPE_STRING[itype]) == type_string) {
|
||||
return static_cast<e_blwl_protocol_type>(itype);
|
||||
return static_cast<e_blwl_protocol_type>(itype);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -51,19 +48,19 @@ e_blwl_protocol_type string_to_blwl_protocol_type(const std::string& type_string
|
|||
/********************************************************************
|
||||
* Parse XML codes of a <bl> to an object of configuration protocol
|
||||
*******************************************************************/
|
||||
static
|
||||
void read_xml_bl_protocol(pugi::xml_node& xml_bl_protocol,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
ConfigProtocol& config_protocol) {
|
||||
static void read_xml_bl_protocol(pugi::xml_node& xml_bl_protocol,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
ConfigProtocol& config_protocol) {
|
||||
/* Find the type of configuration protocol */
|
||||
const char* type_attr = get_attribute(xml_bl_protocol, "protocol", loc_data).value();
|
||||
const char* type_attr =
|
||||
get_attribute(xml_bl_protocol, "protocol", loc_data).value();
|
||||
/* Translate the type of design technology to enumerate */
|
||||
e_blwl_protocol_type blwl_protocol_type = string_to_blwl_protocol_type(std::string(type_attr));
|
||||
e_blwl_protocol_type blwl_protocol_type =
|
||||
string_to_blwl_protocol_type(std::string(type_attr));
|
||||
|
||||
if (NUM_BLWL_PROTOCOL_TYPES == blwl_protocol_type) {
|
||||
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_bl_protocol),
|
||||
"Invalid 'protocol' attribute '%s'\n",
|
||||
type_attr);
|
||||
"Invalid 'protocol' attribute '%s'\n", type_attr);
|
||||
}
|
||||
|
||||
config_protocol.set_bl_protocol_type(blwl_protocol_type);
|
||||
|
@ -73,27 +70,32 @@ void read_xml_bl_protocol(pugi::xml_node& xml_bl_protocol,
|
|||
* - Find the number of shift register chains for each protocol
|
||||
*/
|
||||
if (BLWL_PROTOCOL_SHIFT_REGISTER == blwl_protocol_type) {
|
||||
config_protocol.set_bl_memory_model_name(get_attribute(xml_bl_protocol, "circuit_model_name", loc_data).as_string());
|
||||
config_protocol.set_bl_num_banks(get_attribute(xml_bl_protocol, "num_banks", loc_data, pugiutil::ReqOpt::OPTIONAL).as_int(1));
|
||||
config_protocol.set_bl_memory_model_name(
|
||||
get_attribute(xml_bl_protocol, "circuit_model_name", loc_data)
|
||||
.as_string());
|
||||
config_protocol.set_bl_num_banks(get_attribute(xml_bl_protocol, "num_banks",
|
||||
loc_data,
|
||||
pugiutil::ReqOpt::OPTIONAL)
|
||||
.as_int(1));
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Parse XML codes of a <wl> to an object of configuration protocol
|
||||
*******************************************************************/
|
||||
static
|
||||
void read_xml_wl_protocol(pugi::xml_node& xml_wl_protocol,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
ConfigProtocol& config_protocol) {
|
||||
static void read_xml_wl_protocol(pugi::xml_node& xml_wl_protocol,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
ConfigProtocol& config_protocol) {
|
||||
/* Find the type of configuration protocol */
|
||||
const char* type_attr = get_attribute(xml_wl_protocol, "protocol", loc_data).value();
|
||||
const char* type_attr =
|
||||
get_attribute(xml_wl_protocol, "protocol", loc_data).value();
|
||||
/* Translate the type of design technology to enumerate */
|
||||
e_blwl_protocol_type blwl_protocol_type = string_to_blwl_protocol_type(std::string(type_attr));
|
||||
e_blwl_protocol_type blwl_protocol_type =
|
||||
string_to_blwl_protocol_type(std::string(type_attr));
|
||||
|
||||
if (NUM_BLWL_PROTOCOL_TYPES == blwl_protocol_type) {
|
||||
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_wl_protocol),
|
||||
"Invalid 'protocol' attribute '%s'\n",
|
||||
type_attr);
|
||||
"Invalid 'protocol' attribute '%s'\n", type_attr);
|
||||
}
|
||||
|
||||
config_protocol.set_wl_protocol_type(blwl_protocol_type);
|
||||
|
@ -103,60 +105,75 @@ void read_xml_wl_protocol(pugi::xml_node& xml_wl_protocol,
|
|||
* - Find the number of shift register chains for each protocol
|
||||
*/
|
||||
if (BLWL_PROTOCOL_SHIFT_REGISTER == blwl_protocol_type) {
|
||||
config_protocol.set_wl_memory_model_name(get_attribute(xml_wl_protocol, "circuit_model_name", loc_data).as_string());
|
||||
config_protocol.set_wl_num_banks(get_attribute(xml_wl_protocol, "num_banks", loc_data, pugiutil::ReqOpt::OPTIONAL).as_int(1));
|
||||
config_protocol.set_wl_memory_model_name(
|
||||
get_attribute(xml_wl_protocol, "circuit_model_name", loc_data)
|
||||
.as_string());
|
||||
config_protocol.set_wl_num_banks(get_attribute(xml_wl_protocol, "num_banks",
|
||||
loc_data,
|
||||
pugiutil::ReqOpt::OPTIONAL)
|
||||
.as_int(1));
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Parse XML codes of a <organization> to an object of configuration protocol
|
||||
*******************************************************************/
|
||||
static
|
||||
void read_xml_config_organization(pugi::xml_node& xml_config_orgz,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
ConfigProtocol& config_protocol) {
|
||||
static void read_xml_config_organization(pugi::xml_node& xml_config_orgz,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
ConfigProtocol& config_protocol) {
|
||||
/* Find the type of configuration protocol */
|
||||
const char* type_attr = get_attribute(xml_config_orgz, "type", loc_data).value();
|
||||
const char* type_attr =
|
||||
get_attribute(xml_config_orgz, "type", loc_data).value();
|
||||
/* Translate the type of design technology to enumerate */
|
||||
e_config_protocol_type config_orgz_type = string_to_config_protocol_type(std::string(type_attr));
|
||||
e_config_protocol_type config_orgz_type =
|
||||
string_to_config_protocol_type(std::string(type_attr));
|
||||
|
||||
if (NUM_CONFIG_PROTOCOL_TYPES == config_orgz_type) {
|
||||
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_config_orgz),
|
||||
"Invalid 'type' attribute '%s'\n",
|
||||
type_attr);
|
||||
"Invalid 'type' attribute '%s'\n", type_attr);
|
||||
}
|
||||
|
||||
config_protocol.set_type(config_orgz_type);
|
||||
|
||||
/* Find the circuit model used by the configuration protocol */
|
||||
config_protocol.set_memory_model_name(get_attribute(xml_config_orgz, "circuit_model_name", loc_data).as_string());
|
||||
config_protocol.set_memory_model_name(
|
||||
get_attribute(xml_config_orgz, "circuit_model_name", loc_data).as_string());
|
||||
|
||||
/* Parse the number of configurable regions
|
||||
* At least 1 region should be defined, otherwise error out
|
||||
* At least 1 region should be defined, otherwise error out
|
||||
*/
|
||||
config_protocol.set_num_regions(get_attribute(xml_config_orgz, "num_regions", loc_data, pugiutil::ReqOpt::OPTIONAL).as_int(1));
|
||||
config_protocol.set_num_regions(get_attribute(xml_config_orgz, "num_regions",
|
||||
loc_data,
|
||||
pugiutil::ReqOpt::OPTIONAL)
|
||||
.as_int(1));
|
||||
if (1 > config_protocol.num_regions()) {
|
||||
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_config_orgz),
|
||||
"Invalid 'num_region=%d' definition. At least 1 region should be defined!\n",
|
||||
"Invalid 'num_region=%d' definition. At least 1 region "
|
||||
"should be defined!\n",
|
||||
config_protocol.num_regions());
|
||||
}
|
||||
|
||||
/* Parse BL & WL protocols */
|
||||
if (config_protocol.type() == CONFIG_MEM_QL_MEMORY_BANK) {
|
||||
pugi::xml_node xml_bl_protocol = get_single_child(xml_config_orgz, "bl", loc_data, pugiutil::ReqOpt::OPTIONAL);
|
||||
pugi::xml_node xml_bl_protocol = get_single_child(
|
||||
xml_config_orgz, "bl", loc_data, pugiutil::ReqOpt::OPTIONAL);
|
||||
if (xml_bl_protocol) {
|
||||
read_xml_bl_protocol(xml_bl_protocol, loc_data, config_protocol);
|
||||
}
|
||||
|
||||
pugi::xml_node xml_wl_protocol = get_single_child(xml_config_orgz, "wl", loc_data, pugiutil::ReqOpt::OPTIONAL);
|
||||
pugi::xml_node xml_wl_protocol = get_single_child(
|
||||
xml_config_orgz, "wl", loc_data, pugiutil::ReqOpt::OPTIONAL);
|
||||
if (xml_wl_protocol) {
|
||||
read_xml_wl_protocol(xml_wl_protocol, loc_data, config_protocol);
|
||||
}
|
||||
|
||||
/* Throw an execption if the BL/WL protocols are different. We currently do not support it! */
|
||||
if (config_protocol.bl_protocol_type() != config_protocol.wl_protocol_type()) {
|
||||
|
||||
/* Throw an execption if the BL/WL protocols are different. We currently do
|
||||
* not support it! */
|
||||
if (config_protocol.bl_protocol_type() !=
|
||||
config_protocol.wl_protocol_type()) {
|
||||
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_config_orgz),
|
||||
"Expect same type of protocol for both BL and WL! Other combinations are not supported yet\n");
|
||||
"Expect same type of protocol for both BL and WL! Other "
|
||||
"combinations are not supported yet\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -169,11 +186,12 @@ ConfigProtocol read_xml_config_protocol(pugi::xml_node& Node,
|
|||
ConfigProtocol config_protocol;
|
||||
|
||||
/* Parse configuration protocol root node */
|
||||
pugi::xml_node xml_config = get_single_child(Node, "configuration_protocol", loc_data);
|
||||
pugi::xml_node xml_config =
|
||||
get_single_child(Node, "configuration_protocol", loc_data);
|
||||
|
||||
pugi::xml_node xml_config_orgz = get_single_child(xml_config, "organization", loc_data);
|
||||
pugi::xml_node xml_config_orgz =
|
||||
get_single_child(xml_config, "organization", loc_data);
|
||||
read_xml_config_organization(xml_config_orgz, loc_data, config_protocol);
|
||||
|
||||
return config_protocol;
|
||||
}
|
||||
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
/********************************************************************
|
||||
* Include header files that are required by function declaration
|
||||
*******************************************************************/
|
||||
#include "pugixml_util.hpp"
|
||||
#include "pugixml.hpp"
|
||||
#include "config_protocol.h"
|
||||
#include "pugixml.hpp"
|
||||
#include "pugixml_util.hpp"
|
||||
|
||||
/********************************************************************
|
||||
* Function declaration
|
||||
|
|
|
@ -14,18 +14,17 @@
|
|||
|
||||
/* Headers from libarchfpga */
|
||||
#include "arch_error.h"
|
||||
#include "read_xml_util.h"
|
||||
|
||||
#include "read_xml_technology_library.h"
|
||||
#include "read_xml_circuit_library.h"
|
||||
#include "read_xml_simulation_setting.h"
|
||||
#include "read_xml_config_protocol.h"
|
||||
#include "read_xml_routing_circuit.h"
|
||||
#include "read_xml_tile_annotation.h"
|
||||
#include "read_xml_pb_type_annotation.h"
|
||||
#include "read_xml_bitstream_setting.h"
|
||||
#include "read_xml_openfpga_arch.h"
|
||||
#include "openfpga_arch_linker.h"
|
||||
#include "read_xml_bitstream_setting.h"
|
||||
#include "read_xml_circuit_library.h"
|
||||
#include "read_xml_config_protocol.h"
|
||||
#include "read_xml_openfpga_arch.h"
|
||||
#include "read_xml_pb_type_annotation.h"
|
||||
#include "read_xml_routing_circuit.h"
|
||||
#include "read_xml_simulation_setting.h"
|
||||
#include "read_xml_technology_library.h"
|
||||
#include "read_xml_tile_annotation.h"
|
||||
#include "read_xml_util.h"
|
||||
|
||||
/********************************************************************
|
||||
* Top-level function to parse an XML file and load data to :
|
||||
|
@ -46,26 +45,31 @@ openfpga::Arch read_xml_openfpga_arch(const char* arch_file_name) {
|
|||
loc_data = pugiutil::load_xml(doc, arch_file_name);
|
||||
|
||||
/* First node should be <openfpga_architecture> */
|
||||
auto xml_openfpga_arch = get_single_child(doc, "openfpga_architecture", loc_data);
|
||||
auto xml_openfpga_arch =
|
||||
get_single_child(doc, "openfpga_architecture", loc_data);
|
||||
|
||||
/* Parse circuit_models to circuit library
|
||||
* under the node <module_circuit_models>
|
||||
/* Parse circuit_models to circuit library
|
||||
* under the node <module_circuit_models>
|
||||
*/
|
||||
auto xml_circuit_models = get_single_child(xml_openfpga_arch, "circuit_library", loc_data);
|
||||
openfpga_arch.circuit_lib = read_xml_circuit_library(xml_circuit_models, loc_data);
|
||||
auto xml_circuit_models =
|
||||
get_single_child(xml_openfpga_arch, "circuit_library", loc_data);
|
||||
openfpga_arch.circuit_lib =
|
||||
read_xml_circuit_library(xml_circuit_models, loc_data);
|
||||
|
||||
/* Automatically identify the default models for circuit library */
|
||||
openfpga_arch.circuit_lib.auto_detect_default_models();
|
||||
|
||||
/* Build the internal links for the circuit library */
|
||||
openfpga_arch.circuit_lib.build_model_links();
|
||||
|
||||
|
||||
/* Build the timing graph inside the circuit library */
|
||||
openfpga_arch.circuit_lib.build_timing_graphs();
|
||||
|
||||
/* Parse technology library */
|
||||
auto xml_tech_lib = get_single_child(xml_openfpga_arch, "technology_library", loc_data);
|
||||
openfpga_arch.tech_lib = read_xml_technology_library(xml_tech_lib, loc_data);
|
||||
auto xml_tech_lib =
|
||||
get_single_child(xml_openfpga_arch, "technology_library", loc_data);
|
||||
openfpga_arch.tech_lib =
|
||||
read_xml_technology_library(xml_tech_lib, loc_data);
|
||||
/* Build the internal link for technology library */
|
||||
openfpga_arch.tech_lib.link_models_to_variations();
|
||||
|
||||
|
@ -73,47 +77,49 @@ openfpga::Arch read_xml_openfpga_arch(const char* arch_file_name) {
|
|||
bind_circuit_model_to_technology_model(openfpga_arch);
|
||||
|
||||
/* Parse configuration protocol to data structure */
|
||||
openfpga_arch.config_protocol = read_xml_config_protocol(xml_openfpga_arch, loc_data);
|
||||
openfpga_arch.config_protocol =
|
||||
read_xml_config_protocol(xml_openfpga_arch, loc_data);
|
||||
|
||||
/* Build the internal link between configuration protocol and circuit library */
|
||||
/* Build the internal link between configuration protocol and circuit
|
||||
* library */
|
||||
link_config_protocol_to_circuit_library(openfpga_arch);
|
||||
|
||||
/* Now, we can know the default configurable memory model
|
||||
/* Now, we can know the default configurable memory model
|
||||
* Apply it to all the SRAM ports of circuit models
|
||||
*/
|
||||
config_circuit_models_sram_port_to_default_sram_model(openfpga_arch.circuit_lib,
|
||||
openfpga_arch.config_protocol.memory_model());
|
||||
|
||||
config_circuit_models_sram_port_to_default_sram_model(
|
||||
openfpga_arch.circuit_lib, openfpga_arch.config_protocol.memory_model());
|
||||
|
||||
/* Parse the connection block circuit definition */
|
||||
openfpga_arch.cb_switch2circuit = read_xml_cb_switch_circuit(xml_openfpga_arch, loc_data,
|
||||
openfpga_arch.circuit_lib);
|
||||
openfpga_arch.cb_switch2circuit = read_xml_cb_switch_circuit(
|
||||
xml_openfpga_arch, loc_data, openfpga_arch.circuit_lib);
|
||||
|
||||
/* Parse the connection block circuit definition */
|
||||
openfpga_arch.cb_switch2circuit = read_xml_cb_switch_circuit(xml_openfpga_arch, loc_data,
|
||||
openfpga_arch.circuit_lib);
|
||||
openfpga_arch.cb_switch2circuit = read_xml_cb_switch_circuit(
|
||||
xml_openfpga_arch, loc_data, openfpga_arch.circuit_lib);
|
||||
|
||||
/* Parse the switch block circuit definition */
|
||||
openfpga_arch.sb_switch2circuit = read_xml_sb_switch_circuit(xml_openfpga_arch, loc_data,
|
||||
openfpga_arch.circuit_lib);
|
||||
openfpga_arch.sb_switch2circuit = read_xml_sb_switch_circuit(
|
||||
xml_openfpga_arch, loc_data, openfpga_arch.circuit_lib);
|
||||
|
||||
/* Parse the routing segment circuit definition */
|
||||
openfpga_arch.routing_seg2circuit = read_xml_routing_segment_circuit(xml_openfpga_arch, loc_data,
|
||||
openfpga_arch.circuit_lib);
|
||||
openfpga_arch.routing_seg2circuit = read_xml_routing_segment_circuit(
|
||||
xml_openfpga_arch, loc_data, openfpga_arch.circuit_lib);
|
||||
|
||||
/* Parse the direct circuit definition */
|
||||
openfpga_arch.arch_direct = read_xml_direct_circuit(xml_openfpga_arch, loc_data,
|
||||
openfpga_arch.circuit_lib);
|
||||
openfpga_arch.arch_direct = read_xml_direct_circuit(
|
||||
xml_openfpga_arch, loc_data, openfpga_arch.circuit_lib);
|
||||
|
||||
/* Parse the pb_type annotation */
|
||||
openfpga_arch.tile_annotations = read_xml_tile_annotations(xml_openfpga_arch, loc_data);
|
||||
openfpga_arch.tile_annotations =
|
||||
read_xml_tile_annotations(xml_openfpga_arch, loc_data);
|
||||
|
||||
/* Parse the pb_type annotation */
|
||||
openfpga_arch.pb_type_annotations = read_xml_pb_type_annotations(xml_openfpga_arch, loc_data);
|
||||
openfpga_arch.pb_type_annotations =
|
||||
read_xml_pb_type_annotations(xml_openfpga_arch, loc_data);
|
||||
|
||||
} catch (pugiutil::XmlError& e) {
|
||||
archfpga_throw(arch_file_name, e.line(),
|
||||
"%s", e.what());
|
||||
archfpga_throw(arch_file_name, e.line(), "%s", e.what());
|
||||
}
|
||||
|
||||
return openfpga_arch;
|
||||
|
@ -122,7 +128,8 @@ openfpga::Arch read_xml_openfpga_arch(const char* arch_file_name) {
|
|||
/********************************************************************
|
||||
* Top-level function to parse an XML file and load data to simulation settings
|
||||
*******************************************************************/
|
||||
openfpga::SimulationSetting read_xml_openfpga_simulation_settings(const char* sim_setting_file_name) {
|
||||
openfpga::SimulationSetting read_xml_openfpga_simulation_settings(
|
||||
const char* sim_setting_file_name) {
|
||||
vtr::ScopedStartFinishTimer timer("Read OpenFPGA simulation settings");
|
||||
|
||||
openfpga::SimulationSetting openfpga_sim_setting;
|
||||
|
@ -137,23 +144,25 @@ openfpga::SimulationSetting read_xml_openfpga_simulation_settings(const char* si
|
|||
loc_data = pugiutil::load_xml(doc, sim_setting_file_name);
|
||||
|
||||
/* Second node should be <openfpga_simulation_setting> */
|
||||
auto xml_simulation_settings = get_single_child(doc, "openfpga_simulation_setting", loc_data);
|
||||
auto xml_simulation_settings =
|
||||
get_single_child(doc, "openfpga_simulation_setting", loc_data);
|
||||
|
||||
/* Parse simulation settings to data structure */
|
||||
openfpga_sim_setting = read_xml_simulation_setting(xml_simulation_settings, loc_data);
|
||||
openfpga_sim_setting =
|
||||
read_xml_simulation_setting(xml_simulation_settings, loc_data);
|
||||
|
||||
} catch (pugiutil::XmlError& e) {
|
||||
archfpga_throw(sim_setting_file_name, e.line(),
|
||||
"%s", e.what());
|
||||
archfpga_throw(sim_setting_file_name, e.line(), "%s", e.what());
|
||||
}
|
||||
|
||||
return openfpga_sim_setting;
|
||||
return openfpga_sim_setting;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Top-level function to parse an XML file and load data to bitstream settings
|
||||
*******************************************************************/
|
||||
openfpga::BitstreamSetting read_xml_openfpga_bitstream_settings(const char* bitstream_setting_file_name) {
|
||||
openfpga::BitstreamSetting read_xml_openfpga_bitstream_settings(
|
||||
const char* bitstream_setting_file_name) {
|
||||
vtr::ScopedStartFinishTimer timer("Read OpenFPGA bitstream settings");
|
||||
|
||||
openfpga::BitstreamSetting openfpga_bitstream_setting;
|
||||
|
@ -168,16 +177,16 @@ openfpga::BitstreamSetting read_xml_openfpga_bitstream_settings(const char* bits
|
|||
loc_data = pugiutil::load_xml(doc, bitstream_setting_file_name);
|
||||
|
||||
/* Second node should be <openfpga_simulation_setting> */
|
||||
auto xml_bitstream_settings = get_single_child(doc, "openfpga_bitstream_setting", loc_data);
|
||||
auto xml_bitstream_settings =
|
||||
get_single_child(doc, "openfpga_bitstream_setting", loc_data);
|
||||
|
||||
/* Parse simulation settings to data structure */
|
||||
openfpga_bitstream_setting = read_xml_bitstream_setting(xml_bitstream_settings, loc_data);
|
||||
openfpga_bitstream_setting =
|
||||
read_xml_bitstream_setting(xml_bitstream_settings, loc_data);
|
||||
|
||||
} catch (pugiutil::XmlError& e) {
|
||||
archfpga_throw(bitstream_setting_file_name, e.line(),
|
||||
"%s", e.what());
|
||||
archfpga_throw(bitstream_setting_file_name, e.line(), "%s", e.what());
|
||||
}
|
||||
|
||||
return openfpga_bitstream_setting;
|
||||
return openfpga_bitstream_setting;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,17 +5,20 @@
|
|||
* Include header files that are required by function declaration
|
||||
*******************************************************************/
|
||||
#include <string>
|
||||
|
||||
#include "bitstream_setting.h"
|
||||
#include "openfpga_arch.h"
|
||||
#include "simulation_setting.h"
|
||||
#include "bitstream_setting.h"
|
||||
|
||||
/********************************************************************
|
||||
* Function declaration
|
||||
*******************************************************************/
|
||||
openfpga::Arch read_xml_openfpga_arch(const char* arch_file_name);
|
||||
|
||||
openfpga::SimulationSetting read_xml_openfpga_simulation_settings(const char* sim_setting_file_name);
|
||||
openfpga::SimulationSetting read_xml_openfpga_simulation_settings(
|
||||
const char* sim_setting_file_name);
|
||||
|
||||
openfpga::BitstreamSetting read_xml_openfpga_bitstream_settings(const char* bitstream_setting_file_name);
|
||||
openfpga::BitstreamSetting read_xml_openfpga_bitstream_settings(
|
||||
const char* bitstream_setting_file_name);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -13,47 +13,49 @@
|
|||
#include "vtr_assert.h"
|
||||
|
||||
/* Headers from openfpga util library */
|
||||
#include "openfpga_port_parser.h"
|
||||
#include "openfpga_pb_parser.h"
|
||||
#include "openfpga_port_parser.h"
|
||||
|
||||
/* Headers from libarchfpga */
|
||||
#include "arch_error.h"
|
||||
#include "read_xml_pb_type_annotation.h"
|
||||
#include "read_xml_util.h"
|
||||
|
||||
#include "read_xml_pb_type_annotation.h"
|
||||
|
||||
/********************************************************************
|
||||
* Parse XML description for an interconnection annotation
|
||||
* 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) {
|
||||
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
|
||||
* 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();
|
||||
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);
|
||||
pb_type_annotation.add_interconnect_circuit_model_pair(
|
||||
name_attr, circuit_model_name_attr);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Parse XML description for a pb_type port annotation
|
||||
* 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) {
|
||||
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();
|
||||
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();
|
||||
|
||||
/* Split the physical mode port attributes with space */
|
||||
openfpga::StringToken port_tokenizer(physical_mode_port_attr);
|
||||
|
@ -61,82 +63,91 @@ void read_xml_pb_port_annotation(pugi::xml_node& xml_port,
|
|||
|
||||
/* Parse the mode port using openfpga port parser */
|
||||
for (const auto& physical_mode_port : physical_mode_ports) {
|
||||
openfpga::PortParser port_parser(physical_mode_port);
|
||||
openfpga::PortParser port_parser(physical_mode_port);
|
||||
pb_type_annotation.add_pb_type_port_pair(name_attr, port_parser.port());
|
||||
}
|
||||
|
||||
/* We have an optional attribute: physical_mode_pin_initial_offset
|
||||
* Split based on the number of physical pb_type ports that have been defined
|
||||
*/
|
||||
const std::string& physical_pin_initial_offset_attr = get_attribute(xml_port, "physical_mode_pin_initial_offset", loc_data, pugiutil::ReqOpt::OPTIONAL).as_string();
|
||||
const std::string& physical_pin_initial_offset_attr =
|
||||
get_attribute(xml_port, "physical_mode_pin_initial_offset", loc_data,
|
||||
pugiutil::ReqOpt::OPTIONAL)
|
||||
.as_string();
|
||||
|
||||
if (false == physical_pin_initial_offset_attr.empty()) {
|
||||
/* Split the physical mode port attributes with space */
|
||||
openfpga::StringToken offset_tokenizer(physical_pin_initial_offset_attr);
|
||||
const std::vector<std::string> initial_offsets = offset_tokenizer.split();
|
||||
|
||||
|
||||
/* Error out if the offset does not match the port definition */
|
||||
if (physical_mode_ports.size() != initial_offsets.size()) {
|
||||
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_port),
|
||||
"Defined %lu physical mode ports but only %lu physical pin initial offset are defined! Expect size matching.\n",
|
||||
physical_mode_ports.size(), initial_offsets.size());
|
||||
"Defined %lu physical mode ports but only %lu physical "
|
||||
"pin initial offset are defined! Expect size matching.\n",
|
||||
physical_mode_ports.size(), initial_offsets.size());
|
||||
}
|
||||
|
||||
for (size_t iport = 0; iport < physical_mode_ports.size(); ++iport) {
|
||||
openfpga::PortParser port_parser(physical_mode_ports[iport]);
|
||||
pb_type_annotation.set_physical_pin_initial_offset(name_attr,
|
||||
port_parser.port(),
|
||||
std::stoi(initial_offsets[iport]));
|
||||
openfpga::PortParser port_parser(physical_mode_ports[iport]);
|
||||
pb_type_annotation.set_physical_pin_initial_offset(
|
||||
name_attr, port_parser.port(), std::stoi(initial_offsets[iport]));
|
||||
}
|
||||
}
|
||||
|
||||
/* We have an optional attribute: physical_mode_pin_rotate_offset
|
||||
* Split based on the number of physical pb_type ports that have been defined
|
||||
*/
|
||||
const std::string& physical_pin_rotate_offset_attr = get_attribute(xml_port, "physical_mode_pin_rotate_offset", loc_data, pugiutil::ReqOpt::OPTIONAL).as_string();
|
||||
const std::string& physical_pin_rotate_offset_attr =
|
||||
get_attribute(xml_port, "physical_mode_pin_rotate_offset", loc_data,
|
||||
pugiutil::ReqOpt::OPTIONAL)
|
||||
.as_string();
|
||||
|
||||
if (false == physical_pin_rotate_offset_attr.empty()) {
|
||||
/* Split the physical mode port attributes with space */
|
||||
openfpga::StringToken offset_tokenizer(physical_pin_rotate_offset_attr);
|
||||
const std::vector<std::string> rotate_offsets = offset_tokenizer.split();
|
||||
|
||||
|
||||
/* Error out if the offset does not match the port definition */
|
||||
if (physical_mode_ports.size() != rotate_offsets.size()) {
|
||||
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_port),
|
||||
"Defined %lu physical mode ports but only %lu physical pin rotate offset are defined! Expect size matching.\n",
|
||||
physical_mode_ports.size(), rotate_offsets.size());
|
||||
"Defined %lu physical mode ports but only %lu physical "
|
||||
"pin rotate offset are defined! Expect size matching.\n",
|
||||
physical_mode_ports.size(), rotate_offsets.size());
|
||||
}
|
||||
|
||||
for (size_t iport = 0; iport < physical_mode_ports.size(); ++iport) {
|
||||
openfpga::PortParser port_parser(physical_mode_ports[iport]);
|
||||
pb_type_annotation.set_physical_pin_rotate_offset(name_attr,
|
||||
port_parser.port(),
|
||||
std::stoi(rotate_offsets[iport]));
|
||||
openfpga::PortParser port_parser(physical_mode_ports[iport]);
|
||||
pb_type_annotation.set_physical_pin_rotate_offset(
|
||||
name_attr, port_parser.port(), std::stoi(rotate_offsets[iport]));
|
||||
}
|
||||
}
|
||||
|
||||
/* We have an optional attribute: physical_mode_port_rotate_offset
|
||||
* Split based on the number of physical pb_type ports that have been defined
|
||||
*/
|
||||
const std::string& physical_port_rotate_offset_attr = get_attribute(xml_port, "physical_mode_port_rotate_offset", loc_data, pugiutil::ReqOpt::OPTIONAL).as_string();
|
||||
const std::string& physical_port_rotate_offset_attr =
|
||||
get_attribute(xml_port, "physical_mode_port_rotate_offset", loc_data,
|
||||
pugiutil::ReqOpt::OPTIONAL)
|
||||
.as_string();
|
||||
|
||||
if (false == physical_port_rotate_offset_attr.empty()) {
|
||||
/* Split the physical mode port attributes with space */
|
||||
openfpga::StringToken offset_tokenizer(physical_port_rotate_offset_attr);
|
||||
const std::vector<std::string> rotate_offsets = offset_tokenizer.split();
|
||||
|
||||
|
||||
/* Error out if the offset does not match the port definition */
|
||||
if (physical_mode_ports.size() != rotate_offsets.size()) {
|
||||
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_port),
|
||||
"Defined %lu physical mode ports but only %lu physical port rotate offset are defined! Expect size matching.\n",
|
||||
physical_mode_ports.size(), rotate_offsets.size());
|
||||
"Defined %lu physical mode ports but only %lu physical "
|
||||
"port rotate offset are defined! Expect size matching.\n",
|
||||
physical_mode_ports.size(), rotate_offsets.size());
|
||||
}
|
||||
|
||||
for (size_t iport = 0; iport < physical_mode_ports.size(); ++iport) {
|
||||
openfpga::PortParser port_parser(physical_mode_ports[iport]);
|
||||
pb_type_annotation.set_physical_port_rotate_offset(name_attr,
|
||||
port_parser.port(),
|
||||
std::stoi(rotate_offsets[iport]));
|
||||
openfpga::PortParser port_parser(physical_mode_ports[iport]);
|
||||
pb_type_annotation.set_physical_port_rotate_offset(
|
||||
name_attr, port_parser.port(), std::stoi(rotate_offsets[iport]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -145,10 +156,9 @@ void read_xml_pb_port_annotation(pugi::xml_node& xml_port,
|
|||
* Parse mode_bits: convert from string to array of digits
|
||||
* We only allow the bit to either '0' or '1'
|
||||
*******************************************************************/
|
||||
static
|
||||
std::vector<size_t> parse_mode_bits(pugi::xml_node& xml_mode_bits,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
const std::string& mode_bit_str) {
|
||||
static std::vector<size_t> parse_mode_bits(pugi::xml_node& xml_mode_bits,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
const std::string& mode_bit_str) {
|
||||
std::vector<size_t> mode_bits;
|
||||
|
||||
for (const char& bit_char : mode_bit_str) {
|
||||
|
@ -158,10 +168,11 @@ std::vector<size_t> parse_mode_bits(pugi::xml_node& xml_mode_bits,
|
|||
mode_bits.push_back(1);
|
||||
} else {
|
||||
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_mode_bits),
|
||||
"Unexpected '%c' character found in the mode bit '%s'! Only allow either '0' or '1'\n",
|
||||
"Unexpected '%c' character found in the mode bit '%s'! "
|
||||
"Only allow either '0' or '1'\n",
|
||||
bit_char, mode_bit_str.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return mode_bits;
|
||||
}
|
||||
|
@ -169,115 +180,146 @@ std::vector<size_t> parse_mode_bits(pugi::xml_node& xml_mode_bits,
|
|||
/********************************************************************
|
||||
* 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) {
|
||||
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();
|
||||
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()) ) {
|
||||
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());
|
||||
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());
|
||||
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());
|
||||
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());
|
||||
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()) ) {
|
||||
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());
|
||||
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());
|
||||
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());
|
||||
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());
|
||||
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 */
|
||||
std::vector<size_t> mode_bit_data = parse_mode_bits(xml_pb_type, loc_data, get_attribute(xml_pb_type, "mode_bits", loc_data, pugiutil::ReqOpt::OPTIONAL).as_string());
|
||||
std::vector<size_t> mode_bit_data =
|
||||
parse_mode_bits(xml_pb_type, loc_data,
|
||||
get_attribute(xml_pb_type, "mode_bits", loc_data,
|
||||
pugiutil::ReqOpt::OPTIONAL)
|
||||
.as_string());
|
||||
pb_type_annotation.set_mode_bits(mode_bit_data);
|
||||
|
||||
/* 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 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());
|
||||
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 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_float(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));
|
||||
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_float(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);
|
||||
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);
|
||||
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>
|
||||
/* 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);
|
||||
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 */
|
||||
/* 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
|
||||
* 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> 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);
|
||||
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>
|
||||
|
@ -288,7 +330,7 @@ std::vector<openfpga::PbTypeAnnotation> read_xml_pb_type_annotations(pugi::xml_n
|
|||
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;
|
||||
}
|
||||
|
|
|
@ -4,14 +4,14 @@
|
|||
/********************************************************************
|
||||
* Include header files that are required by function declaration
|
||||
*******************************************************************/
|
||||
#include "pugixml_util.hpp"
|
||||
#include "pugixml.hpp"
|
||||
#include "pb_type_annotation.h"
|
||||
#include "pugixml.hpp"
|
||||
#include "pugixml_util.hpp"
|
||||
|
||||
/********************************************************************
|
||||
* Function declaration
|
||||
*******************************************************************/
|
||||
std::vector<openfpga::PbTypeAnnotation> read_xml_pb_type_annotations(pugi::xml_node& Node,
|
||||
const pugiutil::loc_data& loc_data);
|
||||
std::vector<openfpga::PbTypeAnnotation> read_xml_pb_type_annotations(
|
||||
pugi::xml_node& Node, const pugiutil::loc_data& loc_data);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -14,28 +14,26 @@
|
|||
|
||||
/* Headers from libarchfpga */
|
||||
#include "arch_error.h"
|
||||
#include "read_xml_util.h"
|
||||
|
||||
#include "read_xml_routing_circuit.h"
|
||||
#include "read_xml_util.h"
|
||||
|
||||
/********************************************************************
|
||||
* Find the circuit model id for a routing switch as defined in XML
|
||||
*******************************************************************/
|
||||
static
|
||||
CircuitModelId find_routing_circuit_model(pugi::xml_node& xml_switch,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
const std::string& switch_model_name,
|
||||
const e_circuit_model_type& expected_circuit_model_type) {
|
||||
static CircuitModelId find_routing_circuit_model(
|
||||
pugi::xml_node& xml_switch, const pugiutil::loc_data& loc_data,
|
||||
const CircuitLibrary& circuit_lib, const std::string& switch_model_name,
|
||||
const e_circuit_model_type& expected_circuit_model_type) {
|
||||
/* Find the circuit model id in circuit library */
|
||||
CircuitModelId switch_model = circuit_lib.model(switch_model_name);
|
||||
/* Ensure we have a valid circuit model id! */
|
||||
if (CircuitModelId::INVALID() == switch_model) {
|
||||
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_switch),
|
||||
"Invalid circuit model name '%s'! Unable to find it in circuit library\n",
|
||||
switch_model_name.c_str());
|
||||
archfpga_throw(
|
||||
loc_data.filename_c_str(), loc_data.line(xml_switch),
|
||||
"Invalid circuit model name '%s'! Unable to find it in circuit library\n",
|
||||
switch_model_name.c_str());
|
||||
}
|
||||
/* Check the type of switch model, it must be a specific type!!!
|
||||
/* Check the type of switch model, it must be a specific type!!!
|
||||
* For CB/SB switches, the type must be a multiplexer
|
||||
* For routing segments, the type must be a channel wire
|
||||
* TODO: decide where to put these checking codes
|
||||
|
@ -44,23 +42,26 @@ CircuitModelId find_routing_circuit_model(pugi::xml_node& xml_switch,
|
|||
if (expected_circuit_model_type != circuit_lib.model_type(switch_model)) {
|
||||
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_switch),
|
||||
"Circuit model '%s' must be a type of '%s'\n",
|
||||
switch_model_name.c_str(), CIRCUIT_MODEL_TYPE_STRING[expected_circuit_model_type]);
|
||||
switch_model_name.c_str(),
|
||||
CIRCUIT_MODEL_TYPE_STRING[expected_circuit_model_type]);
|
||||
}
|
||||
|
||||
|
||||
return switch_model;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Parse XML codes about <connection_block> to an object of name-to-circuit mapping
|
||||
* Note: this function should be called AFTER the parsing of circuit library!!!
|
||||
* Parse XML codes about <connection_block> to an object of name-to-circuit
|
||||
*mapping Note: this function should be called AFTER the parsing of circuit
|
||||
*library!!!
|
||||
*******************************************************************/
|
||||
std::map<std::string, CircuitModelId> read_xml_cb_switch_circuit(pugi::xml_node& Node,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
const CircuitLibrary& circuit_lib) {
|
||||
std::map<std::string, CircuitModelId> read_xml_cb_switch_circuit(
|
||||
pugi::xml_node& Node, const pugiutil::loc_data& loc_data,
|
||||
const CircuitLibrary& circuit_lib) {
|
||||
std::map<std::string, CircuitModelId> cb_switch2circuit;
|
||||
|
||||
/* Parse cb switch list */
|
||||
pugi::xml_node xml_cb_switch = get_single_child(Node, "connection_block", loc_data);
|
||||
pugi::xml_node xml_cb_switch =
|
||||
get_single_child(Node, "connection_block", loc_data);
|
||||
|
||||
/* Iterate over the children under this node,
|
||||
* each child should be named after switch
|
||||
|
@ -70,18 +71,20 @@ std::map<std::string, CircuitModelId> read_xml_cb_switch_circuit(pugi::xml_node&
|
|||
if (xml_switch.name() != std::string("switch")) {
|
||||
bad_tag(xml_switch, loc_data, xml_cb_switch, {"switch"});
|
||||
}
|
||||
/* Get the switch name */
|
||||
std::string switch_name = get_attribute(xml_switch, "name", loc_data).as_string();
|
||||
/* Get the switch name */
|
||||
std::string switch_name =
|
||||
get_attribute(xml_switch, "name", loc_data).as_string();
|
||||
|
||||
/* Get the switch circuit model name */
|
||||
std::string switch_model_name = get_attribute(xml_switch, "circuit_model_name", loc_data).as_string();
|
||||
/* Get the switch circuit model name */
|
||||
std::string switch_model_name =
|
||||
get_attribute(xml_switch, "circuit_model_name", loc_data).as_string();
|
||||
|
||||
CircuitModelId switch_model = find_routing_circuit_model(xml_switch, loc_data,
|
||||
circuit_lib, switch_model_name,
|
||||
CIRCUIT_MODEL_MUX);
|
||||
CircuitModelId switch_model = find_routing_circuit_model(
|
||||
xml_switch, loc_data, circuit_lib, switch_model_name, CIRCUIT_MODEL_MUX);
|
||||
|
||||
/* Ensure that there is no duplicated switch names defined here */
|
||||
std::map<std::string, CircuitModelId>::const_iterator it = cb_switch2circuit.find(switch_name);
|
||||
std::map<std::string, CircuitModelId>::const_iterator it =
|
||||
cb_switch2circuit.find(switch_name);
|
||||
if (it != cb_switch2circuit.end()) {
|
||||
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_switch),
|
||||
"Switch name '%s' has been defined more than once!\n",
|
||||
|
@ -89,8 +92,8 @@ std::map<std::string, CircuitModelId> read_xml_cb_switch_circuit(pugi::xml_node&
|
|||
}
|
||||
|
||||
/* Pass all the check, we can add it to the map */
|
||||
cb_switch2circuit[switch_name] = switch_model;
|
||||
}
|
||||
cb_switch2circuit[switch_name] = switch_model;
|
||||
}
|
||||
|
||||
return cb_switch2circuit;
|
||||
}
|
||||
|
@ -99,13 +102,14 @@ std::map<std::string, CircuitModelId> read_xml_cb_switch_circuit(pugi::xml_node&
|
|||
* Parse XML codes about <switch_block> to an object of name-to-circuit mapping
|
||||
* Note: this function should be called AFTER the parsing of circuit library!!!
|
||||
*******************************************************************/
|
||||
std::map<std::string, CircuitModelId> read_xml_sb_switch_circuit(pugi::xml_node& Node,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
const CircuitLibrary& circuit_lib) {
|
||||
std::map<std::string, CircuitModelId> read_xml_sb_switch_circuit(
|
||||
pugi::xml_node& Node, const pugiutil::loc_data& loc_data,
|
||||
const CircuitLibrary& circuit_lib) {
|
||||
std::map<std::string, CircuitModelId> sb_switch2circuit;
|
||||
|
||||
/* Parse cb switch list */
|
||||
pugi::xml_node xml_sb_switch = get_single_child(Node, "switch_block", loc_data);
|
||||
pugi::xml_node xml_sb_switch =
|
||||
get_single_child(Node, "switch_block", loc_data);
|
||||
|
||||
/* Iterate over the children under this node,
|
||||
* each child should be named after switch
|
||||
|
@ -115,18 +119,20 @@ std::map<std::string, CircuitModelId> read_xml_sb_switch_circuit(pugi::xml_node&
|
|||
if (xml_switch.name() != std::string("switch")) {
|
||||
bad_tag(xml_switch, loc_data, xml_sb_switch, {"switch"});
|
||||
}
|
||||
/* Get the switch name */
|
||||
std::string switch_name = get_attribute(xml_switch, "name", loc_data).as_string();
|
||||
/* Get the switch name */
|
||||
std::string switch_name =
|
||||
get_attribute(xml_switch, "name", loc_data).as_string();
|
||||
|
||||
/* Get the switch circuit model name */
|
||||
std::string switch_model_name = get_attribute(xml_switch, "circuit_model_name", loc_data).as_string();
|
||||
/* Get the switch circuit model name */
|
||||
std::string switch_model_name =
|
||||
get_attribute(xml_switch, "circuit_model_name", loc_data).as_string();
|
||||
|
||||
CircuitModelId switch_model = find_routing_circuit_model(xml_switch, loc_data,
|
||||
circuit_lib, switch_model_name,
|
||||
CIRCUIT_MODEL_MUX);
|
||||
CircuitModelId switch_model = find_routing_circuit_model(
|
||||
xml_switch, loc_data, circuit_lib, switch_model_name, CIRCUIT_MODEL_MUX);
|
||||
|
||||
/* Ensure that there is no duplicated switch names defined here */
|
||||
std::map<std::string, CircuitModelId>::const_iterator it = sb_switch2circuit.find(switch_name);
|
||||
std::map<std::string, CircuitModelId>::const_iterator it =
|
||||
sb_switch2circuit.find(switch_name);
|
||||
if (it != sb_switch2circuit.end()) {
|
||||
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_switch),
|
||||
"Switch name '%s' has been defined more than once!\n",
|
||||
|
@ -134,23 +140,25 @@ std::map<std::string, CircuitModelId> read_xml_sb_switch_circuit(pugi::xml_node&
|
|||
}
|
||||
|
||||
/* Pass all the check, we can add it to the map */
|
||||
sb_switch2circuit[switch_name] = switch_model;
|
||||
}
|
||||
sb_switch2circuit[switch_name] = switch_model;
|
||||
}
|
||||
|
||||
return sb_switch2circuit;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Parse XML codes about <routing_segment> to an object of name-to-circuit mapping
|
||||
* Note: this function should be called AFTER the parsing of circuit library!!!
|
||||
* Parse XML codes about <routing_segment> to an object of name-to-circuit
|
||||
*mapping Note: this function should be called AFTER the parsing of circuit
|
||||
*library!!!
|
||||
*******************************************************************/
|
||||
std::map<std::string, CircuitModelId> read_xml_routing_segment_circuit(pugi::xml_node& Node,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
const CircuitLibrary& circuit_lib) {
|
||||
std::map<std::string, CircuitModelId> read_xml_routing_segment_circuit(
|
||||
pugi::xml_node& Node, const pugiutil::loc_data& loc_data,
|
||||
const CircuitLibrary& circuit_lib) {
|
||||
std::map<std::string, CircuitModelId> seg2circuit;
|
||||
|
||||
/* Parse cb switch list */
|
||||
pugi::xml_node xml_segments= get_single_child(Node, "routing_segment", loc_data);
|
||||
pugi::xml_node xml_segments =
|
||||
get_single_child(Node, "routing_segment", loc_data);
|
||||
|
||||
/* Iterate over the children under this node,
|
||||
* each child should be named after switch
|
||||
|
@ -160,18 +168,19 @@ std::map<std::string, CircuitModelId> read_xml_routing_segment_circuit(pugi::xml
|
|||
if (xml_seg.name() != std::string("segment")) {
|
||||
bad_tag(xml_seg, loc_data, xml_segments, {"segment"});
|
||||
}
|
||||
/* Get the switch name */
|
||||
/* Get the switch name */
|
||||
std::string seg_name = get_attribute(xml_seg, "name", loc_data).as_string();
|
||||
|
||||
/* Get the routing segment circuit model name */
|
||||
std::string seg_model_name = get_attribute(xml_seg, "circuit_model_name", loc_data).as_string();
|
||||
/* Get the routing segment circuit model name */
|
||||
std::string seg_model_name =
|
||||
get_attribute(xml_seg, "circuit_model_name", loc_data).as_string();
|
||||
|
||||
CircuitModelId seg_model = find_routing_circuit_model(
|
||||
xml_seg, loc_data, circuit_lib, seg_model_name, CIRCUIT_MODEL_CHAN_WIRE);
|
||||
|
||||
CircuitModelId seg_model = find_routing_circuit_model(xml_seg, loc_data,
|
||||
circuit_lib, seg_model_name,
|
||||
CIRCUIT_MODEL_CHAN_WIRE);
|
||||
|
||||
/* Ensure that there is no duplicated seg names defined here */
|
||||
std::map<std::string, CircuitModelId>::const_iterator it = seg2circuit.find(seg_name);
|
||||
std::map<std::string, CircuitModelId>::const_iterator it =
|
||||
seg2circuit.find(seg_name);
|
||||
if (it != seg2circuit.end()) {
|
||||
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_seg),
|
||||
"Segment name '%s' has been defined more than once!\n",
|
||||
|
@ -179,8 +188,8 @@ std::map<std::string, CircuitModelId> read_xml_routing_segment_circuit(pugi::xml
|
|||
}
|
||||
|
||||
/* Pass all the check, we can add it to the map */
|
||||
seg2circuit[seg_name] = seg_model;
|
||||
}
|
||||
seg2circuit[seg_name] = seg_model;
|
||||
}
|
||||
|
||||
return seg2circuit;
|
||||
}
|
||||
|
@ -188,8 +197,7 @@ std::map<std::string, CircuitModelId> read_xml_routing_segment_circuit(pugi::xml
|
|||
/********************************************************************
|
||||
* Convert string to the enumerate of direct type
|
||||
*******************************************************************/
|
||||
static
|
||||
e_direct_type string_to_direct_type(const std::string& type_string) {
|
||||
static e_direct_type string_to_direct_type(const std::string& type_string) {
|
||||
if (std::string("column") == type_string) {
|
||||
return INTER_COLUMN;
|
||||
}
|
||||
|
@ -199,13 +207,13 @@ e_direct_type string_to_direct_type(const std::string& type_string) {
|
|||
}
|
||||
|
||||
return NUM_DIRECT_TYPES;
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Convert string to the enumerate of direct direction type
|
||||
*******************************************************************/
|
||||
static
|
||||
e_direct_direction string_to_direct_direction(const std::string& type_string) {
|
||||
static e_direct_direction string_to_direct_direction(
|
||||
const std::string& type_string) {
|
||||
if (std::string("positive") == type_string) {
|
||||
return POSITIVE_DIR;
|
||||
}
|
||||
|
@ -215,12 +223,12 @@ e_direct_direction string_to_direct_direction(const std::string& type_string) {
|
|||
}
|
||||
|
||||
return NUM_DIRECT_DIRECTIONS;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Parse XML codes about <direct_connection> to an object of name-to-circuit mapping
|
||||
* Note: this function should be called AFTER the parsing of circuit library!!!
|
||||
* Parse XML codes about <direct_connection> to an object of name-to-circuit
|
||||
*mapping Note: this function should be called AFTER the parsing of circuit
|
||||
*library!!!
|
||||
*******************************************************************/
|
||||
ArchDirect read_xml_direct_circuit(pugi::xml_node& Node,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
|
@ -228,7 +236,8 @@ ArchDirect read_xml_direct_circuit(pugi::xml_node& Node,
|
|||
ArchDirect arch_direct;
|
||||
|
||||
/* Parse direct list, this is optional. May not be used */
|
||||
pugi::xml_node xml_directs= get_single_child(Node, "direct_connection", loc_data, pugiutil::ReqOpt::OPTIONAL);
|
||||
pugi::xml_node xml_directs = get_single_child(
|
||||
Node, "direct_connection", loc_data, pugiutil::ReqOpt::OPTIONAL);
|
||||
/* Not found, we can return */
|
||||
if (!xml_directs) {
|
||||
return arch_direct;
|
||||
|
@ -242,16 +251,17 @@ ArchDirect read_xml_direct_circuit(pugi::xml_node& Node,
|
|||
if (xml_direct.name() != std::string("direct")) {
|
||||
bad_tag(xml_direct, loc_data, xml_directs, {"direct"});
|
||||
}
|
||||
/* Get the switch name */
|
||||
std::string direct_name = get_attribute(xml_direct, "name", loc_data).as_string();
|
||||
/* Get the switch name */
|
||||
std::string direct_name =
|
||||
get_attribute(xml_direct, "name", loc_data).as_string();
|
||||
|
||||
/* Get the routing segment circuit model name */
|
||||
std::string direct_model_name = get_attribute(xml_direct, "circuit_model_name", loc_data).as_string();
|
||||
/* Get the routing segment circuit model name */
|
||||
std::string direct_model_name =
|
||||
get_attribute(xml_direct, "circuit_model_name", loc_data).as_string();
|
||||
|
||||
CircuitModelId direct_model = find_routing_circuit_model(
|
||||
xml_direct, loc_data, circuit_lib, direct_model_name, CIRCUIT_MODEL_WIRE);
|
||||
|
||||
CircuitModelId direct_model = find_routing_circuit_model(xml_direct, loc_data,
|
||||
circuit_lib, direct_model_name,
|
||||
CIRCUIT_MODEL_WIRE);
|
||||
|
||||
/* Add to the Arch direct database */
|
||||
ArchDirectId direct = arch_direct.add_direct(direct_name);
|
||||
if (false == arch_direct.valid_direct_id(direct)) {
|
||||
|
@ -262,7 +272,9 @@ ArchDirect read_xml_direct_circuit(pugi::xml_node& Node,
|
|||
arch_direct.set_circuit_model(direct, direct_model);
|
||||
|
||||
/* Add more information*/
|
||||
std::string direct_type_name = get_attribute(xml_direct, "type", loc_data, pugiutil::ReqOpt::OPTIONAL).as_string("none");
|
||||
std::string direct_type_name =
|
||||
get_attribute(xml_direct, "type", loc_data, pugiutil::ReqOpt::OPTIONAL)
|
||||
.as_string("none");
|
||||
/* If not defined, we go to the next */
|
||||
if (std::string("none") == direct_type_name) {
|
||||
continue;
|
||||
|
@ -271,32 +283,37 @@ ArchDirect read_xml_direct_circuit(pugi::xml_node& Node,
|
|||
e_direct_type direct_type = string_to_direct_type(direct_type_name);
|
||||
|
||||
if (NUM_DIRECT_TYPES == direct_type) {
|
||||
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_direct),
|
||||
"Direct type '%s' is not support! Acceptable values are [column|row]\n",
|
||||
direct_type_name.c_str());
|
||||
archfpga_throw(
|
||||
loc_data.filename_c_str(), loc_data.line(xml_direct),
|
||||
"Direct type '%s' is not support! Acceptable values are [column|row]\n",
|
||||
direct_type_name.c_str());
|
||||
}
|
||||
|
||||
arch_direct.set_type(direct, direct_type);
|
||||
|
||||
std::string x_dir_name = get_attribute(xml_direct, "x_dir", loc_data).as_string();
|
||||
std::string y_dir_name = get_attribute(xml_direct, "y_dir", loc_data).as_string();
|
||||
std::string x_dir_name =
|
||||
get_attribute(xml_direct, "x_dir", loc_data).as_string();
|
||||
std::string y_dir_name =
|
||||
get_attribute(xml_direct, "y_dir", loc_data).as_string();
|
||||
e_direct_direction x_dir = string_to_direct_direction(x_dir_name);
|
||||
e_direct_direction y_dir = string_to_direct_direction(y_dir_name);
|
||||
|
||||
if (NUM_DIRECT_DIRECTIONS == x_dir) {
|
||||
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_direct),
|
||||
"Direct x-direction '%s' is not support! Acceptable values are [positive|column]\n",
|
||||
"Direct x-direction '%s' is not support! Acceptable "
|
||||
"values are [positive|column]\n",
|
||||
x_dir_name.c_str());
|
||||
}
|
||||
|
||||
if (NUM_DIRECT_DIRECTIONS == y_dir) {
|
||||
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_direct),
|
||||
"Direct y-direction '%s' is not support! Acceptable values are [positive|column]\n",
|
||||
"Direct y-direction '%s' is not support! Acceptable "
|
||||
"values are [positive|column]\n",
|
||||
y_dir_name.c_str());
|
||||
}
|
||||
|
||||
arch_direct.set_direction(direct, x_dir, y_dir);
|
||||
}
|
||||
}
|
||||
|
||||
return arch_direct;
|
||||
}
|
||||
|
|
|
@ -4,32 +4,31 @@
|
|||
/********************************************************************
|
||||
* Include header files that are required by function declaration
|
||||
*******************************************************************/
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "pugixml_util.hpp"
|
||||
#include "pugixml.hpp"
|
||||
#include "circuit_library.h"
|
||||
#include "arch_direct.h"
|
||||
#include "circuit_library.h"
|
||||
#include "pugixml.hpp"
|
||||
#include "pugixml_util.hpp"
|
||||
|
||||
/********************************************************************
|
||||
* Function declaration
|
||||
*******************************************************************/
|
||||
std::map<std::string, CircuitModelId> read_xml_cb_switch_circuit(pugi::xml_node& Node,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
const CircuitLibrary& circuit_lib);
|
||||
std::map<std::string, CircuitModelId> read_xml_cb_switch_circuit(
|
||||
pugi::xml_node& Node, const pugiutil::loc_data& loc_data,
|
||||
const CircuitLibrary& circuit_lib);
|
||||
|
||||
std::map<std::string, CircuitModelId> read_xml_sb_switch_circuit(pugi::xml_node& Node,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
const CircuitLibrary& circuit_lib);
|
||||
std::map<std::string, CircuitModelId> read_xml_sb_switch_circuit(
|
||||
pugi::xml_node& Node, const pugiutil::loc_data& loc_data,
|
||||
const CircuitLibrary& circuit_lib);
|
||||
|
||||
std::map<std::string, CircuitModelId> read_xml_routing_segment_circuit(pugi::xml_node& Node,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
const CircuitLibrary& circuit_lib);
|
||||
std::map<std::string, CircuitModelId> read_xml_routing_segment_circuit(
|
||||
pugi::xml_node& Node, const pugiutil::loc_data& loc_data,
|
||||
const CircuitLibrary& circuit_lib);
|
||||
|
||||
ArchDirect read_xml_direct_circuit(pugi::xml_node& Node,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
const CircuitLibrary& circuit_lib);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -17,15 +17,14 @@
|
|||
|
||||
/* Headers from libarchfpga */
|
||||
#include "arch_error.h"
|
||||
#include "read_xml_util.h"
|
||||
|
||||
#include "read_xml_simulation_setting.h"
|
||||
#include "read_xml_util.h"
|
||||
|
||||
/********************************************************************
|
||||
* Convert string to the enumerate of simulation accuracy type
|
||||
*******************************************************************/
|
||||
static
|
||||
e_sim_accuracy_type string_to_sim_accuracy_type(const std::string& type_string) {
|
||||
static e_sim_accuracy_type string_to_sim_accuracy_type(
|
||||
const std::string& type_string) {
|
||||
for (size_t itype = 0; itype < NUM_SIM_ACCURACY_TYPES; ++itype) {
|
||||
if (std::string(SIM_ACCURACY_TYPE_STRING[itype]) == type_string) {
|
||||
return static_cast<e_sim_accuracy_type>(itype);
|
||||
|
@ -36,92 +35,123 @@ e_sim_accuracy_type string_to_sim_accuracy_type(const std::string& type_string)
|
|||
}
|
||||
|
||||
/********************************************************************
|
||||
* Parse XML codes of a <clock> line under <operating> to an object of simulation setting
|
||||
* Parse XML codes of a <clock> line under <operating> to an object of
|
||||
*simulation setting
|
||||
*******************************************************************/
|
||||
static
|
||||
void read_xml_operating_clock_override_setting(pugi::xml_node& xml_clock_override_setting,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
openfpga::SimulationSetting& sim_setting) {
|
||||
std::string clock_name = get_attribute(xml_clock_override_setting, "name", loc_data).as_string();
|
||||
static void read_xml_operating_clock_override_setting(
|
||||
pugi::xml_node& xml_clock_override_setting,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
openfpga::SimulationSetting& sim_setting) {
|
||||
std::string clock_name =
|
||||
get_attribute(xml_clock_override_setting, "name", loc_data).as_string();
|
||||
|
||||
/* Create a new clock override object in the sim_setting object with the given name */
|
||||
/* Create a new clock override object in the sim_setting object with the given
|
||||
* name */
|
||||
SimulationClockId clock_id = sim_setting.create_clock(clock_name);
|
||||
|
||||
|
||||
/* Report if the clock creation failed, this is due to a conflicts in naming*/
|
||||
if (false == sim_setting.valid_clock_id(clock_id)) {
|
||||
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_clock_override_setting),
|
||||
"Fail to create simulation clock '%s', it may share the same name as other simulation clock definition!\n",
|
||||
archfpga_throw(loc_data.filename_c_str(),
|
||||
loc_data.line(xml_clock_override_setting),
|
||||
"Fail to create simulation clock '%s', it may share the "
|
||||
"same name as other simulation clock definition!\n",
|
||||
clock_name.c_str());
|
||||
}
|
||||
|
||||
/* Parse port information */
|
||||
openfpga::PortParser clock_port_parser(get_attribute(xml_clock_override_setting, "port", loc_data).as_string());
|
||||
openfpga::PortParser clock_port_parser(
|
||||
get_attribute(xml_clock_override_setting, "port", loc_data).as_string());
|
||||
sim_setting.set_clock_port(clock_id, clock_port_parser.port());
|
||||
|
||||
/* Parse frequency information */
|
||||
sim_setting.set_clock_frequency(clock_id, get_attribute(xml_clock_override_setting, "frequency", loc_data).as_float(0.));
|
||||
sim_setting.set_clock_frequency(
|
||||
clock_id, get_attribute(xml_clock_override_setting, "frequency", loc_data)
|
||||
.as_float(0.));
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Parse XML codes of a <clock> line under <programming> to an object of simulation setting
|
||||
* Parse XML codes of a <clock> line under <programming> to an object of
|
||||
*simulation setting
|
||||
*******************************************************************/
|
||||
static
|
||||
void read_xml_programming_clock_override_setting(pugi::xml_node& xml_clock_override_setting,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
openfpga::SimulationSetting& sim_setting) {
|
||||
std::string clock_name = get_attribute(xml_clock_override_setting, "name", loc_data).as_string();
|
||||
static void read_xml_programming_clock_override_setting(
|
||||
pugi::xml_node& xml_clock_override_setting,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
openfpga::SimulationSetting& sim_setting) {
|
||||
std::string clock_name =
|
||||
get_attribute(xml_clock_override_setting, "name", loc_data).as_string();
|
||||
|
||||
/* Create a new clock override object in the sim_setting object with the given name */
|
||||
/* Create a new clock override object in the sim_setting object with the given
|
||||
* name */
|
||||
SimulationClockId clock_id = sim_setting.create_clock(clock_name);
|
||||
|
||||
|
||||
/* Report if the clock creation failed, this is due to a conflicts in naming*/
|
||||
if (false == sim_setting.valid_clock_id(clock_id)) {
|
||||
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_clock_override_setting),
|
||||
"Fail to create simulation clock '%s', it may share the same name as other simulation clock definition!\n",
|
||||
archfpga_throw(loc_data.filename_c_str(),
|
||||
loc_data.line(xml_clock_override_setting),
|
||||
"Fail to create simulation clock '%s', it may share the "
|
||||
"same name as other simulation clock definition!\n",
|
||||
clock_name.c_str());
|
||||
}
|
||||
|
||||
/* Parse port information */
|
||||
openfpga::PortParser clock_port_parser(get_attribute(xml_clock_override_setting, "port", loc_data).as_string());
|
||||
openfpga::PortParser clock_port_parser(
|
||||
get_attribute(xml_clock_override_setting, "port", loc_data).as_string());
|
||||
sim_setting.set_clock_port(clock_id, clock_port_parser.port());
|
||||
|
||||
/* Parse frequency information */
|
||||
std::string clock_freq_str = get_attribute(xml_clock_override_setting, "frequency", loc_data).as_string();
|
||||
std::string clock_freq_str =
|
||||
get_attribute(xml_clock_override_setting, "frequency", loc_data)
|
||||
.as_string();
|
||||
if (std::string("auto") != clock_freq_str) {
|
||||
sim_setting.set_clock_frequency(clock_id, get_attribute(xml_clock_override_setting, "frequency", loc_data).as_float(0.));
|
||||
sim_setting.set_clock_frequency(
|
||||
clock_id, get_attribute(xml_clock_override_setting, "frequency", loc_data)
|
||||
.as_float(0.));
|
||||
}
|
||||
|
||||
sim_setting.set_clock_is_programming(clock_id, true);
|
||||
|
||||
sim_setting.set_clock_is_shift_register(clock_id, get_attribute(xml_clock_override_setting, "is_shift_register", loc_data).as_bool(false));
|
||||
sim_setting.set_clock_is_shift_register(
|
||||
clock_id,
|
||||
get_attribute(xml_clock_override_setting, "is_shift_register", loc_data)
|
||||
.as_bool(false));
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Parse XML codes of a <clock_setting> to an object of simulation setting
|
||||
*******************************************************************/
|
||||
static
|
||||
void read_xml_clock_setting(pugi::xml_node& xml_clock_setting,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
openfpga::SimulationSetting& sim_setting) {
|
||||
static void read_xml_clock_setting(pugi::xml_node& xml_clock_setting,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
openfpga::SimulationSetting& sim_setting) {
|
||||
/* Parse operating clock setting */
|
||||
pugi::xml_node xml_operating_clock_setting = get_single_child(xml_clock_setting, "operating", loc_data);
|
||||
pugi::xml_node xml_operating_clock_setting =
|
||||
get_single_child(xml_clock_setting, "operating", loc_data);
|
||||
|
||||
sim_setting.set_default_operating_clock_frequency(get_attribute(xml_operating_clock_setting, "frequency", loc_data).as_float(0.));
|
||||
sim_setting.set_default_operating_clock_frequency(
|
||||
get_attribute(xml_operating_clock_setting, "frequency", loc_data)
|
||||
.as_float(0.));
|
||||
|
||||
/* Parse number of clock cycles to be used in simulation
|
||||
* Valid keywords is "auto" or other integer larger than 0
|
||||
*/
|
||||
std::string num_cycles_str = get_attribute(xml_operating_clock_setting, "num_cycles", loc_data).as_string();
|
||||
std::string num_cycles_str =
|
||||
get_attribute(xml_operating_clock_setting, "num_cycles", loc_data)
|
||||
.as_string();
|
||||
if (std::string("auto") == num_cycles_str) {
|
||||
sim_setting.set_num_clock_cycles(0);
|
||||
} else if (0 < get_attribute(xml_operating_clock_setting, "num_cycles", loc_data).as_int(0.)) {
|
||||
sim_setting.set_num_clock_cycles(get_attribute(xml_operating_clock_setting, "num_cycles", loc_data).as_int(0));
|
||||
} else if (0 <
|
||||
get_attribute(xml_operating_clock_setting, "num_cycles", loc_data)
|
||||
.as_int(0.)) {
|
||||
sim_setting.set_num_clock_cycles(
|
||||
get_attribute(xml_operating_clock_setting, "num_cycles", loc_data)
|
||||
.as_int(0));
|
||||
} else {
|
||||
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_operating_clock_setting),
|
||||
archfpga_throw(loc_data.filename_c_str(),
|
||||
loc_data.line(xml_operating_clock_setting),
|
||||
"Invalid <num_cycles> defined under <operating>");
|
||||
}
|
||||
|
||||
sim_setting.set_operating_clock_frequency_slack(get_attribute(xml_operating_clock_setting, "slack", loc_data).as_float(0.));
|
||||
sim_setting.set_operating_clock_frequency_slack(
|
||||
get_attribute(xml_operating_clock_setting, "slack", loc_data).as_float(0.));
|
||||
|
||||
/* Iterate over multiple operating clock settings and parse one by one */
|
||||
for (pugi::xml_node xml_clock : xml_operating_clock_setting.children()) {
|
||||
|
@ -130,12 +160,15 @@ void read_xml_clock_setting(pugi::xml_node& xml_clock_setting,
|
|||
bad_tag(xml_clock, loc_data, xml_operating_clock_setting, {"clock"});
|
||||
}
|
||||
read_xml_operating_clock_override_setting(xml_clock, loc_data, sim_setting);
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse programming clock setting */
|
||||
pugi::xml_node xml_programming_clock_setting = get_single_child(xml_clock_setting, "programming", loc_data);
|
||||
pugi::xml_node xml_programming_clock_setting =
|
||||
get_single_child(xml_clock_setting, "programming", loc_data);
|
||||
|
||||
sim_setting.set_programming_clock_frequency(get_attribute(xml_programming_clock_setting, "frequency", loc_data).as_float(0.));
|
||||
sim_setting.set_programming_clock_frequency(
|
||||
get_attribute(xml_programming_clock_setting, "frequency", loc_data)
|
||||
.as_float(0.));
|
||||
|
||||
/* Iterate over multiple operating clock settings and parse one by one */
|
||||
for (pugi::xml_node xml_clock : xml_programming_clock_setting.children()) {
|
||||
|
@ -143,153 +176,191 @@ void read_xml_clock_setting(pugi::xml_node& xml_clock_setting,
|
|||
if (xml_clock.name() != std::string("clock")) {
|
||||
bad_tag(xml_clock, loc_data, xml_programming_clock_setting, {"clock"});
|
||||
}
|
||||
read_xml_programming_clock_override_setting(xml_clock, loc_data, sim_setting);
|
||||
}
|
||||
read_xml_programming_clock_override_setting(xml_clock, loc_data,
|
||||
sim_setting);
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Parse XML codes of a <simulator_option> to an object of simulation setting
|
||||
*******************************************************************/
|
||||
static
|
||||
void read_xml_simulator_option(pugi::xml_node& xml_sim_option,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
openfpga::SimulationSetting& sim_setting) {
|
||||
static void read_xml_simulator_option(
|
||||
pugi::xml_node& xml_sim_option, const pugiutil::loc_data& loc_data,
|
||||
openfpga::SimulationSetting& sim_setting) {
|
||||
pugi::xml_node xml_operating_condition =
|
||||
get_single_child(xml_sim_option, "operating_condition", loc_data);
|
||||
sim_setting.set_simulation_temperature(
|
||||
get_attribute(xml_operating_condition, "temperature", loc_data)
|
||||
.as_float(0.));
|
||||
|
||||
pugi::xml_node xml_operating_condition = get_single_child(xml_sim_option, "operating_condition", loc_data);
|
||||
sim_setting.set_simulation_temperature(get_attribute(xml_operating_condition, "temperature", loc_data).as_float(0.));
|
||||
pugi::xml_node xml_output_log =
|
||||
get_single_child(xml_sim_option, "output_log", loc_data);
|
||||
sim_setting.set_verbose_output(
|
||||
get_attribute(xml_output_log, "verbose", loc_data).as_bool(false));
|
||||
sim_setting.set_capacitance_output(
|
||||
get_attribute(xml_output_log, "captab", loc_data).as_bool(false));
|
||||
|
||||
pugi::xml_node xml_output_log = get_single_child(xml_sim_option, "output_log", loc_data);
|
||||
sim_setting.set_verbose_output(get_attribute(xml_output_log, "verbose", loc_data).as_bool(false));
|
||||
sim_setting.set_capacitance_output(get_attribute(xml_output_log, "captab", loc_data).as_bool(false));
|
||||
|
||||
pugi::xml_node xml_accuracy = get_single_child(xml_sim_option, "accuracy", loc_data);
|
||||
pugi::xml_node xml_accuracy =
|
||||
get_single_child(xml_sim_option, "accuracy", loc_data);
|
||||
|
||||
/* Find the type of accuracy */
|
||||
const char* type_attr = get_attribute(xml_accuracy, "type", loc_data).value();
|
||||
/* Translate the type of design technology to enumerate */
|
||||
e_sim_accuracy_type accuracy_type = string_to_sim_accuracy_type(std::string(type_attr));
|
||||
e_sim_accuracy_type accuracy_type =
|
||||
string_to_sim_accuracy_type(std::string(type_attr));
|
||||
|
||||
if (NUM_SIM_ACCURACY_TYPES == accuracy_type) {
|
||||
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_accuracy),
|
||||
"Invalid 'type' attribute '%s'\n",
|
||||
type_attr);
|
||||
"Invalid 'type' attribute '%s'\n", type_attr);
|
||||
}
|
||||
|
||||
sim_setting.set_simulation_accuracy_type(accuracy_type);
|
||||
|
||||
sim_setting.set_simulation_accuracy(get_attribute(xml_accuracy, "value", loc_data).as_float(0.));
|
||||
sim_setting.set_simulation_accuracy(
|
||||
get_attribute(xml_accuracy, "value", loc_data).as_float(0.));
|
||||
|
||||
/* Validate the accuracy value */
|
||||
if (SIM_ACCURACY_FRAC == sim_setting.simulation_accuracy_type()) {
|
||||
if (false == sim_setting.valid_signal_threshold(sim_setting.simulation_accuracy())) {
|
||||
if (false ==
|
||||
sim_setting.valid_signal_threshold(sim_setting.simulation_accuracy())) {
|
||||
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_accuracy),
|
||||
"Invalid 'value' attribute '%f', which should be in the range of (0,1)\n",
|
||||
"Invalid 'value' attribute '%f', which should be in the "
|
||||
"range of (0,1)\n",
|
||||
sim_setting.simulation_accuracy());
|
||||
}
|
||||
}
|
||||
|
||||
pugi::xml_node xml_runtime = get_single_child(xml_sim_option, "runtime", loc_data);
|
||||
sim_setting.set_fast_simulation(get_attribute(xml_runtime, "fast_simulation", loc_data).as_bool(false));
|
||||
pugi::xml_node xml_runtime =
|
||||
get_single_child(xml_sim_option, "runtime", loc_data);
|
||||
sim_setting.set_fast_simulation(
|
||||
get_attribute(xml_runtime, "fast_simulation", loc_data).as_bool(false));
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* Parse XML codes of a <monte_carlo> to an object of simulation setting
|
||||
*******************************************************************/
|
||||
static
|
||||
void read_xml_monte_carlo(pugi::xml_node& xml_mc,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
openfpga::SimulationSetting& sim_setting) {
|
||||
sim_setting.set_monte_carlo_simulation_points(get_attribute(xml_mc, "num_simulation_points", loc_data).as_int(0));
|
||||
static void read_xml_monte_carlo(pugi::xml_node& xml_mc,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
openfpga::SimulationSetting& sim_setting) {
|
||||
sim_setting.set_monte_carlo_simulation_points(
|
||||
get_attribute(xml_mc, "num_simulation_points", loc_data).as_int(0));
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Parse XML codes of a <measurement_setting> to an object of simulation setting
|
||||
*******************************************************************/
|
||||
static
|
||||
void read_xml_measurement_setting(pugi::xml_node& xml_measurement,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
openfpga::SimulationSetting& sim_setting) {
|
||||
static void read_xml_measurement_setting(
|
||||
pugi::xml_node& xml_measurement, const pugiutil::loc_data& loc_data,
|
||||
openfpga::SimulationSetting& sim_setting) {
|
||||
pugi::xml_node xml_slew = get_single_child(xml_measurement, "slew", loc_data);
|
||||
pugi::xml_node xml_slew_rise = get_single_child(xml_slew, "rise", loc_data);
|
||||
sim_setting.set_measure_slew_upper_threshold(SIM_SIGNAL_RISE, get_attribute(xml_slew_rise, "upper_thres_pct", loc_data).as_float(0.));
|
||||
sim_setting.set_measure_slew_lower_threshold(SIM_SIGNAL_RISE, get_attribute(xml_slew_rise, "lower_thres_pct", loc_data).as_float(0.));
|
||||
sim_setting.set_measure_slew_upper_threshold(
|
||||
SIM_SIGNAL_RISE,
|
||||
get_attribute(xml_slew_rise, "upper_thres_pct", loc_data).as_float(0.));
|
||||
sim_setting.set_measure_slew_lower_threshold(
|
||||
SIM_SIGNAL_RISE,
|
||||
get_attribute(xml_slew_rise, "lower_thres_pct", loc_data).as_float(0.));
|
||||
|
||||
pugi::xml_node xml_slew_fall = get_single_child(xml_slew, "fall", loc_data);
|
||||
sim_setting.set_measure_slew_upper_threshold(SIM_SIGNAL_FALL, get_attribute(xml_slew_fall, "upper_thres_pct", loc_data).as_float(0.));
|
||||
sim_setting.set_measure_slew_lower_threshold(SIM_SIGNAL_FALL, get_attribute(xml_slew_fall, "lower_thres_pct", loc_data).as_float(0.));
|
||||
sim_setting.set_measure_slew_upper_threshold(
|
||||
SIM_SIGNAL_FALL,
|
||||
get_attribute(xml_slew_fall, "upper_thres_pct", loc_data).as_float(0.));
|
||||
sim_setting.set_measure_slew_lower_threshold(
|
||||
SIM_SIGNAL_FALL,
|
||||
get_attribute(xml_slew_fall, "lower_thres_pct", loc_data).as_float(0.));
|
||||
|
||||
pugi::xml_node xml_delay = get_single_child(xml_measurement, "delay", loc_data);
|
||||
pugi::xml_node xml_delay =
|
||||
get_single_child(xml_measurement, "delay", loc_data);
|
||||
pugi::xml_node xml_delay_rise = get_single_child(xml_delay, "rise", loc_data);
|
||||
sim_setting.set_measure_delay_input_threshold(SIM_SIGNAL_RISE, get_attribute(xml_delay_rise, "input_thres_pct", loc_data).as_float(0.));
|
||||
sim_setting.set_measure_delay_output_threshold(SIM_SIGNAL_RISE, get_attribute(xml_delay_rise, "output_thres_pct", loc_data).as_float(0.));
|
||||
sim_setting.set_measure_delay_input_threshold(
|
||||
SIM_SIGNAL_RISE,
|
||||
get_attribute(xml_delay_rise, "input_thres_pct", loc_data).as_float(0.));
|
||||
sim_setting.set_measure_delay_output_threshold(
|
||||
SIM_SIGNAL_RISE,
|
||||
get_attribute(xml_delay_rise, "output_thres_pct", loc_data).as_float(0.));
|
||||
|
||||
pugi::xml_node xml_delay_fall = get_single_child(xml_delay, "fall", loc_data);
|
||||
sim_setting.set_measure_delay_input_threshold(SIM_SIGNAL_FALL, get_attribute(xml_delay_fall, "input_thres_pct", loc_data).as_float(0.));
|
||||
sim_setting.set_measure_delay_output_threshold(SIM_SIGNAL_FALL, get_attribute(xml_delay_fall, "output_thres_pct", loc_data).as_float(0.));
|
||||
sim_setting.set_measure_delay_input_threshold(
|
||||
SIM_SIGNAL_FALL,
|
||||
get_attribute(xml_delay_fall, "input_thres_pct", loc_data).as_float(0.));
|
||||
sim_setting.set_measure_delay_output_threshold(
|
||||
SIM_SIGNAL_FALL,
|
||||
get_attribute(xml_delay_fall, "output_thres_pct", loc_data).as_float(0.));
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Parse XML codes of a <clock> inside <stimulus> to an object of simulation setting
|
||||
* Parse XML codes of a <clock> inside <stimulus> to an object of simulation
|
||||
*setting
|
||||
*******************************************************************/
|
||||
static
|
||||
void read_xml_stimulus_clock(pugi::xml_node& xml_stimuli_clock,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
openfpga::SimulationSetting& sim_setting,
|
||||
const e_sim_signal_type& signal_type) {
|
||||
static void read_xml_stimulus_clock(pugi::xml_node& xml_stimuli_clock,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
openfpga::SimulationSetting& sim_setting,
|
||||
const e_sim_signal_type& signal_type) {
|
||||
/* Find the type of accuracy */
|
||||
const char* type_attr = get_attribute(xml_stimuli_clock, "slew_type", loc_data).value();
|
||||
const char* type_attr =
|
||||
get_attribute(xml_stimuli_clock, "slew_type", loc_data).value();
|
||||
/* Translate the type of design technology to enumerate */
|
||||
e_sim_accuracy_type accuracy_type = string_to_sim_accuracy_type(std::string(type_attr));
|
||||
e_sim_accuracy_type accuracy_type =
|
||||
string_to_sim_accuracy_type(std::string(type_attr));
|
||||
|
||||
if (NUM_SIM_ACCURACY_TYPES == accuracy_type) {
|
||||
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_stimuli_clock),
|
||||
"Invalid 'type' attribute '%s'\n",
|
||||
type_attr);
|
||||
"Invalid 'type' attribute '%s'\n", type_attr);
|
||||
}
|
||||
|
||||
sim_setting.set_stimuli_clock_slew_type(signal_type, accuracy_type);
|
||||
|
||||
sim_setting.set_stimuli_clock_slew(signal_type, get_attribute(xml_stimuli_clock, "slew_time", loc_data).as_float(0.));
|
||||
sim_setting.set_stimuli_clock_slew(
|
||||
signal_type,
|
||||
get_attribute(xml_stimuli_clock, "slew_time", loc_data).as_float(0.));
|
||||
|
||||
/* Validate the accuracy value */
|
||||
if (SIM_ACCURACY_FRAC == sim_setting.stimuli_clock_slew_type(signal_type)) {
|
||||
if (false == sim_setting.valid_signal_threshold(sim_setting.stimuli_clock_slew(signal_type))) {
|
||||
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_stimuli_clock),
|
||||
"Invalid 'value' attribute '%f', which should be in the range of (0,1)\n",
|
||||
if (false == sim_setting.valid_signal_threshold(
|
||||
sim_setting.stimuli_clock_slew(signal_type))) {
|
||||
archfpga_throw(loc_data.filename_c_str(),
|
||||
loc_data.line(xml_stimuli_clock),
|
||||
"Invalid 'value' attribute '%f', which should be in the "
|
||||
"range of (0,1)\n",
|
||||
sim_setting.stimuli_clock_slew(signal_type));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Parse XML codes of a <input> inside <stimulus> to an object of simulation setting
|
||||
* Parse XML codes of a <input> inside <stimulus> to an object of simulation
|
||||
*setting
|
||||
*******************************************************************/
|
||||
static
|
||||
void read_xml_stimulus_input(pugi::xml_node& xml_stimuli_input,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
openfpga::SimulationSetting& sim_setting,
|
||||
const e_sim_signal_type& signal_type) {
|
||||
static void read_xml_stimulus_input(pugi::xml_node& xml_stimuli_input,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
openfpga::SimulationSetting& sim_setting,
|
||||
const e_sim_signal_type& signal_type) {
|
||||
/* Find the type of accuracy */
|
||||
const char* type_attr = get_attribute(xml_stimuli_input, "slew_type", loc_data).value();
|
||||
const char* type_attr =
|
||||
get_attribute(xml_stimuli_input, "slew_type", loc_data).value();
|
||||
/* Translate the type of design technology to enumerate */
|
||||
e_sim_accuracy_type accuracy_type = string_to_sim_accuracy_type(std::string(type_attr));
|
||||
e_sim_accuracy_type accuracy_type =
|
||||
string_to_sim_accuracy_type(std::string(type_attr));
|
||||
|
||||
if (NUM_SIM_ACCURACY_TYPES == accuracy_type) {
|
||||
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_stimuli_input),
|
||||
"Invalid 'type' attribute '%s'\n",
|
||||
type_attr);
|
||||
"Invalid 'type' attribute '%s'\n", type_attr);
|
||||
}
|
||||
|
||||
sim_setting.set_stimuli_input_slew_type(signal_type, accuracy_type);
|
||||
|
||||
sim_setting.set_stimuli_input_slew(signal_type, get_attribute(xml_stimuli_input, "slew_time", loc_data).as_float(0.));
|
||||
sim_setting.set_stimuli_input_slew(
|
||||
signal_type,
|
||||
get_attribute(xml_stimuli_input, "slew_time", loc_data).as_float(0.));
|
||||
|
||||
/* Validate the accuracy value */
|
||||
if (SIM_ACCURACY_FRAC == sim_setting.stimuli_input_slew_type(signal_type)) {
|
||||
if (false == sim_setting.valid_signal_threshold(sim_setting.stimuli_input_slew(signal_type))) {
|
||||
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_stimuli_input),
|
||||
"Invalid 'value' attribute '%f', which should be in the range of (0,1)\n",
|
||||
if (false == sim_setting.valid_signal_threshold(
|
||||
sim_setting.stimuli_input_slew(signal_type))) {
|
||||
archfpga_throw(loc_data.filename_c_str(),
|
||||
loc_data.line(xml_stimuli_input),
|
||||
"Invalid 'value' attribute '%f', which should be in the "
|
||||
"range of (0,1)\n",
|
||||
sim_setting.stimuli_input_slew(signal_type));
|
||||
}
|
||||
}
|
||||
|
@ -298,48 +369,56 @@ void read_xml_stimulus_input(pugi::xml_node& xml_stimuli_input,
|
|||
/********************************************************************
|
||||
* Parse XML codes of a <stimulus> to an object of simulation setting
|
||||
*******************************************************************/
|
||||
static
|
||||
void read_xml_stimulus(pugi::xml_node& xml_stimulus,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
openfpga::SimulationSetting& sim_setting) {
|
||||
static void read_xml_stimulus(pugi::xml_node& xml_stimulus,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
openfpga::SimulationSetting& sim_setting) {
|
||||
pugi::xml_node xml_clock = get_single_child(xml_stimulus, "clock", loc_data);
|
||||
pugi::xml_node xml_clock_rise = get_single_child(xml_clock, "rise", loc_data);
|
||||
read_xml_stimulus_clock(xml_clock_rise, loc_data, sim_setting, SIM_SIGNAL_RISE);
|
||||
read_xml_stimulus_clock(xml_clock_rise, loc_data, sim_setting,
|
||||
SIM_SIGNAL_RISE);
|
||||
|
||||
pugi::xml_node xml_clock_fall = get_single_child(xml_clock, "fall", loc_data);
|
||||
read_xml_stimulus_clock(xml_clock_fall, loc_data, sim_setting, SIM_SIGNAL_FALL);
|
||||
read_xml_stimulus_clock(xml_clock_fall, loc_data, sim_setting,
|
||||
SIM_SIGNAL_FALL);
|
||||
|
||||
pugi::xml_node xml_input = get_single_child(xml_stimulus, "input", loc_data);
|
||||
pugi::xml_node xml_input_rise = get_single_child(xml_input, "rise", loc_data);
|
||||
read_xml_stimulus_input(xml_input_rise, loc_data, sim_setting, SIM_SIGNAL_RISE);
|
||||
read_xml_stimulus_input(xml_input_rise, loc_data, sim_setting,
|
||||
SIM_SIGNAL_RISE);
|
||||
|
||||
pugi::xml_node xml_input_fall = get_single_child(xml_input, "fall", loc_data);
|
||||
read_xml_stimulus_input(xml_input_fall, loc_data, sim_setting, SIM_SIGNAL_FALL);
|
||||
read_xml_stimulus_input(xml_input_fall, loc_data, sim_setting,
|
||||
SIM_SIGNAL_FALL);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Parse XML codes about <openfpga_simulation_setting> to an object of technology library
|
||||
* Parse XML codes about <openfpga_simulation_setting> to an object of
|
||||
*technology library
|
||||
*******************************************************************/
|
||||
openfpga::SimulationSetting read_xml_simulation_setting(pugi::xml_node& Node,
|
||||
const pugiutil::loc_data& loc_data) {
|
||||
openfpga::SimulationSetting read_xml_simulation_setting(
|
||||
pugi::xml_node& Node, const pugiutil::loc_data& loc_data) {
|
||||
openfpga::SimulationSetting sim_setting;
|
||||
|
||||
/* Parse clock settings */
|
||||
pugi::xml_node xml_clock_setting = get_single_child(Node, "clock_setting", loc_data);
|
||||
pugi::xml_node xml_clock_setting =
|
||||
get_single_child(Node, "clock_setting", loc_data);
|
||||
read_xml_clock_setting(xml_clock_setting, loc_data, sim_setting);
|
||||
|
||||
/* Parse simulator options */
|
||||
pugi::xml_node xml_simulator_option = get_single_child(Node, "simulator_option", loc_data);
|
||||
pugi::xml_node xml_simulator_option =
|
||||
get_single_child(Node, "simulator_option", loc_data);
|
||||
read_xml_simulator_option(xml_simulator_option, loc_data, sim_setting);
|
||||
|
||||
/* Parse Monte carlo simulation options */
|
||||
pugi::xml_node xml_mc = get_single_child(Node, "monte_carlo", loc_data, pugiutil::ReqOpt::OPTIONAL);
|
||||
pugi::xml_node xml_mc =
|
||||
get_single_child(Node, "monte_carlo", loc_data, pugiutil::ReqOpt::OPTIONAL);
|
||||
if (xml_mc) {
|
||||
read_xml_monte_carlo(xml_mc, loc_data, sim_setting);
|
||||
}
|
||||
|
||||
/* Parse measurement settings */
|
||||
pugi::xml_node xml_measurement = get_single_child(Node, "measurement_setting", loc_data);
|
||||
pugi::xml_node xml_measurement =
|
||||
get_single_child(Node, "measurement_setting", loc_data);
|
||||
read_xml_measurement_setting(xml_measurement, loc_data, sim_setting);
|
||||
|
||||
/* Parse stimulus settings */
|
||||
|
|
|
@ -4,15 +4,15 @@
|
|||
/********************************************************************
|
||||
* Include header files that are required by function declaration
|
||||
*******************************************************************/
|
||||
#include "pugixml_util.hpp"
|
||||
#include "pugixml.hpp"
|
||||
#include "pugixml_util.hpp"
|
||||
#include "simulation_setting.h"
|
||||
|
||||
/********************************************************************
|
||||
* Function declaration
|
||||
*******************************************************************/
|
||||
|
||||
openfpga::SimulationSetting read_xml_simulation_setting(pugi::xml_node& Node,
|
||||
const pugiutil::loc_data& loc_data);
|
||||
openfpga::SimulationSetting read_xml_simulation_setting(
|
||||
pugi::xml_node& Node, const pugiutil::loc_data& loc_data);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -14,15 +14,14 @@
|
|||
|
||||
/* Headers from libarchfpga */
|
||||
#include "arch_error.h"
|
||||
#include "read_xml_util.h"
|
||||
|
||||
#include "read_xml_technology_library.h"
|
||||
#include "read_xml_util.h"
|
||||
|
||||
/********************************************************************
|
||||
* Convert string to the enumerate of device model type
|
||||
*******************************************************************/
|
||||
static
|
||||
e_tech_lib_model_type string_to_device_model_type(const std::string& type_string) {
|
||||
static e_tech_lib_model_type string_to_device_model_type(
|
||||
const std::string& type_string) {
|
||||
for (size_t itype = 0; itype < NUM_TECH_LIB_MODEL_TYPES; ++itype) {
|
||||
if (std::string(TECH_LIB_MODEL_TYPE_STRING[itype]) == type_string) {
|
||||
return static_cast<e_tech_lib_model_type>(itype);
|
||||
|
@ -35,8 +34,7 @@ e_tech_lib_model_type string_to_device_model_type(const std::string& type_string
|
|||
/********************************************************************
|
||||
* Convert string to the enumerate of technology library type
|
||||
*******************************************************************/
|
||||
static
|
||||
e_tech_lib_type string_to_tech_lib_type(const std::string& type_string) {
|
||||
static e_tech_lib_type string_to_tech_lib_type(const std::string& type_string) {
|
||||
for (size_t itype = 0; itype < NUM_TECH_LIB_TYPES; ++itype) {
|
||||
if (std::string(TECH_LIB_TYPE_STRING[itype]) == type_string) {
|
||||
return static_cast<e_tech_lib_type>(itype);
|
||||
|
@ -47,152 +45,187 @@ e_tech_lib_type string_to_tech_lib_type(const std::string& type_string) {
|
|||
}
|
||||
|
||||
/********************************************************************
|
||||
* Parse XML codes of a <lib> under a device model definiton
|
||||
* Parse XML codes of a <lib> under a device model definiton
|
||||
* to an object of technology library
|
||||
*******************************************************************/
|
||||
static
|
||||
void read_xml_device_model_lib_settings(pugi::xml_node& xml_device_model_lib,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
TechnologyLibrary& tech_lib,
|
||||
TechnologyModelId& device_model) {
|
||||
static void read_xml_device_model_lib_settings(
|
||||
pugi::xml_node& xml_device_model_lib, const pugiutil::loc_data& loc_data,
|
||||
TechnologyLibrary& tech_lib, TechnologyModelId& device_model) {
|
||||
/* Parse the type of model library */
|
||||
const char* type_attr = get_attribute(xml_device_model_lib, "type", loc_data).value();
|
||||
const char* type_attr =
|
||||
get_attribute(xml_device_model_lib, "type", loc_data).value();
|
||||
/* Translate the type of design technology to enumerate */
|
||||
e_tech_lib_type device_model_lib_type = string_to_tech_lib_type(std::string(type_attr));
|
||||
e_tech_lib_type device_model_lib_type =
|
||||
string_to_tech_lib_type(std::string(type_attr));
|
||||
|
||||
if (NUM_TECH_LIB_TYPES == device_model_lib_type) {
|
||||
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_device_model_lib),
|
||||
"Invalid 'type' attribute '%s'\n",
|
||||
type_attr);
|
||||
archfpga_throw(loc_data.filename_c_str(),
|
||||
loc_data.line(xml_device_model_lib),
|
||||
"Invalid 'type' attribute '%s'\n", type_attr);
|
||||
}
|
||||
|
||||
tech_lib.set_model_lib_type(device_model, device_model_lib_type);
|
||||
|
||||
/* Parse the type of process corner, this is ONLY applicable to industry library */
|
||||
/* Parse the type of process corner, this is ONLY applicable to industry
|
||||
* library */
|
||||
if (TECH_LIB_INDUSTRY == tech_lib.model_lib_type(device_model)) {
|
||||
tech_lib.set_model_corner(device_model, get_attribute(xml_device_model_lib, "corner", loc_data).as_string());
|
||||
tech_lib.set_model_corner(
|
||||
device_model,
|
||||
get_attribute(xml_device_model_lib, "corner", loc_data).as_string());
|
||||
}
|
||||
|
||||
/* Parse the model reference */
|
||||
tech_lib.set_model_ref(device_model, get_attribute(xml_device_model_lib, "ref", loc_data).as_string());
|
||||
tech_lib.set_model_ref(
|
||||
device_model,
|
||||
get_attribute(xml_device_model_lib, "ref", loc_data).as_string());
|
||||
|
||||
/* Parse the lib path */
|
||||
tech_lib.set_model_lib_path(device_model, get_attribute(xml_device_model_lib, "path", loc_data).as_string());
|
||||
tech_lib.set_model_lib_path(
|
||||
device_model,
|
||||
get_attribute(xml_device_model_lib, "path", loc_data).as_string());
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Parse XML codes of design parameters under a device model
|
||||
* to an object of technology library
|
||||
*******************************************************************/
|
||||
static
|
||||
void read_xml_device_model_design_settings(pugi::xml_node& xml_device_model_design,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
TechnologyLibrary& tech_lib,
|
||||
TechnologyModelId& device_model) {
|
||||
static void read_xml_device_model_design_settings(
|
||||
pugi::xml_node& xml_device_model_design, const pugiutil::loc_data& loc_data,
|
||||
TechnologyLibrary& tech_lib, TechnologyModelId& device_model) {
|
||||
/* Parse the vdd to be used in circuit design */
|
||||
tech_lib.set_model_vdd(device_model, get_attribute(xml_device_model_design, "vdd", loc_data).as_float(0.));
|
||||
tech_lib.set_model_vdd(
|
||||
device_model,
|
||||
get_attribute(xml_device_model_design, "vdd", loc_data).as_float(0.));
|
||||
|
||||
/* Parse the width ratio between PMOS and NMOS transistor */
|
||||
tech_lib.set_model_pn_ratio(device_model, get_attribute(xml_device_model_design, "pn_ratio", loc_data).as_float(0.));
|
||||
tech_lib.set_model_pn_ratio(
|
||||
device_model,
|
||||
get_attribute(xml_device_model_design, "pn_ratio", loc_data).as_float(0.));
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Parse XML codes of transistor models under a device model
|
||||
* to an object of technology library
|
||||
*******************************************************************/
|
||||
static
|
||||
void read_xml_device_transistor(pugi::xml_node& xml_device_transistor,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
TechnologyLibrary& tech_lib,
|
||||
TechnologyModelId& device_model,
|
||||
const e_tech_lib_transistor_type& transistor_type) {
|
||||
static void read_xml_device_transistor(
|
||||
pugi::xml_node& xml_device_transistor, const pugiutil::loc_data& loc_data,
|
||||
TechnologyLibrary& tech_lib, TechnologyModelId& device_model,
|
||||
const e_tech_lib_transistor_type& transistor_type) {
|
||||
/* Parse the transistor model name */
|
||||
tech_lib.set_transistor_model_name(device_model, transistor_type,
|
||||
get_attribute(xml_device_transistor, "name", loc_data).as_string());
|
||||
tech_lib.set_transistor_model_name(
|
||||
device_model, transistor_type,
|
||||
get_attribute(xml_device_transistor, "name", loc_data).as_string());
|
||||
|
||||
/* Parse the transistor channel length */
|
||||
tech_lib.set_transistor_model_chan_length(device_model, transistor_type,
|
||||
get_attribute(xml_device_transistor, "chan_length", loc_data).as_float(0.));
|
||||
tech_lib.set_transistor_model_chan_length(
|
||||
device_model, transistor_type,
|
||||
get_attribute(xml_device_transistor, "chan_length", loc_data).as_float(0.));
|
||||
|
||||
/* Parse the transistor minimum width */
|
||||
tech_lib.set_transistor_model_min_width(device_model, transistor_type,
|
||||
get_attribute(xml_device_transistor, "min_width", loc_data).as_float(0.));
|
||||
tech_lib.set_transistor_model_min_width(
|
||||
device_model, transistor_type,
|
||||
get_attribute(xml_device_transistor, "min_width", loc_data).as_float(0.));
|
||||
|
||||
/* Parse the transistor maximum width, by default we consider the same as minimum width */
|
||||
tech_lib.set_transistor_model_max_width(device_model, transistor_type,
|
||||
get_attribute(xml_device_transistor, "max_width", loc_data, pugiutil::ReqOpt::OPTIONAL).as_float(0.));
|
||||
/* Parse the transistor maximum width, by default we consider the same as
|
||||
* minimum width */
|
||||
tech_lib.set_transistor_model_max_width(
|
||||
device_model, transistor_type,
|
||||
get_attribute(xml_device_transistor, "max_width", loc_data,
|
||||
pugiutil::ReqOpt::OPTIONAL)
|
||||
.as_float(0.));
|
||||
/* If the max_width is default value, we set it to be the same as min_width */
|
||||
if (0. == tech_lib.transistor_model_max_width(device_model, transistor_type)) {
|
||||
tech_lib.set_transistor_model_max_width(device_model, transistor_type, tech_lib.transistor_model_min_width(device_model, transistor_type));
|
||||
if (0. ==
|
||||
tech_lib.transistor_model_max_width(device_model, transistor_type)) {
|
||||
tech_lib.set_transistor_model_max_width(
|
||||
device_model, transistor_type,
|
||||
tech_lib.transistor_model_min_width(device_model, transistor_type));
|
||||
}
|
||||
|
||||
/* Parse the transistor variation name */
|
||||
tech_lib.set_transistor_model_variation_name(device_model, transistor_type,
|
||||
get_attribute(xml_device_transistor, "variation", loc_data).as_string());
|
||||
tech_lib.set_transistor_model_variation_name(
|
||||
device_model, transistor_type,
|
||||
get_attribute(xml_device_transistor, "variation", loc_data).as_string());
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Parse XML codes of RRAM models under a device model
|
||||
* to an object of technology library
|
||||
*******************************************************************/
|
||||
static
|
||||
void read_xml_device_rram(pugi::xml_node& xml_device_rram,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
TechnologyLibrary& tech_lib,
|
||||
TechnologyModelId& device_model) {
|
||||
static void read_xml_device_rram(pugi::xml_node& xml_device_rram,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
TechnologyLibrary& tech_lib,
|
||||
TechnologyModelId& device_model) {
|
||||
/* Parse the LRS and HRS resistance */
|
||||
tech_lib.set_rram_rlrs(device_model, get_attribute(xml_device_rram, "rlrs", loc_data).as_float(0.));
|
||||
tech_lib.set_rram_rhrs(device_model, get_attribute(xml_device_rram, "rhrs", loc_data).as_float(0.));
|
||||
tech_lib.set_rram_rlrs(
|
||||
device_model,
|
||||
get_attribute(xml_device_rram, "rlrs", loc_data).as_float(0.));
|
||||
tech_lib.set_rram_rhrs(
|
||||
device_model,
|
||||
get_attribute(xml_device_rram, "rhrs", loc_data).as_float(0.));
|
||||
|
||||
/* Parse the RRAM variation name */
|
||||
tech_lib.set_rram_variation_name(device_model, get_attribute(xml_device_rram, "variation", loc_data).as_string());
|
||||
tech_lib.set_rram_variation_name(
|
||||
device_model,
|
||||
get_attribute(xml_device_rram, "variation", loc_data).as_string());
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Parse XML codes of a <device> to an object of technology library
|
||||
*******************************************************************/
|
||||
static
|
||||
void read_xml_device_model(pugi::xml_node& xml_device_model,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
TechnologyLibrary& tech_lib) {
|
||||
/* Get the name of this device_model node and add a device to the technology library */
|
||||
TechnologyModelId device_model = tech_lib.add_model(get_attribute(xml_device_model, "name", loc_data).as_string());
|
||||
static void read_xml_device_model(pugi::xml_node& xml_device_model,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
TechnologyLibrary& tech_lib) {
|
||||
/* Get the name of this device_model node and add a device to the technology
|
||||
* library */
|
||||
TechnologyModelId device_model = tech_lib.add_model(
|
||||
get_attribute(xml_device_model, "name", loc_data).as_string());
|
||||
|
||||
/* Find the type of device model*/
|
||||
const char* type_attr = get_attribute(xml_device_model, "type", loc_data).value();
|
||||
const char* type_attr =
|
||||
get_attribute(xml_device_model, "type", loc_data).value();
|
||||
/* Translate the type of design technology to enumerate */
|
||||
e_tech_lib_model_type device_model_type = string_to_device_model_type(std::string(type_attr));
|
||||
e_tech_lib_model_type device_model_type =
|
||||
string_to_device_model_type(std::string(type_attr));
|
||||
|
||||
if (NUM_TECH_LIB_MODEL_TYPES == device_model_type) {
|
||||
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_device_model),
|
||||
"Invalid 'type' attribute '%s'\n",
|
||||
type_attr);
|
||||
"Invalid 'type' attribute '%s'\n", type_attr);
|
||||
}
|
||||
|
||||
tech_lib.set_model_type(device_model, device_model_type);
|
||||
|
||||
/* Model library -relate attributes */
|
||||
auto xml_device_model_lib = get_single_child(xml_device_model, "lib", loc_data);
|
||||
read_xml_device_model_lib_settings(xml_device_model_lib, loc_data, tech_lib, device_model);
|
||||
auto xml_device_model_lib =
|
||||
get_single_child(xml_device_model, "lib", loc_data);
|
||||
read_xml_device_model_lib_settings(xml_device_model_lib, loc_data, tech_lib,
|
||||
device_model);
|
||||
|
||||
/* Model design -relate attributes, this is ONLY applicable to transistor models */
|
||||
/* Model design -relate attributes, this is ONLY applicable to transistor
|
||||
* models */
|
||||
if (TECH_LIB_MODEL_TRANSISTOR == tech_lib.model_type(device_model)) {
|
||||
auto xml_device_model_design = get_single_child(xml_device_model, "design", loc_data);
|
||||
read_xml_device_model_design_settings(xml_device_model_design, loc_data, tech_lib, device_model);
|
||||
auto xml_device_model_design =
|
||||
get_single_child(xml_device_model, "design", loc_data);
|
||||
read_xml_device_model_design_settings(xml_device_model_design, loc_data,
|
||||
tech_lib, device_model);
|
||||
}
|
||||
|
||||
/* Transistor -relate attributes, this is ONLY applicable to transistor models */
|
||||
/* Transistor -relate attributes, this is ONLY applicable to transistor models
|
||||
*/
|
||||
if (TECH_LIB_MODEL_TRANSISTOR == tech_lib.model_type(device_model)) {
|
||||
auto xml_device_model_pmos = get_single_child(xml_device_model, "pmos", loc_data);
|
||||
read_xml_device_transistor(xml_device_model_pmos, loc_data, tech_lib, device_model, TECH_LIB_TRANSISTOR_PMOS);
|
||||
auto xml_device_model_pmos =
|
||||
get_single_child(xml_device_model, "pmos", loc_data);
|
||||
read_xml_device_transistor(xml_device_model_pmos, loc_data, tech_lib,
|
||||
device_model, TECH_LIB_TRANSISTOR_PMOS);
|
||||
|
||||
auto xml_device_model_nmos = get_single_child(xml_device_model, "nmos", loc_data);
|
||||
read_xml_device_transistor(xml_device_model_nmos, loc_data, tech_lib, device_model, TECH_LIB_TRANSISTOR_NMOS);
|
||||
auto xml_device_model_nmos =
|
||||
get_single_child(xml_device_model, "nmos", loc_data);
|
||||
read_xml_device_transistor(xml_device_model_nmos, loc_data, tech_lib,
|
||||
device_model, TECH_LIB_TRANSISTOR_NMOS);
|
||||
}
|
||||
|
||||
/* RRAM -relate attributes, this is ONLY applicable to RRAM models */
|
||||
if (TECH_LIB_MODEL_RRAM == tech_lib.model_type(device_model)) {
|
||||
auto xml_device_rram = get_single_child(xml_device_model, "rram", loc_data);
|
||||
auto xml_device_rram = get_single_child(xml_device_model, "rram", loc_data);
|
||||
read_xml_device_rram(xml_device_rram, loc_data, tech_lib, device_model);
|
||||
}
|
||||
}
|
||||
|
@ -200,24 +233,27 @@ void read_xml_device_model(pugi::xml_node& xml_device_model,
|
|||
/********************************************************************
|
||||
* Parse XML codes of a <variation> to an object of technology library
|
||||
*******************************************************************/
|
||||
static
|
||||
void read_xml_device_variation(pugi::xml_node& xml_device_variation,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
TechnologyLibrary& tech_lib) {
|
||||
static void read_xml_device_variation(pugi::xml_node& xml_device_variation,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
TechnologyLibrary& tech_lib) {
|
||||
/* Get the name of this variation and add it to the technology library */
|
||||
TechnologyVariationId variation = tech_lib.add_variation(get_attribute(xml_device_variation, "name", loc_data).as_string());
|
||||
TechnologyVariationId variation = tech_lib.add_variation(
|
||||
get_attribute(xml_device_variation, "name", loc_data).as_string());
|
||||
|
||||
tech_lib.set_variation_abs_value(variation, get_attribute(xml_device_variation, "abs_deviation", loc_data).as_float(0.));
|
||||
tech_lib.set_variation_num_sigma(variation, get_attribute(xml_device_variation, "num_sigma", loc_data).as_int(0.));
|
||||
tech_lib.set_variation_abs_value(
|
||||
variation, get_attribute(xml_device_variation, "abs_deviation", loc_data)
|
||||
.as_float(0.));
|
||||
tech_lib.set_variation_num_sigma(
|
||||
variation,
|
||||
get_attribute(xml_device_variation, "num_sigma", loc_data).as_int(0.));
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Parse XML codes of a <device_library> to an object of technology library
|
||||
*******************************************************************/
|
||||
static
|
||||
void read_xml_device_lib(pugi::xml_node& xml_device_lib,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
TechnologyLibrary& tech_lib) {
|
||||
static void read_xml_device_lib(pugi::xml_node& xml_device_lib,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
TechnologyLibrary& tech_lib) {
|
||||
/* Iterate over the children under this node,
|
||||
* each child should be named after <device>
|
||||
*/
|
||||
|
@ -227,16 +263,15 @@ void read_xml_device_lib(pugi::xml_node& xml_device_lib,
|
|||
bad_tag(xml_device_model, loc_data, xml_device_lib, {"device_model"});
|
||||
}
|
||||
read_xml_device_model(xml_device_model, loc_data, tech_lib);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Parse XML codes of a <variation_library> to an object of technology library
|
||||
*******************************************************************/
|
||||
static
|
||||
void read_xml_variation_lib(pugi::xml_node& xml_variation_lib,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
TechnologyLibrary& tech_lib) {
|
||||
static void read_xml_variation_lib(pugi::xml_node& xml_variation_lib,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
TechnologyLibrary& tech_lib) {
|
||||
/* Iterate over the children under this node,
|
||||
* each child should be named after <variation>
|
||||
*/
|
||||
|
@ -246,14 +281,14 @@ void read_xml_variation_lib(pugi::xml_node& xml_variation_lib,
|
|||
bad_tag(xml_device_variation, loc_data, xml_variation_lib, {"variation"});
|
||||
}
|
||||
read_xml_device_variation(xml_device_variation, loc_data, tech_lib);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Parse XML codes about <technology_library> to an object of technology library
|
||||
*******************************************************************/
|
||||
TechnologyLibrary read_xml_technology_library(pugi::xml_node& Node,
|
||||
const pugiutil::loc_data& loc_data) {
|
||||
TechnologyLibrary read_xml_technology_library(
|
||||
pugi::xml_node& Node, const pugiutil::loc_data& loc_data) {
|
||||
TechnologyLibrary tech_lib;
|
||||
|
||||
/* Iterate over the children under this node,
|
||||
|
@ -263,20 +298,25 @@ TechnologyLibrary read_xml_technology_library(pugi::xml_node& Node,
|
|||
*/
|
||||
size_t num_device_lib = count_children(Node, "device_library", loc_data);
|
||||
if (1 != num_device_lib) {
|
||||
archfpga_throw(loc_data.filename_c_str(), loc_data.line(Node),
|
||||
"Expect only 1 <device_library> defined under <technology_library>");
|
||||
archfpga_throw(
|
||||
loc_data.filename_c_str(), loc_data.line(Node),
|
||||
"Expect only 1 <device_library> defined under <technology_library>");
|
||||
}
|
||||
|
||||
pugi::xml_node xml_device_lib = get_first_child(Node, "device_library", loc_data);
|
||||
|
||||
pugi::xml_node xml_device_lib =
|
||||
get_first_child(Node, "device_library", loc_data);
|
||||
read_xml_device_lib(xml_device_lib, loc_data, tech_lib);
|
||||
|
||||
size_t num_variation_lib = count_children(Node, "variation_library", loc_data);
|
||||
size_t num_variation_lib =
|
||||
count_children(Node, "variation_library", loc_data);
|
||||
if (1 != num_variation_lib) {
|
||||
archfpga_throw(loc_data.filename_c_str(), loc_data.line(Node),
|
||||
"Expect only 1 <variation_library> defined under <technology_library>");
|
||||
archfpga_throw(
|
||||
loc_data.filename_c_str(), loc_data.line(Node),
|
||||
"Expect only 1 <variation_library> defined under <technology_library>");
|
||||
}
|
||||
|
||||
pugi::xml_node xml_variation_lib = get_first_child(Node, "variation_library", loc_data);
|
||||
pugi::xml_node xml_variation_lib =
|
||||
get_first_child(Node, "variation_library", loc_data);
|
||||
read_xml_variation_lib(xml_variation_lib, loc_data, tech_lib);
|
||||
|
||||
return tech_lib;
|
||||
|
|
|
@ -4,14 +4,14 @@
|
|||
/********************************************************************
|
||||
* Include header files that are required by function declaration
|
||||
*******************************************************************/
|
||||
#include "pugixml_util.hpp"
|
||||
#include "pugixml.hpp"
|
||||
#include "pugixml_util.hpp"
|
||||
#include "technology_library.h"
|
||||
|
||||
/********************************************************************
|
||||
* Function declaration
|
||||
*******************************************************************/
|
||||
TechnologyLibrary read_xml_technology_library(pugi::xml_node& Node,
|
||||
const pugiutil::loc_data& loc_data);
|
||||
TechnologyLibrary read_xml_technology_library(
|
||||
pugi::xml_node& Node, const pugiutil::loc_data& loc_data);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -17,30 +17,31 @@
|
|||
#include "read_xml_util.h"
|
||||
|
||||
/* Headers from libopenfpgautil */
|
||||
#include "openfpga_tokenizer.h"
|
||||
#include "openfpga_port_parser.h"
|
||||
|
||||
#include "openfpga_tokenizer.h"
|
||||
#include "read_xml_tile_annotation.h"
|
||||
|
||||
/********************************************************************
|
||||
* Parse XML description for an interconnection annotation
|
||||
* Parse XML description for an interconnection annotation
|
||||
* under a <global_port> XML node
|
||||
*******************************************************************/
|
||||
static
|
||||
void read_xml_tile_global_port_annotation(pugi::xml_node& xml_tile,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
openfpga::TileAnnotation& tile_annotation) {
|
||||
/* We have mandatory XML attributes:
|
||||
* - name of the port
|
||||
static void read_xml_tile_global_port_annotation(
|
||||
pugi::xml_node& xml_tile, const pugiutil::loc_data& loc_data,
|
||||
openfpga::TileAnnotation& tile_annotation) {
|
||||
/* We have mandatory XML attributes:
|
||||
* - name of the port
|
||||
*/
|
||||
const std::string& name_attr = get_attribute(xml_tile, "name", loc_data).as_string();
|
||||
const std::string& name_attr =
|
||||
get_attribute(xml_tile, "name", loc_data).as_string();
|
||||
|
||||
TileGlobalPortId tile_global_port_id = tile_annotation.create_global_port(name_attr);
|
||||
TileGlobalPortId tile_global_port_id =
|
||||
tile_annotation.create_global_port(name_attr);
|
||||
|
||||
/* Report any duplicated port names */
|
||||
if (TileGlobalPortId::INVALID() == tile_global_port_id) {
|
||||
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_tile),
|
||||
"Invalid port name '%s' which is defined more than once in the global port list!\n",
|
||||
"Invalid port name '%s' which is defined more than once in "
|
||||
"the global port list!\n",
|
||||
name_attr.c_str());
|
||||
}
|
||||
|
||||
|
@ -53,59 +54,79 @@ void read_xml_tile_global_port_annotation(pugi::xml_node& xml_tile,
|
|||
bad_tag(xml_tile_port, loc_data, xml_tile, {"tile"});
|
||||
}
|
||||
/* Parse the name of the tiles and ports */
|
||||
const std::string& tile_name_attr = get_attribute(xml_tile_port, "name", loc_data).as_string();
|
||||
const std::string& port_name_attr = get_attribute(xml_tile_port, "port", loc_data).as_string();
|
||||
const std::string& tile_name_attr =
|
||||
get_attribute(xml_tile_port, "name", loc_data).as_string();
|
||||
const std::string& port_name_attr =
|
||||
get_attribute(xml_tile_port, "port", loc_data).as_string();
|
||||
|
||||
/* Extract the tile port information */
|
||||
openfpga::PortParser tile_port_parser(port_name_attr);
|
||||
|
||||
/* Parse tile coordinates */
|
||||
vtr::Point<size_t> tile_coord(get_attribute(xml_tile_port, "x", loc_data, pugiutil::ReqOpt::OPTIONAL).as_int(-1),
|
||||
get_attribute(xml_tile_port, "y", loc_data, pugiutil::ReqOpt::OPTIONAL).as_int(-1));
|
||||
|
||||
/* Add tile port information */
|
||||
tile_annotation.add_global_port_tile_information(tile_global_port_id,
|
||||
tile_name_attr,
|
||||
tile_port_parser.port(),
|
||||
tile_coord);
|
||||
}
|
||||
/* Parse tile coordinates */
|
||||
vtr::Point<size_t> tile_coord(
|
||||
get_attribute(xml_tile_port, "x", loc_data, pugiutil::ReqOpt::OPTIONAL)
|
||||
.as_int(-1),
|
||||
get_attribute(xml_tile_port, "y", loc_data, pugiutil::ReqOpt::OPTIONAL)
|
||||
.as_int(-1));
|
||||
|
||||
/* Add tile port information */
|
||||
tile_annotation.add_global_port_tile_information(
|
||||
tile_global_port_id, tile_name_attr, tile_port_parser.port(), tile_coord);
|
||||
}
|
||||
|
||||
/* Check: Must have at least one global port tile information */
|
||||
if (true == tile_annotation.global_port_tile_names(tile_global_port_id).empty()) {
|
||||
if (true ==
|
||||
tile_annotation.global_port_tile_names(tile_global_port_id).empty()) {
|
||||
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_tile),
|
||||
"Invalid tile annotation for global port '%s'! At least 1 tile port definition is expected!\n",
|
||||
"Invalid tile annotation for global port '%s'! At least 1 "
|
||||
"tile port definition is expected!\n",
|
||||
name_attr.c_str());
|
||||
}
|
||||
|
||||
/* Get is_clock attributes */
|
||||
tile_annotation.set_global_port_is_clock(tile_global_port_id, get_attribute(xml_tile, "is_clock", loc_data, pugiutil::ReqOpt::OPTIONAL).as_bool(false));
|
||||
tile_annotation.set_global_port_is_clock(
|
||||
tile_global_port_id,
|
||||
get_attribute(xml_tile, "is_clock", loc_data, pugiutil::ReqOpt::OPTIONAL)
|
||||
.as_bool(false));
|
||||
|
||||
/* Get is_set attributes */
|
||||
tile_annotation.set_global_port_is_set(tile_global_port_id, get_attribute(xml_tile, "is_set", loc_data, pugiutil::ReqOpt::OPTIONAL).as_bool(false));
|
||||
tile_annotation.set_global_port_is_set(
|
||||
tile_global_port_id,
|
||||
get_attribute(xml_tile, "is_set", loc_data, pugiutil::ReqOpt::OPTIONAL)
|
||||
.as_bool(false));
|
||||
|
||||
/* Get is_reset attributes */
|
||||
tile_annotation.set_global_port_is_reset(tile_global_port_id, get_attribute(xml_tile, "is_reset", loc_data, pugiutil::ReqOpt::OPTIONAL).as_bool(false));
|
||||
tile_annotation.set_global_port_is_reset(
|
||||
tile_global_port_id,
|
||||
get_attribute(xml_tile, "is_reset", loc_data, pugiutil::ReqOpt::OPTIONAL)
|
||||
.as_bool(false));
|
||||
|
||||
/* Get default_value attributes */
|
||||
tile_annotation.set_global_port_default_value(tile_global_port_id, get_attribute(xml_tile, "default_val", loc_data, pugiutil::ReqOpt::OPTIONAL).as_int(0));
|
||||
tile_annotation.set_global_port_default_value(
|
||||
tile_global_port_id,
|
||||
get_attribute(xml_tile, "default_val", loc_data, pugiutil::ReqOpt::OPTIONAL)
|
||||
.as_int(0));
|
||||
|
||||
/* Ensure valid port attributes */
|
||||
if (false == tile_annotation.valid_global_port_attributes(tile_global_port_id)) {
|
||||
if (false ==
|
||||
tile_annotation.valid_global_port_attributes(tile_global_port_id)) {
|
||||
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_tile),
|
||||
"Invalid port attributes for '%s'! A port can only be clock or set or reset.\n",
|
||||
"Invalid port attributes for '%s'! A port can only be clock "
|
||||
"or set or reset.\n",
|
||||
name_attr.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Top function to parse XML description about tile annotation
|
||||
* Top function to parse XML description about tile annotation
|
||||
*******************************************************************/
|
||||
openfpga::TileAnnotation read_xml_tile_annotations(pugi::xml_node& Node,
|
||||
const pugiutil::loc_data& loc_data) {
|
||||
openfpga::TileAnnotation read_xml_tile_annotations(
|
||||
pugi::xml_node& Node, const pugiutil::loc_data& loc_data) {
|
||||
openfpga::TileAnnotation tile_annotations;
|
||||
|
||||
/* Parse configuration protocol root node */
|
||||
pugi::xml_node xml_annotations = get_single_child(Node, "tile_annotations", loc_data, pugiutil::ReqOpt::OPTIONAL);
|
||||
pugi::xml_node xml_annotations = get_single_child(
|
||||
Node, "tile_annotations", loc_data, pugiutil::ReqOpt::OPTIONAL);
|
||||
|
||||
/* Not found, we can return */
|
||||
if (!xml_annotations) {
|
||||
|
@ -120,8 +141,9 @@ openfpga::TileAnnotation read_xml_tile_annotations(pugi::xml_node& Node,
|
|||
if (xml_tile_global_port.name() != std::string("global_port")) {
|
||||
bad_tag(xml_tile_global_port, loc_data, xml_annotations, {"global_port"});
|
||||
}
|
||||
read_xml_tile_global_port_annotation(xml_tile_global_port, loc_data, tile_annotations);
|
||||
}
|
||||
read_xml_tile_global_port_annotation(xml_tile_global_port, loc_data,
|
||||
tile_annotations);
|
||||
}
|
||||
|
||||
return tile_annotations;
|
||||
}
|
||||
|
|
|
@ -4,14 +4,14 @@
|
|||
/********************************************************************
|
||||
* Include header files that are required by function declaration
|
||||
*******************************************************************/
|
||||
#include "pugixml_util.hpp"
|
||||
#include "pugixml.hpp"
|
||||
#include "pugixml_util.hpp"
|
||||
#include "tile_annotation.h"
|
||||
|
||||
/********************************************************************
|
||||
* Function declaration
|
||||
*******************************************************************/
|
||||
openfpga::TileAnnotation read_xml_tile_annotations(pugi::xml_node& Node,
|
||||
const pugiutil::loc_data& loc_data);
|
||||
openfpga::TileAnnotation read_xml_tile_annotations(
|
||||
pugi::xml_node& Node, const pugiutil::loc_data& loc_data);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#include "vtr_assert.h"
|
||||
|
||||
#include "simulation_setting.h"
|
||||
|
||||
#include "vtr_assert.h"
|
||||
|
||||
/* namespace openfpga begins */
|
||||
namespace openfpga {
|
||||
|
||||
|
@ -36,7 +36,8 @@ std::vector<SimulationClockId> SimulationSetting::programming_clocks() const {
|
|||
return prog_clks;
|
||||
}
|
||||
|
||||
std::vector<SimulationClockId> SimulationSetting::programming_shift_register_clocks() const {
|
||||
std::vector<SimulationClockId>
|
||||
SimulationSetting::programming_shift_register_clocks() const {
|
||||
std::vector<SimulationClockId> prog_clks;
|
||||
for (const SimulationClockId& clk : clocks()) {
|
||||
if (clock_is_programming(clk) && clock_is_shift_register(clk)) {
|
||||
|
@ -49,9 +50,7 @@ std::vector<SimulationClockId> SimulationSetting::programming_shift_register_clo
|
|||
/************************************************************************
|
||||
* Constructors
|
||||
***********************************************************************/
|
||||
SimulationSetting::SimulationSetting() {
|
||||
return;
|
||||
}
|
||||
SimulationSetting::SimulationSetting() { return; }
|
||||
|
||||
/************************************************************************
|
||||
* Public Accessors
|
||||
|
@ -68,27 +67,32 @@ size_t SimulationSetting::num_simulation_clock_cycles() const {
|
|||
return clock_ids_.size();
|
||||
}
|
||||
|
||||
std::string SimulationSetting::clock_name(const SimulationClockId& clock_id) const {
|
||||
std::string SimulationSetting::clock_name(
|
||||
const SimulationClockId& clock_id) const {
|
||||
VTR_ASSERT(valid_clock_id(clock_id));
|
||||
return clock_names_[clock_id];
|
||||
}
|
||||
|
||||
BasicPort SimulationSetting::clock_port(const SimulationClockId& clock_id) const {
|
||||
BasicPort SimulationSetting::clock_port(
|
||||
const SimulationClockId& clock_id) const {
|
||||
VTR_ASSERT(valid_clock_id(clock_id));
|
||||
return clock_ports_[clock_id];
|
||||
}
|
||||
|
||||
float SimulationSetting::clock_frequency(const SimulationClockId& clock_id) const {
|
||||
float SimulationSetting::clock_frequency(
|
||||
const SimulationClockId& clock_id) const {
|
||||
VTR_ASSERT(valid_clock_id(clock_id));
|
||||
return clock_frequencies_[clock_id];
|
||||
}
|
||||
|
||||
bool SimulationSetting::clock_is_programming(const SimulationClockId& clock_id) const {
|
||||
bool SimulationSetting::clock_is_programming(
|
||||
const SimulationClockId& clock_id) const {
|
||||
VTR_ASSERT(valid_clock_id(clock_id));
|
||||
return clock_is_programming_[clock_id];
|
||||
}
|
||||
|
||||
bool SimulationSetting::clock_is_shift_register(const SimulationClockId& clock_id) const {
|
||||
bool SimulationSetting::clock_is_shift_register(
|
||||
const SimulationClockId& clock_id) const {
|
||||
VTR_ASSERT(valid_clock_id(clock_id));
|
||||
return clock_is_shift_register_[clock_id];
|
||||
}
|
||||
|
@ -97,9 +101,7 @@ bool SimulationSetting::auto_select_num_clock_cycles() const {
|
|||
return 0 == num_clock_cycles_;
|
||||
}
|
||||
|
||||
size_t SimulationSetting::num_clock_cycles() const {
|
||||
return num_clock_cycles_;
|
||||
}
|
||||
size_t SimulationSetting::num_clock_cycles() const { return num_clock_cycles_; }
|
||||
|
||||
float SimulationSetting::operating_clock_frequency_slack() const {
|
||||
return operating_clock_frequency_slack_;
|
||||
|
@ -109,9 +111,7 @@ float SimulationSetting::simulation_temperature() const {
|
|||
return simulation_temperature_;
|
||||
}
|
||||
|
||||
bool SimulationSetting::verbose_output() const {
|
||||
return verbose_output_;
|
||||
}
|
||||
bool SimulationSetting::verbose_output() const { return verbose_output_; }
|
||||
|
||||
bool SimulationSetting::capacitance_output() const {
|
||||
return capacitance_output_;
|
||||
|
@ -125,9 +125,7 @@ float SimulationSetting::simulation_accuracy() const {
|
|||
return simulation_accuracy_;
|
||||
}
|
||||
|
||||
bool SimulationSetting::fast_simulation() const {
|
||||
return fast_simulation_;
|
||||
}
|
||||
bool SimulationSetting::fast_simulation() const { return fast_simulation_; }
|
||||
|
||||
bool SimulationSetting::run_monte_carlo_simulation() const {
|
||||
return 0 == monte_carlo_simulation_points_;
|
||||
|
@ -137,56 +135,71 @@ size_t SimulationSetting::monte_carlo_simulation_points() const {
|
|||
return monte_carlo_simulation_points_;
|
||||
}
|
||||
|
||||
float SimulationSetting::measure_slew_upper_threshold(const e_sim_signal_type& signal_type) const {
|
||||
VTR_ASSERT (true == valid_signal_threshold(slew_upper_thresholds_[signal_type]));
|
||||
float SimulationSetting::measure_slew_upper_threshold(
|
||||
const e_sim_signal_type& signal_type) const {
|
||||
VTR_ASSERT(true ==
|
||||
valid_signal_threshold(slew_upper_thresholds_[signal_type]));
|
||||
return slew_upper_thresholds_[signal_type];
|
||||
}
|
||||
|
||||
float SimulationSetting::measure_slew_lower_threshold(const e_sim_signal_type& signal_type) const {
|
||||
VTR_ASSERT (true == valid_signal_threshold(slew_lower_thresholds_[signal_type]));
|
||||
float SimulationSetting::measure_slew_lower_threshold(
|
||||
const e_sim_signal_type& signal_type) const {
|
||||
VTR_ASSERT(true ==
|
||||
valid_signal_threshold(slew_lower_thresholds_[signal_type]));
|
||||
return slew_lower_thresholds_[signal_type];
|
||||
}
|
||||
|
||||
float SimulationSetting::measure_delay_input_threshold(const e_sim_signal_type& signal_type) const {
|
||||
VTR_ASSERT (true == valid_signal_threshold(delay_input_thresholds_[signal_type]));
|
||||
float SimulationSetting::measure_delay_input_threshold(
|
||||
const e_sim_signal_type& signal_type) const {
|
||||
VTR_ASSERT(true ==
|
||||
valid_signal_threshold(delay_input_thresholds_[signal_type]));
|
||||
return delay_input_thresholds_[signal_type];
|
||||
}
|
||||
|
||||
float SimulationSetting::measure_delay_output_threshold(const e_sim_signal_type& signal_type) const {
|
||||
VTR_ASSERT (true == valid_signal_threshold(delay_output_thresholds_[signal_type]));
|
||||
float SimulationSetting::measure_delay_output_threshold(
|
||||
const e_sim_signal_type& signal_type) const {
|
||||
VTR_ASSERT(true ==
|
||||
valid_signal_threshold(delay_output_thresholds_[signal_type]));
|
||||
return delay_output_thresholds_[signal_type];
|
||||
}
|
||||
|
||||
e_sim_accuracy_type SimulationSetting::stimuli_clock_slew_type(const e_sim_signal_type& signal_type) const {
|
||||
e_sim_accuracy_type SimulationSetting::stimuli_clock_slew_type(
|
||||
const e_sim_signal_type& signal_type) const {
|
||||
return clock_slew_types_[signal_type];
|
||||
}
|
||||
|
||||
float SimulationSetting::stimuli_clock_slew(const e_sim_signal_type& signal_type) const {
|
||||
float SimulationSetting::stimuli_clock_slew(
|
||||
const e_sim_signal_type& signal_type) const {
|
||||
return clock_slews_[signal_type];
|
||||
}
|
||||
|
||||
e_sim_accuracy_type SimulationSetting::stimuli_input_slew_type(const e_sim_signal_type& signal_type) const {
|
||||
e_sim_accuracy_type SimulationSetting::stimuli_input_slew_type(
|
||||
const e_sim_signal_type& signal_type) const {
|
||||
return input_slew_types_[signal_type];
|
||||
}
|
||||
|
||||
float SimulationSetting::stimuli_input_slew(const e_sim_signal_type& signal_type) const {
|
||||
float SimulationSetting::stimuli_input_slew(
|
||||
const e_sim_signal_type& signal_type) const {
|
||||
return input_slews_[signal_type];
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Public Mutators
|
||||
***********************************************************************/
|
||||
void SimulationSetting::set_default_operating_clock_frequency(const float& clock_freq) {
|
||||
void SimulationSetting::set_default_operating_clock_frequency(
|
||||
const float& clock_freq) {
|
||||
default_clock_frequencies_.set_x(clock_freq);
|
||||
}
|
||||
|
||||
void SimulationSetting::set_programming_clock_frequency(const float& clock_freq) {
|
||||
void SimulationSetting::set_programming_clock_frequency(
|
||||
const float& clock_freq) {
|
||||
default_clock_frequencies_.set_y(clock_freq);
|
||||
}
|
||||
|
||||
SimulationClockId SimulationSetting::create_clock(const std::string& name) {
|
||||
/* Ensure a unique name for the clock definition */
|
||||
std::map<std::string, SimulationClockId>::iterator it = clock_name2ids_.find(name);
|
||||
std::map<std::string, SimulationClockId>::iterator it =
|
||||
clock_name2ids_.find(name);
|
||||
if (it != clock_name2ids_.end()) {
|
||||
return SimulationClockId::INVALID();
|
||||
}
|
||||
|
@ -218,14 +231,14 @@ void SimulationSetting::set_clock_frequency(const SimulationClockId& clock_id,
|
|||
clock_frequencies_[clock_id] = frequency;
|
||||
}
|
||||
|
||||
void SimulationSetting::set_clock_is_programming(const SimulationClockId& clock_id,
|
||||
const float& is_prog) {
|
||||
void SimulationSetting::set_clock_is_programming(
|
||||
const SimulationClockId& clock_id, const float& is_prog) {
|
||||
VTR_ASSERT(valid_clock_id(clock_id));
|
||||
clock_is_programming_[clock_id] = is_prog;
|
||||
}
|
||||
|
||||
void SimulationSetting::set_clock_is_shift_register(const SimulationClockId& clock_id,
|
||||
const float& is_sr) {
|
||||
void SimulationSetting::set_clock_is_shift_register(
|
||||
const SimulationClockId& clock_id, const float& is_sr) {
|
||||
VTR_ASSERT(valid_clock_id(clock_id));
|
||||
clock_is_shift_register_[clock_id] = is_sr;
|
||||
}
|
||||
|
@ -234,7 +247,8 @@ void SimulationSetting::set_num_clock_cycles(const size_t& num_clk_cycles) {
|
|||
num_clock_cycles_ = num_clk_cycles;
|
||||
}
|
||||
|
||||
void SimulationSetting::set_operating_clock_frequency_slack(const float& op_clk_freq_slack) {
|
||||
void SimulationSetting::set_operating_clock_frequency_slack(
|
||||
const float& op_clk_freq_slack) {
|
||||
operating_clock_frequency_slack_ = op_clk_freq_slack;
|
||||
}
|
||||
|
||||
|
@ -250,7 +264,8 @@ void SimulationSetting::set_capacitance_output(const bool& cap_output) {
|
|||
capacitance_output_ = cap_output;
|
||||
}
|
||||
|
||||
void SimulationSetting::set_simulation_accuracy_type(const e_sim_accuracy_type& type) {
|
||||
void SimulationSetting::set_simulation_accuracy_type(
|
||||
const e_sim_accuracy_type& type) {
|
||||
VTR_ASSERT(NUM_SIM_ACCURACY_TYPES != type);
|
||||
simulation_accuracy_type_ = type;
|
||||
}
|
||||
|
@ -263,57 +278,58 @@ void SimulationSetting::set_fast_simulation(const bool& fast_sim) {
|
|||
fast_simulation_ = fast_sim;
|
||||
}
|
||||
|
||||
void SimulationSetting::set_monte_carlo_simulation_points(const size_t& num_mc_points) {
|
||||
void SimulationSetting::set_monte_carlo_simulation_points(
|
||||
const size_t& num_mc_points) {
|
||||
monte_carlo_simulation_points_ = num_mc_points;
|
||||
}
|
||||
|
||||
void SimulationSetting::set_measure_slew_upper_threshold(const e_sim_signal_type& signal_type,
|
||||
const float& upper_thres) {
|
||||
void SimulationSetting::set_measure_slew_upper_threshold(
|
||||
const e_sim_signal_type& signal_type, const float& upper_thres) {
|
||||
VTR_ASSERT(NUM_SIM_SIGNAL_TYPES != signal_type);
|
||||
VTR_ASSERT (true == valid_signal_threshold(upper_thres));
|
||||
VTR_ASSERT(true == valid_signal_threshold(upper_thres));
|
||||
slew_upper_thresholds_[signal_type] = upper_thres;
|
||||
}
|
||||
|
||||
void SimulationSetting::set_measure_slew_lower_threshold(const e_sim_signal_type& signal_type,
|
||||
const float& lower_thres) {
|
||||
void SimulationSetting::set_measure_slew_lower_threshold(
|
||||
const e_sim_signal_type& signal_type, const float& lower_thres) {
|
||||
VTR_ASSERT(NUM_SIM_SIGNAL_TYPES != signal_type);
|
||||
VTR_ASSERT (true == valid_signal_threshold(lower_thres));
|
||||
VTR_ASSERT(true == valid_signal_threshold(lower_thres));
|
||||
slew_lower_thresholds_[signal_type] = lower_thres;
|
||||
}
|
||||
|
||||
void SimulationSetting::set_measure_delay_input_threshold(const e_sim_signal_type& signal_type,
|
||||
const float& input_thres) {
|
||||
void SimulationSetting::set_measure_delay_input_threshold(
|
||||
const e_sim_signal_type& signal_type, const float& input_thres) {
|
||||
VTR_ASSERT(NUM_SIM_SIGNAL_TYPES != signal_type);
|
||||
VTR_ASSERT (true == valid_signal_threshold(input_thres));
|
||||
VTR_ASSERT(true == valid_signal_threshold(input_thres));
|
||||
delay_input_thresholds_[signal_type] = input_thres;
|
||||
}
|
||||
|
||||
void SimulationSetting::set_measure_delay_output_threshold(const e_sim_signal_type& signal_type,
|
||||
const float& output_thres) {
|
||||
void SimulationSetting::set_measure_delay_output_threshold(
|
||||
const e_sim_signal_type& signal_type, const float& output_thres) {
|
||||
VTR_ASSERT(NUM_SIM_SIGNAL_TYPES != signal_type);
|
||||
VTR_ASSERT (true == valid_signal_threshold(output_thres));
|
||||
VTR_ASSERT(true == valid_signal_threshold(output_thres));
|
||||
delay_output_thresholds_[signal_type] = output_thres;
|
||||
}
|
||||
|
||||
void SimulationSetting::set_stimuli_clock_slew_type(const e_sim_signal_type& signal_type,
|
||||
const e_sim_accuracy_type& slew_type) {
|
||||
void SimulationSetting::set_stimuli_clock_slew_type(
|
||||
const e_sim_signal_type& signal_type, const e_sim_accuracy_type& slew_type) {
|
||||
VTR_ASSERT(NUM_SIM_SIGNAL_TYPES != signal_type);
|
||||
clock_slew_types_[signal_type] = slew_type;
|
||||
}
|
||||
|
||||
void SimulationSetting::set_stimuli_clock_slew(const e_sim_signal_type& signal_type,
|
||||
const float& clock_slew) {
|
||||
void SimulationSetting::set_stimuli_clock_slew(
|
||||
const e_sim_signal_type& signal_type, const float& clock_slew) {
|
||||
clock_slews_[signal_type] = clock_slew;
|
||||
}
|
||||
|
||||
void SimulationSetting::set_stimuli_input_slew_type(const e_sim_signal_type& signal_type,
|
||||
const e_sim_accuracy_type& input_type) {
|
||||
void SimulationSetting::set_stimuli_input_slew_type(
|
||||
const e_sim_signal_type& signal_type, const e_sim_accuracy_type& input_type) {
|
||||
VTR_ASSERT(NUM_SIM_SIGNAL_TYPES != signal_type);
|
||||
input_slew_types_[signal_type] = input_type;
|
||||
}
|
||||
|
||||
void SimulationSetting::set_stimuli_input_slew(const e_sim_signal_type& signal_type,
|
||||
const float& input_slew) {
|
||||
void SimulationSetting::set_stimuli_input_slew(
|
||||
const e_sim_signal_type& signal_type, const float& input_slew) {
|
||||
input_slews_[signal_type] = input_slew;
|
||||
}
|
||||
|
||||
|
@ -324,13 +340,16 @@ bool SimulationSetting::valid_signal_threshold(const float& threshold) const {
|
|||
return (0. < threshold) && (threshold < 1);
|
||||
}
|
||||
|
||||
bool SimulationSetting::valid_clock_id(const SimulationClockId& clock_id) const {
|
||||
return ( size_t(clock_id) < clock_ids_.size() ) && ( clock_id == clock_ids_[clock_id] );
|
||||
bool SimulationSetting::valid_clock_id(
|
||||
const SimulationClockId& clock_id) const {
|
||||
return (size_t(clock_id) < clock_ids_.size()) &&
|
||||
(clock_id == clock_ids_[clock_id]);
|
||||
}
|
||||
|
||||
bool SimulationSetting::constrained_clock(const SimulationClockId& clock_id) const {
|
||||
bool SimulationSetting::constrained_clock(
|
||||
const SimulationClockId& clock_id) const {
|
||||
VTR_ASSERT(valid_clock_id(clock_id));
|
||||
return 0. != clock_frequencies_[clock_id];
|
||||
}
|
||||
|
||||
} /* namespace openfpga ends */
|
||||
} // namespace openfpga
|
||||
|
|
|
@ -3,34 +3,33 @@
|
|||
|
||||
/********************************************************************
|
||||
* This file include the declaration of simulation settings
|
||||
* which are used by OpenFPGA
|
||||
* which are used by OpenFPGA
|
||||
*******************************************************************/
|
||||
#include <string>
|
||||
#include <array>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "vtr_vector.h"
|
||||
#include "vtr_geometry.h"
|
||||
|
||||
#include "openfpga_port.h"
|
||||
|
||||
#include "simulation_setting_fwd.h"
|
||||
#include "openfpga_port.h"
|
||||
#include "simulation_setting_fwd.h"
|
||||
#include "vtr_geometry.h"
|
||||
#include "vtr_vector.h"
|
||||
|
||||
/********************************************************************
|
||||
* Types of signal type in measurement and stimuli
|
||||
*******************************************************************/
|
||||
enum e_sim_signal_type {
|
||||
SIM_SIGNAL_RISE,
|
||||
SIM_SIGNAL_RISE,
|
||||
SIM_SIGNAL_FALL,
|
||||
NUM_SIM_SIGNAL_TYPES
|
||||
};
|
||||
/* Strings correspond to each delay type */
|
||||
constexpr std::array<const char*, NUM_SIM_SIGNAL_TYPES> SIM_SIGNAL_TYPE_STRING = {{"rise", "fall"}};
|
||||
constexpr std::array<const char*, NUM_SIM_SIGNAL_TYPES> SIM_SIGNAL_TYPE_STRING =
|
||||
{{"rise", "fall"}};
|
||||
|
||||
/********************************************************************
|
||||
* Types of simulation accuracy type
|
||||
* 1. Fraction to the operating clock frequency
|
||||
* 2. Absolute value
|
||||
* 2. Absolute value
|
||||
*******************************************************************/
|
||||
enum e_sim_accuracy_type {
|
||||
SIM_ACCURACY_FRAC,
|
||||
|
@ -38,7 +37,8 @@ enum e_sim_accuracy_type {
|
|||
NUM_SIM_ACCURACY_TYPES
|
||||
};
|
||||
/* Strings correspond to each accuracy type */
|
||||
constexpr std::array<const char*, NUM_SIM_ACCURACY_TYPES> SIM_ACCURACY_TYPE_STRING = {{"frac", "abs"}};
|
||||
constexpr std::array<const char*, NUM_SIM_ACCURACY_TYPES>
|
||||
SIM_ACCURACY_TYPE_STRING = {{"frac", "abs"}};
|
||||
|
||||
/* namespace openfpga begins */
|
||||
namespace openfpga {
|
||||
|
@ -54,223 +54,233 @@ namespace openfpga {
|
|||
*
|
||||
*******************************************************************/
|
||||
class SimulationSetting {
|
||||
public: /* Types */
|
||||
typedef vtr::vector<SimulationClockId, SimulationClockId>::const_iterator simulation_clock_iterator;
|
||||
/* Create range */
|
||||
typedef vtr::Range<simulation_clock_iterator> simulation_clock_range;
|
||||
public: /* Constructors */
|
||||
SimulationSetting();
|
||||
public: /* Accessors: aggregates */
|
||||
simulation_clock_range clocks() const;
|
||||
std::vector<SimulationClockId> operating_clocks() const;
|
||||
std::vector<SimulationClockId> programming_clocks() const;
|
||||
std::vector<SimulationClockId> programming_shift_register_clocks() const;
|
||||
public: /* Public Accessors */
|
||||
float default_operating_clock_frequency() const;
|
||||
float programming_clock_frequency() const;
|
||||
size_t num_simulation_clock_cycles() const;
|
||||
std::string clock_name(const SimulationClockId& clock_id) const;
|
||||
BasicPort clock_port(const SimulationClockId& clock_id) const;
|
||||
float clock_frequency(const SimulationClockId& clock_id) const;
|
||||
bool clock_is_programming(const SimulationClockId& clock_id) const;
|
||||
bool clock_is_shift_register(const SimulationClockId& clock_id) const;
|
||||
bool auto_select_num_clock_cycles() const;
|
||||
size_t num_clock_cycles() const;
|
||||
float operating_clock_frequency_slack() const;
|
||||
float simulation_temperature() const;
|
||||
bool verbose_output() const;
|
||||
bool capacitance_output() const;
|
||||
e_sim_accuracy_type simulation_accuracy_type() const;
|
||||
float simulation_accuracy() const;
|
||||
bool fast_simulation() const;
|
||||
bool run_monte_carlo_simulation() const;
|
||||
size_t monte_carlo_simulation_points() const;
|
||||
float measure_slew_upper_threshold(const e_sim_signal_type& signal_type) const;
|
||||
float measure_slew_lower_threshold(const e_sim_signal_type& signal_type) const;
|
||||
float measure_delay_input_threshold(const e_sim_signal_type& signal_type) const;
|
||||
float measure_delay_output_threshold(const e_sim_signal_type& signal_type) const;
|
||||
e_sim_accuracy_type stimuli_clock_slew_type(const e_sim_signal_type& signal_type) const;
|
||||
float stimuli_clock_slew(const e_sim_signal_type& signal_type) const;
|
||||
e_sim_accuracy_type stimuli_input_slew_type(const e_sim_signal_type& signal_type) const;
|
||||
float stimuli_input_slew(const e_sim_signal_type& signal_type) const;
|
||||
public: /* Public Mutators */
|
||||
void set_default_operating_clock_frequency(const float& clock_freq);
|
||||
void set_programming_clock_frequency(const float& clock_freq);
|
||||
/* Add a new simulation clock with
|
||||
* - a given name
|
||||
* - a given port description
|
||||
* - a default zero frequency which can be overwritten by
|
||||
* the operating_clock_frequency()
|
||||
*/
|
||||
SimulationClockId create_clock(const std::string& name);
|
||||
void set_clock_port(const SimulationClockId& clock_id,
|
||||
const BasicPort& port);
|
||||
void set_clock_frequency(const SimulationClockId& clock_id,
|
||||
const float& frequency);
|
||||
void set_clock_is_programming(const SimulationClockId& clock_id,
|
||||
const float& is_prog);
|
||||
void set_clock_is_shift_register(const SimulationClockId& clock_id,
|
||||
const float& is_sr);
|
||||
void set_num_clock_cycles(const size_t& num_clk_cycles);
|
||||
void set_operating_clock_frequency_slack(const float& op_clk_freq_slack);
|
||||
void set_simulation_temperature(const float& sim_temp);
|
||||
void set_verbose_output(const bool& verbose_output);
|
||||
void set_capacitance_output(const bool& cap_output);
|
||||
void set_simulation_accuracy_type(const e_sim_accuracy_type& type);
|
||||
void set_simulation_accuracy(const float& accuracy);
|
||||
void set_fast_simulation(const bool& fast_sim);
|
||||
void set_monte_carlo_simulation_points(const size_t& num_mc_points);
|
||||
void set_measure_slew_upper_threshold(const e_sim_signal_type& signal_type,
|
||||
const float& upper_thres);
|
||||
void set_measure_slew_lower_threshold(const e_sim_signal_type& signal_type,
|
||||
const float& lower_thres);
|
||||
void set_measure_delay_input_threshold(const e_sim_signal_type& signal_type,
|
||||
const float& input_thres);
|
||||
void set_measure_delay_output_threshold(const e_sim_signal_type& signal_type,
|
||||
const float& output_thres);
|
||||
void set_stimuli_clock_slew_type(const e_sim_signal_type& signal_type,
|
||||
const e_sim_accuracy_type& slew_type);
|
||||
void set_stimuli_clock_slew(const e_sim_signal_type& signal_type,
|
||||
const float& clock_slew);
|
||||
void set_stimuli_input_slew_type(const e_sim_signal_type& signal_type,
|
||||
const e_sim_accuracy_type& slew_type);
|
||||
void set_stimuli_input_slew(const e_sim_signal_type& signal_type,
|
||||
const float& input_slew);
|
||||
public: /* Public Validators */
|
||||
bool valid_signal_threshold(const float& threshold) const;
|
||||
bool valid_clock_id(const SimulationClockId& clock_id) const;
|
||||
/** @brief Validate if a given clock is constrained or not */
|
||||
bool constrained_clock(const SimulationClockId& clock_id) const;
|
||||
private: /* Internal data */
|
||||
/* Operating clock frequency: the default clock frequency to be applied to users' implemetation on FPGA
|
||||
* This will be stored in the x() part of vtr::Point
|
||||
* Programming clock frequency: the clock frequency to be applied to configuration protocol of FPGA
|
||||
* This will be stored in the y() part of vtr::Point
|
||||
*/
|
||||
vtr::Point<float> default_clock_frequencies_;
|
||||
public: /* Types */
|
||||
typedef vtr::vector<SimulationClockId, SimulationClockId>::const_iterator
|
||||
simulation_clock_iterator;
|
||||
/* Create range */
|
||||
typedef vtr::Range<simulation_clock_iterator> simulation_clock_range;
|
||||
|
||||
/* Multiple simulation clocks with detailed information
|
||||
* Each clock has
|
||||
* - a unique id
|
||||
* - a unique name
|
||||
* - a unique port definition which is supposed
|
||||
* to match the clock port definition in OpenFPGA documentation
|
||||
* - a frequency which is only applicable to this clock name
|
||||
*/
|
||||
vtr::vector<SimulationClockId, SimulationClockId> clock_ids_;
|
||||
vtr::vector<SimulationClockId, std::string> clock_names_;
|
||||
vtr::vector<SimulationClockId, BasicPort> clock_ports_;
|
||||
vtr::vector<SimulationClockId, float> clock_frequencies_;
|
||||
vtr::vector<SimulationClockId, bool> clock_is_programming_;
|
||||
vtr::vector<SimulationClockId, bool> clock_is_shift_register_;
|
||||
public: /* Constructors */
|
||||
SimulationSetting();
|
||||
|
||||
/* Fast name-to-id lookup */
|
||||
std::map<std::string, SimulationClockId> clock_name2ids_;
|
||||
public: /* Accessors: aggregates */
|
||||
simulation_clock_range clocks() const;
|
||||
std::vector<SimulationClockId> operating_clocks() const;
|
||||
std::vector<SimulationClockId> programming_clocks() const;
|
||||
std::vector<SimulationClockId> programming_shift_register_clocks() const;
|
||||
|
||||
/* Number of clock cycles to be used in simulation
|
||||
* If the value is 0, the clock cycles can be automatically
|
||||
* inferred from the signal activities of users' implementation
|
||||
*/
|
||||
size_t num_clock_cycles_;
|
||||
|
||||
/* Slack or margin to be added to clock frequency
|
||||
* if the operating clock frequency is automatically
|
||||
* detemined by VPR's routing results
|
||||
*/
|
||||
float operating_clock_frequency_slack_;
|
||||
public: /* Public Accessors */
|
||||
float default_operating_clock_frequency() const;
|
||||
float programming_clock_frequency() const;
|
||||
size_t num_simulation_clock_cycles() const;
|
||||
std::string clock_name(const SimulationClockId& clock_id) const;
|
||||
BasicPort clock_port(const SimulationClockId& clock_id) const;
|
||||
float clock_frequency(const SimulationClockId& clock_id) const;
|
||||
bool clock_is_programming(const SimulationClockId& clock_id) const;
|
||||
bool clock_is_shift_register(const SimulationClockId& clock_id) const;
|
||||
bool auto_select_num_clock_cycles() const;
|
||||
size_t num_clock_cycles() const;
|
||||
float operating_clock_frequency_slack() const;
|
||||
float simulation_temperature() const;
|
||||
bool verbose_output() const;
|
||||
bool capacitance_output() const;
|
||||
e_sim_accuracy_type simulation_accuracy_type() const;
|
||||
float simulation_accuracy() const;
|
||||
bool fast_simulation() const;
|
||||
bool run_monte_carlo_simulation() const;
|
||||
size_t monte_carlo_simulation_points() const;
|
||||
float measure_slew_upper_threshold(
|
||||
const e_sim_signal_type& signal_type) const;
|
||||
float measure_slew_lower_threshold(
|
||||
const e_sim_signal_type& signal_type) const;
|
||||
float measure_delay_input_threshold(
|
||||
const e_sim_signal_type& signal_type) const;
|
||||
float measure_delay_output_threshold(
|
||||
const e_sim_signal_type& signal_type) const;
|
||||
e_sim_accuracy_type stimuli_clock_slew_type(
|
||||
const e_sim_signal_type& signal_type) const;
|
||||
float stimuli_clock_slew(const e_sim_signal_type& signal_type) const;
|
||||
e_sim_accuracy_type stimuli_input_slew_type(
|
||||
const e_sim_signal_type& signal_type) const;
|
||||
float stimuli_input_slew(const e_sim_signal_type& signal_type) const;
|
||||
|
||||
/* Operating temperature to be use in simulation */
|
||||
float simulation_temperature_;
|
||||
public: /* Public Mutators */
|
||||
void set_default_operating_clock_frequency(const float& clock_freq);
|
||||
void set_programming_clock_frequency(const float& clock_freq);
|
||||
/* Add a new simulation clock with
|
||||
* - a given name
|
||||
* - a given port description
|
||||
* - a default zero frequency which can be overwritten by
|
||||
* the operating_clock_frequency()
|
||||
*/
|
||||
SimulationClockId create_clock(const std::string& name);
|
||||
void set_clock_port(const SimulationClockId& clock_id, const BasicPort& port);
|
||||
void set_clock_frequency(const SimulationClockId& clock_id,
|
||||
const float& frequency);
|
||||
void set_clock_is_programming(const SimulationClockId& clock_id,
|
||||
const float& is_prog);
|
||||
void set_clock_is_shift_register(const SimulationClockId& clock_id,
|
||||
const float& is_sr);
|
||||
void set_num_clock_cycles(const size_t& num_clk_cycles);
|
||||
void set_operating_clock_frequency_slack(const float& op_clk_freq_slack);
|
||||
void set_simulation_temperature(const float& sim_temp);
|
||||
void set_verbose_output(const bool& verbose_output);
|
||||
void set_capacitance_output(const bool& cap_output);
|
||||
void set_simulation_accuracy_type(const e_sim_accuracy_type& type);
|
||||
void set_simulation_accuracy(const float& accuracy);
|
||||
void set_fast_simulation(const bool& fast_sim);
|
||||
void set_monte_carlo_simulation_points(const size_t& num_mc_points);
|
||||
void set_measure_slew_upper_threshold(const e_sim_signal_type& signal_type,
|
||||
const float& upper_thres);
|
||||
void set_measure_slew_lower_threshold(const e_sim_signal_type& signal_type,
|
||||
const float& lower_thres);
|
||||
void set_measure_delay_input_threshold(const e_sim_signal_type& signal_type,
|
||||
const float& input_thres);
|
||||
void set_measure_delay_output_threshold(const e_sim_signal_type& signal_type,
|
||||
const float& output_thres);
|
||||
void set_stimuli_clock_slew_type(const e_sim_signal_type& signal_type,
|
||||
const e_sim_accuracy_type& slew_type);
|
||||
void set_stimuli_clock_slew(const e_sim_signal_type& signal_type,
|
||||
const float& clock_slew);
|
||||
void set_stimuli_input_slew_type(const e_sim_signal_type& signal_type,
|
||||
const e_sim_accuracy_type& slew_type);
|
||||
void set_stimuli_input_slew(const e_sim_signal_type& signal_type,
|
||||
const float& input_slew);
|
||||
|
||||
/* Options support by simulators
|
||||
* verbose_output: This is an option to turn on verbose output in simulators
|
||||
* Simulation runtime can be slow when this option is on
|
||||
* for large FPGA fabrics!
|
||||
* capacitance_output: Show capacitance of each nodes in the log file
|
||||
* This is an option provided by SPICE simulators
|
||||
* Simulation runtime can be slow when this option is on
|
||||
* for large FPGA fabrics!
|
||||
* accuracy_type: type of accuracy to be used in simulation
|
||||
* See the definition in enumeration e_sim_accuracy_type
|
||||
* Simulation runtime can be slow when a high accuracy is enable
|
||||
* for large FPGA fabrics!
|
||||
* accuracy: the absolute value of accuracy to be used in simulation.
|
||||
* If fractional accuarcy is specified, the value will be determined by
|
||||
* the maximum operating frequency after VPR routing finished
|
||||
* If absolute accuracy is specified, the value will be given by users
|
||||
*/
|
||||
bool verbose_output_;
|
||||
bool capacitance_output_;
|
||||
e_sim_accuracy_type simulation_accuracy_type_;
|
||||
float simulation_accuracy_;
|
||||
public: /* Public Validators */
|
||||
bool valid_signal_threshold(const float& threshold) const;
|
||||
bool valid_clock_id(const SimulationClockId& clock_id) const;
|
||||
/** @brief Validate if a given clock is constrained or not */
|
||||
bool constrained_clock(const SimulationClockId& clock_id) const;
|
||||
|
||||
/* Enable fast simulation
|
||||
* Note: this may impact the accuracy of simulation results
|
||||
*/
|
||||
bool fast_simulation_;
|
||||
private: /* Internal data */
|
||||
/* Operating clock frequency: the default clock frequency to be applied to
|
||||
* users' implemetation on FPGA This will be stored in the x() part of
|
||||
* vtr::Point Programming clock frequency: the clock frequency to be applied
|
||||
* to configuration protocol of FPGA This will be stored in the y() part of
|
||||
* vtr::Point
|
||||
*/
|
||||
vtr::Point<float> default_clock_frequencies_;
|
||||
|
||||
/* Number of simulation points to be used in Monte Carlo simulation
|
||||
* If a zero is given, monte carlo simulation will not be applied
|
||||
* The larger number of simulation points is used, the slower runtime will be
|
||||
*/
|
||||
size_t monte_carlo_simulation_points_;
|
||||
/* Multiple simulation clocks with detailed information
|
||||
* Each clock has
|
||||
* - a unique id
|
||||
* - a unique name
|
||||
* - a unique port definition which is supposed
|
||||
* to match the clock port definition in OpenFPGA documentation
|
||||
* - a frequency which is only applicable to this clock name
|
||||
*/
|
||||
vtr::vector<SimulationClockId, SimulationClockId> clock_ids_;
|
||||
vtr::vector<SimulationClockId, std::string> clock_names_;
|
||||
vtr::vector<SimulationClockId, BasicPort> clock_ports_;
|
||||
vtr::vector<SimulationClockId, float> clock_frequencies_;
|
||||
vtr::vector<SimulationClockId, bool> clock_is_programming_;
|
||||
vtr::vector<SimulationClockId, bool> clock_is_shift_register_;
|
||||
|
||||
/* The thresholds (in percentage) to be used in the measuring signal slews
|
||||
* Thresholds related to rising edge will be stored in the first element
|
||||
* Thresholds related to falling edge will be stored in the second element
|
||||
*/
|
||||
std::array<float, NUM_SIM_SIGNAL_TYPES> slew_upper_thresholds_;
|
||||
std::array<float, NUM_SIM_SIGNAL_TYPES> slew_lower_thresholds_;
|
||||
/* Fast name-to-id lookup */
|
||||
std::map<std::string, SimulationClockId> clock_name2ids_;
|
||||
|
||||
/* The thresholds (in percentage) to be used in the measuring signal delays
|
||||
* Thresholds related to rising edge will be stored in the first element
|
||||
* Thresholds related to falling edge will be stored in the second element
|
||||
*
|
||||
* An example of delay measurement in rising edge
|
||||
* from 50% of input signal to 50% of output signal
|
||||
* (delay_input_threshold=0.5; delay_output_threshold=0.5)
|
||||
*
|
||||
* Input signal
|
||||
*
|
||||
* 50% of full swing of input signal
|
||||
* ^ +--------------------------
|
||||
* |/
|
||||
* +----------------+
|
||||
* / | |
|
||||
* -------+ | |
|
||||
* v |
|
||||
* rise delay |
|
||||
* |
|
||||
* Output signal |
|
||||
* | +--------
|
||||
* |/
|
||||
* +
|
||||
* /|
|
||||
* -------------------------+ |
|
||||
* v
|
||||
* 50% of full swing of output signal
|
||||
*/
|
||||
std::array<float, NUM_SIM_SIGNAL_TYPES> delay_input_thresholds_;
|
||||
std::array<float, NUM_SIM_SIGNAL_TYPES> delay_output_thresholds_;
|
||||
/* Number of clock cycles to be used in simulation
|
||||
* If the value is 0, the clock cycles can be automatically
|
||||
* inferred from the signal activities of users' implementation
|
||||
*/
|
||||
size_t num_clock_cycles_;
|
||||
|
||||
/* Stimulus to be given to each type of port.
|
||||
* We support two types of ports:
|
||||
* 1. clock ports
|
||||
* 2. regular input ports
|
||||
*
|
||||
* Slew time related to rising edge will be stored in the first element
|
||||
* Slew time related to falling edge will be stored in the second element
|
||||
*
|
||||
* accuracy_type: type of accuracy to be used in simulation
|
||||
* Fractional accuracy will be determined by the clock frequency
|
||||
* to be defined by user in the clock_setting
|
||||
*/
|
||||
std::array<e_sim_accuracy_type, NUM_SIM_ACCURACY_TYPES> clock_slew_types_;
|
||||
std::array<float, NUM_SIM_ACCURACY_TYPES> clock_slews_;
|
||||
std::array<e_sim_accuracy_type, NUM_SIM_ACCURACY_TYPES> input_slew_types_;
|
||||
std::array<float, NUM_SIM_ACCURACY_TYPES> input_slews_;
|
||||
/* Slack or margin to be added to clock frequency
|
||||
* if the operating clock frequency is automatically
|
||||
* detemined by VPR's routing results
|
||||
*/
|
||||
float operating_clock_frequency_slack_;
|
||||
|
||||
/* Operating temperature to be use in simulation */
|
||||
float simulation_temperature_;
|
||||
|
||||
/* Options support by simulators
|
||||
* verbose_output: This is an option to turn on verbose output in
|
||||
* simulators Simulation runtime can be slow when this option is on for large
|
||||
* FPGA fabrics! capacitance_output: Show capacitance of each nodes in the log
|
||||
* file This is an option provided by SPICE simulators Simulation runtime can
|
||||
* be slow when this option is on for large FPGA fabrics! accuracy_type: type
|
||||
* of accuracy to be used in simulation See the definition in enumeration
|
||||
* e_sim_accuracy_type Simulation runtime can be slow when a high accuracy is
|
||||
* enable for large FPGA fabrics! accuracy: the absolute value of
|
||||
* accuracy to be used in simulation. If fractional accuarcy is specified, the
|
||||
* value will be determined by the maximum operating frequency after VPR
|
||||
* routing finished If absolute accuracy is specified, the value will be given
|
||||
* by users
|
||||
*/
|
||||
bool verbose_output_;
|
||||
bool capacitance_output_;
|
||||
e_sim_accuracy_type simulation_accuracy_type_;
|
||||
float simulation_accuracy_;
|
||||
|
||||
/* Enable fast simulation
|
||||
* Note: this may impact the accuracy of simulation results
|
||||
*/
|
||||
bool fast_simulation_;
|
||||
|
||||
/* Number of simulation points to be used in Monte Carlo simulation
|
||||
* If a zero is given, monte carlo simulation will not be applied
|
||||
* The larger number of simulation points is used, the slower runtime will be
|
||||
*/
|
||||
size_t monte_carlo_simulation_points_;
|
||||
|
||||
/* The thresholds (in percentage) to be used in the measuring signal slews
|
||||
* Thresholds related to rising edge will be stored in the first element
|
||||
* Thresholds related to falling edge will be stored in the second element
|
||||
*/
|
||||
std::array<float, NUM_SIM_SIGNAL_TYPES> slew_upper_thresholds_;
|
||||
std::array<float, NUM_SIM_SIGNAL_TYPES> slew_lower_thresholds_;
|
||||
|
||||
/* The thresholds (in percentage) to be used in the measuring signal delays
|
||||
* Thresholds related to rising edge will be stored in the first element
|
||||
* Thresholds related to falling edge will be stored in the second element
|
||||
*
|
||||
* An example of delay measurement in rising edge
|
||||
* from 50% of input signal to 50% of output signal
|
||||
* (delay_input_threshold=0.5; delay_output_threshold=0.5)
|
||||
*
|
||||
* Input signal
|
||||
*
|
||||
* 50% of full swing of input signal
|
||||
* ^ +--------------------------
|
||||
* |/
|
||||
* +----------------+
|
||||
* / | |
|
||||
* -------+ | |
|
||||
* v |
|
||||
* rise delay |
|
||||
* |
|
||||
* Output signal |
|
||||
* | +--------
|
||||
* |/
|
||||
* +
|
||||
* /|
|
||||
* -------------------------+ |
|
||||
* v
|
||||
* 50% of full swing of output signal
|
||||
*/
|
||||
std::array<float, NUM_SIM_SIGNAL_TYPES> delay_input_thresholds_;
|
||||
std::array<float, NUM_SIM_SIGNAL_TYPES> delay_output_thresholds_;
|
||||
|
||||
/* Stimulus to be given to each type of port.
|
||||
* We support two types of ports:
|
||||
* 1. clock ports
|
||||
* 2. regular input ports
|
||||
*
|
||||
* Slew time related to rising edge will be stored in the first element
|
||||
* Slew time related to falling edge will be stored in the second element
|
||||
*
|
||||
* accuracy_type: type of accuracy to be used in simulation
|
||||
* Fractional accuracy will be determined by the clock
|
||||
* frequency to be defined by user in the clock_setting
|
||||
*/
|
||||
std::array<e_sim_accuracy_type, NUM_SIM_ACCURACY_TYPES> clock_slew_types_;
|
||||
std::array<float, NUM_SIM_ACCURACY_TYPES> clock_slews_;
|
||||
std::array<e_sim_accuracy_type, NUM_SIM_ACCURACY_TYPES> input_slew_types_;
|
||||
std::array<float, NUM_SIM_ACCURACY_TYPES> input_slews_;
|
||||
};
|
||||
|
||||
} /* namespace openfpga ends */
|
||||
} // namespace openfpga
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/************************************************************************
|
||||
* A header file for SimulationSetting class, including critical data declaration
|
||||
* Please include this file only for using any SimulationSetting data structure
|
||||
* Refer to simulation_setting.h for more details
|
||||
* A header file for SimulationSetting class, including critical data
|
||||
*declaration Please include this file only for using any SimulationSetting data
|
||||
*structure Refer to simulation_setting.h for more details
|
||||
***********************************************************************/
|
||||
|
||||
/************************************************************************
|
||||
* Create strong id for Simulation Clock to avoid illegal type casting
|
||||
* Create strong id for Simulation Clock to avoid illegal type casting
|
||||
***********************************************************************/
|
||||
#ifndef SIMULATION_SETTING_FWD_H
|
||||
#define SIMULATION_SETTING_FWD_H
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#include "vtr_assert.h"
|
||||
|
||||
#include "technology_library.h"
|
||||
|
||||
#include "vtr_assert.h"
|
||||
|
||||
/************************************************************************
|
||||
* Member functions for class TechnologyLibrary
|
||||
***********************************************************************/
|
||||
|
@ -9,9 +9,7 @@
|
|||
/************************************************************************
|
||||
* Constructors
|
||||
***********************************************************************/
|
||||
TechnologyLibrary::TechnologyLibrary() {
|
||||
return;
|
||||
}
|
||||
TechnologyLibrary::TechnologyLibrary() { return; }
|
||||
|
||||
/************************************************************************
|
||||
* Public Accessors : aggregates
|
||||
|
@ -20,12 +18,15 @@ TechnologyLibrary::technology_model_range TechnologyLibrary::models() const {
|
|||
return vtr::make_range(model_ids_.begin(), model_ids_.end());
|
||||
}
|
||||
|
||||
TechnologyLibrary::technology_variation_range TechnologyLibrary::variations() const {
|
||||
TechnologyLibrary::technology_variation_range TechnologyLibrary::variations()
|
||||
const {
|
||||
return vtr::make_range(variation_ids_.begin(), variation_ids_.end());
|
||||
}
|
||||
|
||||
/* Find technology models in the same type (defined by users) and return a list of ids */
|
||||
std::vector<TechnologyModelId> TechnologyLibrary::models_by_type(const enum e_tech_lib_model_type& type) const {
|
||||
/* Find technology models in the same type (defined by users) and return a list
|
||||
* of ids */
|
||||
std::vector<TechnologyModelId> TechnologyLibrary::models_by_type(
|
||||
const enum e_tech_lib_model_type& type) const {
|
||||
std::vector<TechnologyModelId> type_ids;
|
||||
for (auto id : models()) {
|
||||
/* Skip unmatched types */
|
||||
|
@ -42,10 +43,11 @@ std::vector<TechnologyModelId> TechnologyLibrary::models_by_type(const enum e_te
|
|||
* Public Accessors : Basic data query on technology models
|
||||
***********************************************************************/
|
||||
/* Access the name of a technology model */
|
||||
std::string TechnologyLibrary::model_name(const TechnologyModelId& model_id) const {
|
||||
std::string TechnologyLibrary::model_name(
|
||||
const TechnologyModelId& model_id) const {
|
||||
/* validate the model_id */
|
||||
VTR_ASSERT(valid_model_id(model_id));
|
||||
return model_names_[model_id];
|
||||
return model_names_[model_id];
|
||||
}
|
||||
|
||||
/* Access the id of a technology model by name,
|
||||
|
@ -53,216 +55,235 @@ std::string TechnologyLibrary::model_name(const TechnologyModelId& model_id) con
|
|||
* Otherwise, return an invalid id
|
||||
*/
|
||||
TechnologyModelId TechnologyLibrary::model(const std::string& name) const {
|
||||
std::map<std::string, TechnologyModelId>::const_iterator it = model_name2ids_.find(name);
|
||||
std::map<std::string, TechnologyModelId>::const_iterator it =
|
||||
model_name2ids_.find(name);
|
||||
if (it == model_name2ids_.end()) {
|
||||
return TechnologyModelId::INVALID();
|
||||
}
|
||||
|
||||
return model_name2ids_.at(name);
|
||||
return model_name2ids_.at(name);
|
||||
}
|
||||
|
||||
/* Access the type of a technology model */
|
||||
enum e_tech_lib_model_type TechnologyLibrary::model_type(const TechnologyModelId& model_id) const {
|
||||
enum e_tech_lib_model_type TechnologyLibrary::model_type(
|
||||
const TechnologyModelId& model_id) const {
|
||||
/* validate the model_id */
|
||||
VTR_ASSERT(valid_model_id(model_id));
|
||||
return model_types_[model_id];
|
||||
return model_types_[model_id];
|
||||
}
|
||||
|
||||
/* Access the model type of a technology model */
|
||||
enum e_tech_lib_type TechnologyLibrary::model_lib_type(const TechnologyModelId& model_id) const {
|
||||
enum e_tech_lib_type TechnologyLibrary::model_lib_type(
|
||||
const TechnologyModelId& model_id) const {
|
||||
/* validate the model_id */
|
||||
VTR_ASSERT(valid_model_id(model_id));
|
||||
return model_lib_types_[model_id];
|
||||
return model_lib_types_[model_id];
|
||||
}
|
||||
|
||||
/* Access the process corner name of a technology model */
|
||||
std::string TechnologyLibrary::model_corner(const TechnologyModelId& model_id) const {
|
||||
std::string TechnologyLibrary::model_corner(
|
||||
const TechnologyModelId& model_id) const {
|
||||
/* validate the model_id */
|
||||
VTR_ASSERT(valid_model_id(model_id));
|
||||
return model_corners_[model_id];
|
||||
return model_corners_[model_id];
|
||||
}
|
||||
|
||||
/* Access the model reference name of a technology model */
|
||||
std::string TechnologyLibrary::model_ref(const TechnologyModelId& model_id) const {
|
||||
std::string TechnologyLibrary::model_ref(
|
||||
const TechnologyModelId& model_id) const {
|
||||
/* validate the model_id */
|
||||
VTR_ASSERT(valid_model_id(model_id));
|
||||
return model_refs_[model_id];
|
||||
return model_refs_[model_id];
|
||||
}
|
||||
|
||||
/* Access the path of library for a technology model */
|
||||
std::string TechnologyLibrary::model_lib_path(const TechnologyModelId& model_id) const {
|
||||
std::string TechnologyLibrary::model_lib_path(
|
||||
const TechnologyModelId& model_id) const {
|
||||
/* validate the model_id */
|
||||
VTR_ASSERT(valid_model_id(model_id));
|
||||
return model_lib_paths_[model_id];
|
||||
return model_lib_paths_[model_id];
|
||||
}
|
||||
|
||||
/* Access the VDD of a technology model
|
||||
* Note: This is ONLY applicable to transistor model
|
||||
* Note: This is ONLY applicable to transistor model
|
||||
*/
|
||||
float TechnologyLibrary::model_vdd(const TechnologyModelId& model_id) const {
|
||||
/* validate the model_id */
|
||||
VTR_ASSERT(valid_model_id(model_id));
|
||||
/* This is only applicable to transistor model */
|
||||
VTR_ASSERT(TECH_LIB_MODEL_TRANSISTOR == model_type(model_id));
|
||||
return model_vdds_[model_id];
|
||||
return model_vdds_[model_id];
|
||||
}
|
||||
|
||||
/* Access the width ratio between PMOS and NMOS for a technology model
|
||||
* Note: This is ONLY applicable to transistor model
|
||||
* Note: This is ONLY applicable to transistor model
|
||||
*/
|
||||
float TechnologyLibrary::model_pn_ratio(const TechnologyModelId& model_id) const {
|
||||
float TechnologyLibrary::model_pn_ratio(
|
||||
const TechnologyModelId& model_id) const {
|
||||
/* validate the model_id */
|
||||
VTR_ASSERT(valid_model_id(model_id));
|
||||
/* This is only applicable to transistor model */
|
||||
VTR_ASSERT(TECH_LIB_MODEL_TRANSISTOR == model_type(model_id));
|
||||
return model_pn_ratios_[model_id];
|
||||
return model_pn_ratios_[model_id];
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Public Accessors : Basic data query on transistors
|
||||
***********************************************************************/
|
||||
/* Access the model name of a transistor (either PMOS or NMOS) for a technology model
|
||||
* Note: This is ONLY applicable to transistor model
|
||||
/* Access the model name of a transistor (either PMOS or NMOS) for a technology
|
||||
* model Note: This is ONLY applicable to transistor model
|
||||
*/
|
||||
std::string TechnologyLibrary::transistor_model_name(const TechnologyModelId& model_id,
|
||||
const e_tech_lib_transistor_type& transistor_type) const {
|
||||
std::string TechnologyLibrary::transistor_model_name(
|
||||
const TechnologyModelId& model_id,
|
||||
const e_tech_lib_transistor_type& transistor_type) const {
|
||||
/* validate the model_id */
|
||||
VTR_ASSERT(valid_model_id(model_id));
|
||||
/* This is only applicable to transistor model */
|
||||
VTR_ASSERT(TECH_LIB_MODEL_TRANSISTOR == model_type(model_id));
|
||||
return transistor_model_names_[model_id][transistor_type];
|
||||
return transistor_model_names_[model_id][transistor_type];
|
||||
}
|
||||
|
||||
/* Access the channel length of a transistor (either PMOS or NMOS) for a technology model
|
||||
* Note: This is ONLY applicable to transistor model
|
||||
/* Access the channel length of a transistor (either PMOS or NMOS) for a
|
||||
* technology model Note: This is ONLY applicable to transistor model
|
||||
*/
|
||||
float TechnologyLibrary::transistor_model_chan_length(const TechnologyModelId& model_id,
|
||||
const e_tech_lib_transistor_type& transistor_type) const {
|
||||
float TechnologyLibrary::transistor_model_chan_length(
|
||||
const TechnologyModelId& model_id,
|
||||
const e_tech_lib_transistor_type& transistor_type) const {
|
||||
/* validate the model_id */
|
||||
VTR_ASSERT(valid_model_id(model_id));
|
||||
/* This is only applicable to transistor model */
|
||||
VTR_ASSERT(TECH_LIB_MODEL_TRANSISTOR == model_type(model_id));
|
||||
return transistor_model_chan_lengths_[model_id][transistor_type];
|
||||
return transistor_model_chan_lengths_[model_id][transistor_type];
|
||||
}
|
||||
|
||||
/* Access the minimum width of a transistor (either PMOS or NMOS) for a technology model
|
||||
* Note: This is ONLY applicable to transistor model
|
||||
/* Access the minimum width of a transistor (either PMOS or NMOS) for a
|
||||
* technology model Note: This is ONLY applicable to transistor model
|
||||
*/
|
||||
float TechnologyLibrary::transistor_model_min_width(const TechnologyModelId& model_id,
|
||||
const e_tech_lib_transistor_type& transistor_type) const {
|
||||
float TechnologyLibrary::transistor_model_min_width(
|
||||
const TechnologyModelId& model_id,
|
||||
const e_tech_lib_transistor_type& transistor_type) const {
|
||||
/* validate the model_id */
|
||||
VTR_ASSERT(valid_model_id(model_id));
|
||||
/* This is only applicable to transistor model */
|
||||
VTR_ASSERT(TECH_LIB_MODEL_TRANSISTOR == model_type(model_id));
|
||||
return transistor_model_min_widths_[model_id][transistor_type];
|
||||
return transistor_model_min_widths_[model_id][transistor_type];
|
||||
}
|
||||
|
||||
/* Access the maximum width of a transistor (either PMOS or NMOS) for a technology model
|
||||
* Note: This is ONLY applicable to transistor model
|
||||
/* Access the maximum width of a transistor (either PMOS or NMOS) for a
|
||||
* technology model Note: This is ONLY applicable to transistor model
|
||||
*/
|
||||
float TechnologyLibrary::transistor_model_max_width(const TechnologyModelId& model_id,
|
||||
const e_tech_lib_transistor_type& transistor_type) const {
|
||||
float TechnologyLibrary::transistor_model_max_width(
|
||||
const TechnologyModelId& model_id,
|
||||
const e_tech_lib_transistor_type& transistor_type) const {
|
||||
/* validate the model_id */
|
||||
VTR_ASSERT(valid_model_id(model_id));
|
||||
/* This is only applicable to transistor model */
|
||||
VTR_ASSERT(TECH_LIB_MODEL_TRANSISTOR == model_type(model_id));
|
||||
return transistor_model_max_widths_[model_id][transistor_type];
|
||||
return transistor_model_max_widths_[model_id][transistor_type];
|
||||
}
|
||||
|
||||
/* Access the minimum width of a transistor (either PMOS or NMOS) for a technology model
|
||||
* Note: This is ONLY applicable to transistor model
|
||||
/* Access the minimum width of a transistor (either PMOS or NMOS) for a
|
||||
* technology model Note: This is ONLY applicable to transistor model
|
||||
*/
|
||||
TechnologyVariationId TechnologyLibrary::transistor_model_variation(const TechnologyModelId& model_id,
|
||||
const e_tech_lib_transistor_type& transistor_type) const {
|
||||
TechnologyVariationId TechnologyLibrary::transistor_model_variation(
|
||||
const TechnologyModelId& model_id,
|
||||
const e_tech_lib_transistor_type& transistor_type) const {
|
||||
/* validate the model_id */
|
||||
VTR_ASSERT(valid_model_id(model_id));
|
||||
/* This is only applicable to transistor model */
|
||||
VTR_ASSERT(TECH_LIB_MODEL_TRANSISTOR == model_type(model_id));
|
||||
return transistor_model_variation_ids_[model_id][transistor_type];
|
||||
return transistor_model_variation_ids_[model_id][transistor_type];
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Public Accessors : Basic data query on RRAM models
|
||||
***********************************************************************/
|
||||
/* Access the Low Resistence of a RRAM for a technology model
|
||||
* Note: This is ONLY applicable to RRAM model
|
||||
* Note: This is ONLY applicable to RRAM model
|
||||
*/
|
||||
float TechnologyLibrary::rram_rlrs(const TechnologyModelId& model_id) const {
|
||||
/* validate the model_id */
|
||||
VTR_ASSERT(valid_model_id(model_id));
|
||||
/* This is only applicable to transistor model */
|
||||
VTR_ASSERT(TECH_LIB_MODEL_RRAM == model_type(model_id));
|
||||
return rram_resistances_[model_id].x();
|
||||
return rram_resistances_[model_id].x();
|
||||
}
|
||||
|
||||
/* Access the High Resistence of a RRAM for a technology model
|
||||
* Note: This is ONLY applicable to RRAM model
|
||||
* Note: This is ONLY applicable to RRAM model
|
||||
*/
|
||||
float TechnologyLibrary::rram_rhrs(const TechnologyModelId& model_id) const {
|
||||
/* validate the model_id */
|
||||
VTR_ASSERT(valid_model_id(model_id));
|
||||
/* This is only applicable to transistor model */
|
||||
VTR_ASSERT(TECH_LIB_MODEL_RRAM == model_type(model_id));
|
||||
return rram_resistances_[model_id].y();
|
||||
return rram_resistances_[model_id].y();
|
||||
}
|
||||
|
||||
/* Access the Variation id of a RRAM for a technology model
|
||||
* Note: This is ONLY applicable to RRAM model
|
||||
* Note: This is ONLY applicable to RRAM model
|
||||
*/
|
||||
TechnologyVariationId TechnologyLibrary::rram_variation(const TechnologyModelId& model_id) const {
|
||||
TechnologyVariationId TechnologyLibrary::rram_variation(
|
||||
const TechnologyModelId& model_id) const {
|
||||
/* validate the model_id */
|
||||
VTR_ASSERT(valid_model_id(model_id));
|
||||
/* This is only applicable to RRAM model */
|
||||
VTR_ASSERT(TECH_LIB_MODEL_RRAM == model_type(model_id));
|
||||
return rram_variation_ids_[model_id];
|
||||
return rram_variation_ids_[model_id];
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Public Accessors : Basic data query on technology variations
|
||||
***********************************************************************/
|
||||
/* Access the name of a technology variation */
|
||||
std::string TechnologyLibrary::variation_name(const TechnologyVariationId& variation_id) const {
|
||||
std::string TechnologyLibrary::variation_name(
|
||||
const TechnologyVariationId& variation_id) const {
|
||||
/* validate the variation_id */
|
||||
VTR_ASSERT(valid_variation_id(variation_id));
|
||||
return variation_names_[variation_id];
|
||||
return variation_names_[variation_id];
|
||||
}
|
||||
|
||||
/* Access the id of a technology variation by name
|
||||
* If the name is valid, we return a valid id
|
||||
* Otherwise, return an invalid id
|
||||
*/
|
||||
TechnologyVariationId TechnologyLibrary::variation(const std::string& name) const {
|
||||
std::map<std::string, TechnologyVariationId>::const_iterator it = variation_name2ids_.find(name);
|
||||
TechnologyVariationId TechnologyLibrary::variation(
|
||||
const std::string& name) const {
|
||||
std::map<std::string, TechnologyVariationId>::const_iterator it =
|
||||
variation_name2ids_.find(name);
|
||||
if (it != variation_name2ids_.end()) {
|
||||
return TechnologyVariationId::INVALID();
|
||||
}
|
||||
|
||||
return variation_name2ids_.at(name);
|
||||
return variation_name2ids_.at(name);
|
||||
}
|
||||
|
||||
/* Access the abs value of a technology variation */
|
||||
float TechnologyLibrary::variation_abs_value(const TechnologyVariationId& variation_id) const {
|
||||
float TechnologyLibrary::variation_abs_value(
|
||||
const TechnologyVariationId& variation_id) const {
|
||||
/* validate the variation_id */
|
||||
VTR_ASSERT(valid_variation_id(variation_id));
|
||||
return variation_abs_values_[variation_id];
|
||||
return variation_abs_values_[variation_id];
|
||||
}
|
||||
|
||||
/* Access the abs value of a technology variation */
|
||||
size_t TechnologyLibrary::variation_num_sigma(const TechnologyVariationId& variation_id) const {
|
||||
size_t TechnologyLibrary::variation_num_sigma(
|
||||
const TechnologyVariationId& variation_id) const {
|
||||
/* validate the variation_id */
|
||||
VTR_ASSERT(valid_variation_id(variation_id));
|
||||
return variation_num_sigmas_[variation_id];
|
||||
return variation_num_sigmas_[variation_id];
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Public Mutators: model-related
|
||||
***********************************************************************/
|
||||
/* Add a new model to the library, return an id
|
||||
* This function will check if the name has already been used inside the data structure.
|
||||
* If used, it will return an invalid id
|
||||
/* Add a new model to the library, return an id
|
||||
* This function will check if the name has already been used inside the data
|
||||
* structure. If used, it will return an invalid id
|
||||
*/
|
||||
TechnologyModelId TechnologyLibrary::add_model(const std::string& name) {
|
||||
std::map<std::string, TechnologyModelId>::iterator it = model_name2ids_.find(name);
|
||||
std::map<std::string, TechnologyModelId>::iterator it =
|
||||
model_name2ids_.find(name);
|
||||
if (it != model_name2ids_.end()) {
|
||||
return TechnologyModelId::INVALID();
|
||||
}
|
||||
|
@ -284,7 +305,9 @@ TechnologyModelId TechnologyLibrary::add_model(const std::string& name) {
|
|||
transistor_model_min_widths_.emplace_back();
|
||||
transistor_model_max_widths_.emplace_back();
|
||||
transistor_model_variation_names_.emplace_back();
|
||||
transistor_model_variation_ids_.push_back(std::array<TechnologyVariationId, 2>{TechnologyVariationId::INVALID(), TechnologyVariationId::INVALID()});
|
||||
transistor_model_variation_ids_.push_back(
|
||||
std::array<TechnologyVariationId, 2>{TechnologyVariationId::INVALID(),
|
||||
TechnologyVariationId::INVALID()});
|
||||
|
||||
rram_resistances_.emplace_back();
|
||||
rram_variation_names_.emplace_back();
|
||||
|
@ -292,13 +315,13 @@ TechnologyModelId TechnologyLibrary::add_model(const std::string& name) {
|
|||
|
||||
/* Register in the name-to-id map */
|
||||
model_name2ids_[name] = model;
|
||||
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
/* Set the model type of a model in the library */
|
||||
void TechnologyLibrary::set_model_type(const TechnologyModelId& model_id,
|
||||
const e_tech_lib_model_type& type) {
|
||||
void TechnologyLibrary::set_model_type(const TechnologyModelId& model_id,
|
||||
const e_tech_lib_model_type& type) {
|
||||
/* validate the model_id */
|
||||
VTR_ASSERT(valid_model_id(model_id));
|
||||
model_types_[model_id] = type;
|
||||
|
@ -306,8 +329,8 @@ void TechnologyLibrary::set_model_type(const TechnologyModelId& model_id,
|
|||
}
|
||||
|
||||
/* Set the model type of a device model in the library */
|
||||
void TechnologyLibrary::set_model_lib_type(const TechnologyModelId& model_id,
|
||||
const e_tech_lib_type& model_lib_type) {
|
||||
void TechnologyLibrary::set_model_lib_type(
|
||||
const TechnologyModelId& model_id, const e_tech_lib_type& model_lib_type) {
|
||||
/* validate the model_id */
|
||||
VTR_ASSERT(valid_model_id(model_id));
|
||||
model_lib_types_[model_id] = model_lib_type;
|
||||
|
@ -315,8 +338,8 @@ void TechnologyLibrary::set_model_lib_type(const TechnologyModelId& model_id,
|
|||
}
|
||||
|
||||
/* Set the process corner of a model in the library */
|
||||
void TechnologyLibrary::set_model_corner(const TechnologyModelId& model_id,
|
||||
const std::string& corner) {
|
||||
void TechnologyLibrary::set_model_corner(const TechnologyModelId& model_id,
|
||||
const std::string& corner) {
|
||||
/* validate the model_id */
|
||||
VTR_ASSERT(valid_model_id(model_id));
|
||||
model_corners_[model_id] = corner;
|
||||
|
@ -324,7 +347,7 @@ void TechnologyLibrary::set_model_corner(const TechnologyModelId& model_id,
|
|||
}
|
||||
|
||||
/* Set the string used to model reference of a model in the library */
|
||||
void TechnologyLibrary::set_model_ref(const TechnologyModelId& model_id,
|
||||
void TechnologyLibrary::set_model_ref(const TechnologyModelId& model_id,
|
||||
const std::string& model_ref) {
|
||||
/* validate the model_id */
|
||||
VTR_ASSERT(valid_model_id(model_id));
|
||||
|
@ -333,7 +356,7 @@ void TechnologyLibrary::set_model_ref(const TechnologyModelId& model_id,
|
|||
}
|
||||
|
||||
/* Set the library file path of a model in the library */
|
||||
void TechnologyLibrary::set_model_lib_path(const TechnologyModelId& model_id,
|
||||
void TechnologyLibrary::set_model_lib_path(const TechnologyModelId& model_id,
|
||||
const std::string& lib_path) {
|
||||
/* validate the model_id */
|
||||
VTR_ASSERT(valid_model_id(model_id));
|
||||
|
@ -341,11 +364,11 @@ void TechnologyLibrary::set_model_lib_path(const TechnologyModelId& model_id,
|
|||
return;
|
||||
}
|
||||
|
||||
/* Set the operating voltage of a model in the library
|
||||
/* Set the operating voltage of a model in the library
|
||||
* This is ONLY applicable to transistors
|
||||
*/
|
||||
void TechnologyLibrary::set_model_vdd(const TechnologyModelId& model_id,
|
||||
const float& vdd) {
|
||||
void TechnologyLibrary::set_model_vdd(const TechnologyModelId& model_id,
|
||||
const float& vdd) {
|
||||
/* validate the model_id */
|
||||
VTR_ASSERT(valid_model_id(model_id));
|
||||
VTR_ASSERT(TECH_LIB_MODEL_TRANSISTOR == model_type(model_id));
|
||||
|
@ -353,11 +376,11 @@ void TechnologyLibrary::set_model_vdd(const TechnologyModelId& model_id,
|
|||
return;
|
||||
}
|
||||
|
||||
/* Set the width ratio between PMOS and NMOS of a model in the library
|
||||
/* Set the width ratio between PMOS and NMOS of a model in the library
|
||||
* This is ONLY applicable to transistors
|
||||
*/
|
||||
void TechnologyLibrary::set_model_pn_ratio(const TechnologyModelId& model_id,
|
||||
const float& pn_ratio) {
|
||||
void TechnologyLibrary::set_model_pn_ratio(const TechnologyModelId& model_id,
|
||||
const float& pn_ratio) {
|
||||
/* validate the model_id */
|
||||
VTR_ASSERT(valid_model_id(model_id));
|
||||
VTR_ASSERT(TECH_LIB_MODEL_TRANSISTOR == model_type(model_id));
|
||||
|
@ -368,12 +391,13 @@ void TechnologyLibrary::set_model_pn_ratio(const TechnologyModelId& model_id,
|
|||
/************************************************************************
|
||||
* Public Mutators: transistor-related
|
||||
***********************************************************************/
|
||||
/* Set the model name for either PMOS or NMOS of a model in the library
|
||||
/* Set the model name for either PMOS or NMOS of a model in the library
|
||||
* This is ONLY applicable to transistors
|
||||
*/
|
||||
void TechnologyLibrary::set_transistor_model_name(const TechnologyModelId& model_id,
|
||||
const e_tech_lib_transistor_type& transistor_type,
|
||||
const std::string& model_name) {
|
||||
void TechnologyLibrary::set_transistor_model_name(
|
||||
const TechnologyModelId& model_id,
|
||||
const e_tech_lib_transistor_type& transistor_type,
|
||||
const std::string& model_name) {
|
||||
/* validate the model_id */
|
||||
VTR_ASSERT(valid_model_id(model_id));
|
||||
VTR_ASSERT(TECH_LIB_MODEL_TRANSISTOR == model_type(model_id));
|
||||
|
@ -381,12 +405,12 @@ void TechnologyLibrary::set_transistor_model_name(const TechnologyModelId& model
|
|||
return;
|
||||
}
|
||||
|
||||
/* Set the channel length for either PMOS or NMOS of a model in the library
|
||||
/* Set the channel length for either PMOS or NMOS of a model in the library
|
||||
* This is ONLY applicable to transistors
|
||||
*/
|
||||
void TechnologyLibrary::set_transistor_model_chan_length(const TechnologyModelId& model_id,
|
||||
const e_tech_lib_transistor_type& transistor_type,
|
||||
const float& chan_length) {
|
||||
void TechnologyLibrary::set_transistor_model_chan_length(
|
||||
const TechnologyModelId& model_id,
|
||||
const e_tech_lib_transistor_type& transistor_type, const float& chan_length) {
|
||||
/* validate the model_id */
|
||||
VTR_ASSERT(valid_model_id(model_id));
|
||||
VTR_ASSERT(TECH_LIB_MODEL_TRANSISTOR == model_type(model_id));
|
||||
|
@ -394,12 +418,12 @@ void TechnologyLibrary::set_transistor_model_chan_length(const TechnologyModelId
|
|||
return;
|
||||
}
|
||||
|
||||
/* Set the minimum width for either PMOS or NMOS of a model in the library
|
||||
/* Set the minimum width for either PMOS or NMOS of a model in the library
|
||||
* This is ONLY applicable to transistors
|
||||
*/
|
||||
void TechnologyLibrary::set_transistor_model_min_width(const TechnologyModelId& model_id,
|
||||
const e_tech_lib_transistor_type& transistor_type,
|
||||
const float& min_width) {
|
||||
void TechnologyLibrary::set_transistor_model_min_width(
|
||||
const TechnologyModelId& model_id,
|
||||
const e_tech_lib_transistor_type& transistor_type, const float& min_width) {
|
||||
/* validate the model_id */
|
||||
VTR_ASSERT(valid_model_id(model_id));
|
||||
VTR_ASSERT(TECH_LIB_MODEL_TRANSISTOR == model_type(model_id));
|
||||
|
@ -407,12 +431,12 @@ void TechnologyLibrary::set_transistor_model_min_width(const TechnologyModelId&
|
|||
return;
|
||||
}
|
||||
|
||||
/* Set the maximum width for either PMOS or NMOS of a model in the library
|
||||
/* Set the maximum width for either PMOS or NMOS of a model in the library
|
||||
* This is ONLY applicable to transistors
|
||||
*/
|
||||
void TechnologyLibrary::set_transistor_model_max_width(const TechnologyModelId& model_id,
|
||||
const e_tech_lib_transistor_type& transistor_type,
|
||||
const float& max_width) {
|
||||
void TechnologyLibrary::set_transistor_model_max_width(
|
||||
const TechnologyModelId& model_id,
|
||||
const e_tech_lib_transistor_type& transistor_type, const float& max_width) {
|
||||
/* validate the model_id */
|
||||
VTR_ASSERT(valid_model_id(model_id));
|
||||
VTR_ASSERT(TECH_LIB_MODEL_TRANSISTOR == model_type(model_id));
|
||||
|
@ -420,12 +444,13 @@ void TechnologyLibrary::set_transistor_model_max_width(const TechnologyModelId&
|
|||
return;
|
||||
}
|
||||
|
||||
/* Set the variation name for either PMOS or NMOS of a model in the library
|
||||
/* Set the variation name for either PMOS or NMOS of a model in the library
|
||||
* This is ONLY applicable to transistors
|
||||
*/
|
||||
void TechnologyLibrary::set_transistor_model_variation_name(const TechnologyModelId& model_id,
|
||||
const e_tech_lib_transistor_type& transistor_type,
|
||||
const std::string& variation_name) {
|
||||
void TechnologyLibrary::set_transistor_model_variation_name(
|
||||
const TechnologyModelId& model_id,
|
||||
const e_tech_lib_transistor_type& transistor_type,
|
||||
const std::string& variation_name) {
|
||||
/* validate the model_id */
|
||||
VTR_ASSERT(valid_model_id(model_id));
|
||||
VTR_ASSERT(TECH_LIB_MODEL_TRANSISTOR == model_type(model_id));
|
||||
|
@ -436,10 +461,10 @@ void TechnologyLibrary::set_transistor_model_variation_name(const TechnologyMode
|
|||
/************************************************************************
|
||||
* Public Mutators: RRAM-related
|
||||
***********************************************************************/
|
||||
/* Set the Low Resistance State (LRS) resistance for a RRAM model in the library
|
||||
/* Set the Low Resistance State (LRS) resistance for a RRAM model in the library
|
||||
* This is ONLY applicable to RRAM models
|
||||
*/
|
||||
void TechnologyLibrary::set_rram_rlrs(const TechnologyModelId& model_id,
|
||||
void TechnologyLibrary::set_rram_rlrs(const TechnologyModelId& model_id,
|
||||
const float& rlrs) {
|
||||
/* validate the model_id */
|
||||
VTR_ASSERT(valid_model_id(model_id));
|
||||
|
@ -448,10 +473,10 @@ void TechnologyLibrary::set_rram_rlrs(const TechnologyModelId& model_id,
|
|||
return;
|
||||
}
|
||||
|
||||
/* Set the High Resistance State (HRS) resistance for a RRAM model in the library
|
||||
* This is ONLY applicable to RRAM models
|
||||
/* Set the High Resistance State (HRS) resistance for a RRAM model in the
|
||||
* library This is ONLY applicable to RRAM models
|
||||
*/
|
||||
void TechnologyLibrary::set_rram_rhrs(const TechnologyModelId& model_id,
|
||||
void TechnologyLibrary::set_rram_rhrs(const TechnologyModelId& model_id,
|
||||
const float& rhrs) {
|
||||
/* validate the model_id */
|
||||
VTR_ASSERT(valid_model_id(model_id));
|
||||
|
@ -460,11 +485,11 @@ void TechnologyLibrary::set_rram_rhrs(const TechnologyModelId& model_id,
|
|||
return;
|
||||
}
|
||||
|
||||
/* Set the variation name for a RRAM model in the library
|
||||
/* Set the variation name for a RRAM model in the library
|
||||
* This is ONLY applicable to RRAM models
|
||||
*/
|
||||
void TechnologyLibrary::set_rram_variation_name(const TechnologyModelId& model_id,
|
||||
const std::string& variation_name) {
|
||||
void TechnologyLibrary::set_rram_variation_name(
|
||||
const TechnologyModelId& model_id, const std::string& variation_name) {
|
||||
/* validate the model_id */
|
||||
VTR_ASSERT(valid_model_id(model_id));
|
||||
VTR_ASSERT(TECH_LIB_MODEL_RRAM == model_type(model_id));
|
||||
|
@ -475,18 +500,21 @@ void TechnologyLibrary::set_rram_variation_name(const TechnologyModelId& model_i
|
|||
/************************************************************************
|
||||
* Public Mutators: variation-related
|
||||
***********************************************************************/
|
||||
/* Add a new variation to the library, return an id
|
||||
* This function will check if the name has already been used inside the data structure.
|
||||
* If used, it will return an invalid id
|
||||
/* Add a new variation to the library, return an id
|
||||
* This function will check if the name has already been used inside the data
|
||||
* structure. If used, it will return an invalid id
|
||||
*/
|
||||
TechnologyVariationId TechnologyLibrary::add_variation(const std::string& name) {
|
||||
std::map<std::string, TechnologyVariationId>::iterator it = variation_name2ids_.find(name);
|
||||
TechnologyVariationId TechnologyLibrary::add_variation(
|
||||
const std::string& name) {
|
||||
std::map<std::string, TechnologyVariationId>::iterator it =
|
||||
variation_name2ids_.find(name);
|
||||
if (it != variation_name2ids_.end()) {
|
||||
return TechnologyVariationId::INVALID();
|
||||
}
|
||||
|
||||
/* This is a legal name. we can create a new id */
|
||||
TechnologyVariationId variation = TechnologyVariationId(variation_ids_.size());
|
||||
TechnologyVariationId variation =
|
||||
TechnologyVariationId(variation_ids_.size());
|
||||
variation_ids_.push_back(variation);
|
||||
variation_names_.push_back(name);
|
||||
variation_abs_values_.push_back(0.);
|
||||
|
@ -494,12 +522,13 @@ TechnologyVariationId TechnologyLibrary::add_variation(const std::string& name)
|
|||
|
||||
/* Register in the name-to-id map */
|
||||
variation_name2ids_[name] = variation;
|
||||
|
||||
|
||||
return variation;
|
||||
}
|
||||
|
||||
/* Set the absolute value of a variation */
|
||||
void TechnologyLibrary::set_variation_abs_value(const TechnologyVariationId& variation_id, const float& abs_value) {
|
||||
void TechnologyLibrary::set_variation_abs_value(
|
||||
const TechnologyVariationId& variation_id, const float& abs_value) {
|
||||
/* validate the variation_id */
|
||||
VTR_ASSERT(valid_variation_id(variation_id));
|
||||
variation_abs_values_[variation_id] = abs_value;
|
||||
|
@ -507,7 +536,8 @@ void TechnologyLibrary::set_variation_abs_value(const TechnologyVariationId& var
|
|||
}
|
||||
|
||||
/* Set the number of sigma of a variation */
|
||||
void TechnologyLibrary::set_variation_num_sigma(const TechnologyVariationId& variation_id, const size_t& num_sigma) {
|
||||
void TechnologyLibrary::set_variation_num_sigma(
|
||||
const TechnologyVariationId& variation_id, const size_t& num_sigma) {
|
||||
/* validate the variation_id */
|
||||
VTR_ASSERT(valid_variation_id(variation_id));
|
||||
variation_num_sigmas_[variation_id] = num_sigma;
|
||||
|
@ -522,23 +552,29 @@ void TechnologyLibrary::set_variation_num_sigma(const TechnologyVariationId& var
|
|||
*/
|
||||
void TechnologyLibrary::link_models_to_variations() {
|
||||
for (const TechnologyModelId& model : models()) {
|
||||
/* For transistors, find the variation name for each model and build a link */
|
||||
/* For transistors, find the variation name for each model and build a link
|
||||
*/
|
||||
if (TECH_LIB_MODEL_TRANSISTOR == model_type(model)) {
|
||||
/* PMOS transistor, if a variation name is specified, we try to build a link
|
||||
* Otherwise, we assign any invalid id */
|
||||
const std::string& pmos_var_name = transistor_model_variation_names_[model][TECH_LIB_TRANSISTOR_PMOS];
|
||||
transistor_model_variation_ids_[model][TECH_LIB_TRANSISTOR_PMOS] = variation(pmos_var_name);
|
||||
/* PMOS transistor, if a variation name is specified, we try to build a
|
||||
* link Otherwise, we assign any invalid id */
|
||||
const std::string& pmos_var_name =
|
||||
transistor_model_variation_names_[model][TECH_LIB_TRANSISTOR_PMOS];
|
||||
transistor_model_variation_ids_[model][TECH_LIB_TRANSISTOR_PMOS] =
|
||||
variation(pmos_var_name);
|
||||
|
||||
/* NMOS transistor, if a variation name is specified, we try to build a link
|
||||
* Otherwise, we assign any invalid id
|
||||
/* NMOS transistor, if a variation name is specified, we try to build a
|
||||
* link Otherwise, we assign any invalid id
|
||||
*/
|
||||
const std::string& nmos_var_name = transistor_model_variation_names_[model][TECH_LIB_TRANSISTOR_NMOS];
|
||||
transistor_model_variation_ids_[model][TECH_LIB_TRANSISTOR_NMOS] = variation(nmos_var_name);
|
||||
const std::string& nmos_var_name =
|
||||
transistor_model_variation_names_[model][TECH_LIB_TRANSISTOR_NMOS];
|
||||
transistor_model_variation_ids_[model][TECH_LIB_TRANSISTOR_NMOS] =
|
||||
variation(nmos_var_name);
|
||||
/* Finish for transistors, go to the next */
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Reach here it means an RRAM model, we find the variation name and try to build a link */
|
||||
/* Reach here it means an RRAM model, we find the variation name and try to
|
||||
* build a link */
|
||||
VTR_ASSERT(TECH_LIB_MODEL_RRAM == model_type(model));
|
||||
const std::string& rram_var_name = rram_variation_names_[model];
|
||||
rram_variation_ids_[model] = variation(rram_var_name);
|
||||
|
@ -547,13 +583,17 @@ void TechnologyLibrary::link_models_to_variations() {
|
|||
}
|
||||
|
||||
/************************************************************************
|
||||
* Internal invalidators/validators
|
||||
* Internal invalidators/validators
|
||||
***********************************************************************/
|
||||
/* Validators */
|
||||
bool TechnologyLibrary::valid_model_id(const TechnologyModelId& model_id) const {
|
||||
return ( size_t(model_id) < model_ids_.size() ) && ( model_id == model_ids_[model_id] );
|
||||
bool TechnologyLibrary::valid_model_id(
|
||||
const TechnologyModelId& model_id) const {
|
||||
return (size_t(model_id) < model_ids_.size()) &&
|
||||
(model_id == model_ids_[model_id]);
|
||||
}
|
||||
|
||||
bool TechnologyLibrary::valid_variation_id(const TechnologyVariationId& variation_id) const {
|
||||
return ( size_t(variation_id) < variation_ids_.size() ) && ( variation_id == variation_ids_[variation_id] );
|
||||
bool TechnologyLibrary::valid_variation_id(
|
||||
const TechnologyVariationId& variation_id) const {
|
||||
return (size_t(variation_id) < variation_ids_.size()) &&
|
||||
(variation_id == variation_ids_[variation_id]);
|
||||
}
|
||||
|
|
|
@ -4,24 +4,23 @@
|
|||
/********************************************************************
|
||||
* This file include the declaration of technology library
|
||||
*******************************************************************/
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <array>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
/* Headers from vtrutil library */
|
||||
#include "vtr_vector.h"
|
||||
#include "vtr_geometry.h"
|
||||
|
||||
#include "technology_library_fwd.h"
|
||||
#include "vtr_geometry.h"
|
||||
#include "vtr_vector.h"
|
||||
|
||||
/********************************************************************
|
||||
* Types for technology library attributes
|
||||
* Industrial library: the .lib file which define technology
|
||||
* Industrial library: the .lib file which define technology
|
||||
* This is ubiquitous in commercial vendors
|
||||
* For industry library, we allow users to define
|
||||
* process corners.
|
||||
* Academia library: the .pm file which define technology
|
||||
* This is mainly used in PTM-like technology library
|
||||
* Academia library: the .pm file which define technology
|
||||
* This is mainly used in PTM-like technology library
|
||||
* PTM is the Predictive Technology Model provided by the Arizona
|
||||
* State University (ASU). Available at ptm.asu.edu
|
||||
*******************************************************************/
|
||||
|
@ -31,33 +30,36 @@ enum e_tech_lib_type {
|
|||
NUM_TECH_LIB_TYPES
|
||||
};
|
||||
/* Strings correspond to each technology library type */
|
||||
constexpr std::array<const char*, NUM_TECH_LIB_TYPES> TECH_LIB_TYPE_STRING = {{"industry", "academia"}};
|
||||
constexpr std::array<const char*, NUM_TECH_LIB_TYPES> TECH_LIB_TYPE_STRING = {
|
||||
{"industry", "academia"}};
|
||||
|
||||
/********************************************************************
|
||||
* Types of model which may be defined in a technology library
|
||||
* 1. transistor
|
||||
* 1. transistor
|
||||
* 2. RRAM
|
||||
*******************************************************************/
|
||||
enum e_tech_lib_model_type {
|
||||
TECH_LIB_MODEL_TRANSISTOR,
|
||||
TECH_LIB_MODEL_RRAM,
|
||||
TECH_LIB_MODEL_TRANSISTOR,
|
||||
TECH_LIB_MODEL_RRAM,
|
||||
NUM_TECH_LIB_MODEL_TYPES
|
||||
};
|
||||
/* Strings correspond to transistor type */
|
||||
constexpr std::array<const char*, NUM_TECH_LIB_MODEL_TYPES> TECH_LIB_MODEL_TYPE_STRING = {{"transistor", "rram"}};
|
||||
constexpr std::array<const char*, NUM_TECH_LIB_MODEL_TYPES>
|
||||
TECH_LIB_MODEL_TYPE_STRING = {{"transistor", "rram"}};
|
||||
|
||||
/********************************************************************
|
||||
* Types of transistors which may be defined in a technology library
|
||||
* 1. NMOS transistor
|
||||
* 2. PMOS transistor
|
||||
* 1. NMOS transistor
|
||||
* 2. PMOS transistor
|
||||
*******************************************************************/
|
||||
enum e_tech_lib_transistor_type {
|
||||
TECH_LIB_TRANSISTOR_PMOS,
|
||||
TECH_LIB_TRANSISTOR_NMOS,
|
||||
TECH_LIB_TRANSISTOR_PMOS,
|
||||
TECH_LIB_TRANSISTOR_NMOS,
|
||||
NUM_TECH_LIB_TRANSISTOR_TYPES
|
||||
};
|
||||
/* Strings correspond to transistor type */
|
||||
constexpr std::array<const char*, NUM_TECH_LIB_TRANSISTOR_TYPES> TECH_LIB_TRANSISTOR_TYPE_STRING = {{"pmos", "nmos"}};
|
||||
constexpr std::array<const char*, NUM_TECH_LIB_TRANSISTOR_TYPES>
|
||||
TECH_LIB_TRANSISTOR_TYPE_STRING = {{"pmos", "nmos"}};
|
||||
|
||||
/********************************************************************
|
||||
* A data structure to describe technology library
|
||||
|
@ -72,214 +74,247 @@ constexpr std::array<const char*, NUM_TECH_LIB_TRANSISTOR_TYPES> TECH_LIB_TRANSI
|
|||
*
|
||||
*******************************************************************/
|
||||
class TechnologyLibrary {
|
||||
public: /* Types */
|
||||
typedef vtr::vector<TechnologyModelId, TechnologyModelId>::const_iterator technology_model_iterator;
|
||||
typedef vtr::vector<TechnologyVariationId, TechnologyVariationId>::const_iterator technology_variation_iterator;
|
||||
/* Create range */
|
||||
typedef vtr::Range<technology_model_iterator> technology_model_range;
|
||||
typedef vtr::Range<technology_variation_iterator> technology_variation_range;
|
||||
public: /* Constructors */
|
||||
TechnologyLibrary();
|
||||
public: /* Accessors: aggregates */
|
||||
technology_model_range models() const;
|
||||
technology_variation_range variations() const;
|
||||
std::vector<TechnologyModelId> models_by_type(const enum e_tech_lib_model_type& type) const;
|
||||
public: /* Public Accessors: Basic data query on models */
|
||||
std::string model_name(const TechnologyModelId& model_id) const;
|
||||
TechnologyModelId model(const std::string& name) const;
|
||||
enum e_tech_lib_model_type model_type(const TechnologyModelId& model_id) const;
|
||||
enum e_tech_lib_type model_lib_type(const TechnologyModelId& model_id) const;
|
||||
std::string model_corner(const TechnologyModelId& model_id) const;
|
||||
std::string model_ref(const TechnologyModelId& model_id) const;
|
||||
std::string model_lib_path(const TechnologyModelId& model_id) const;
|
||||
float model_vdd(const TechnologyModelId& model_id) const;
|
||||
float model_pn_ratio(const TechnologyModelId& model_id) const;
|
||||
public: /* Public Accessors: Basic data query on transistors */
|
||||
std::string transistor_model_name(const TechnologyModelId& model_id,
|
||||
const e_tech_lib_transistor_type& transistor_type) const;
|
||||
float transistor_model_chan_length(const TechnologyModelId& model_id,
|
||||
const e_tech_lib_transistor_type& transistor_type) const;
|
||||
float transistor_model_min_width(const TechnologyModelId& model_id,
|
||||
const e_tech_lib_transistor_type& transistor_type) const;
|
||||
float transistor_model_max_width(const TechnologyModelId& model_id,
|
||||
const e_tech_lib_transistor_type& transistor_type) const;
|
||||
TechnologyVariationId transistor_model_variation(const TechnologyModelId& model_id,
|
||||
const e_tech_lib_transistor_type& transistor_type) const;
|
||||
public: /* Public Accessors: Basic data query on RRAM models */
|
||||
float rram_rlrs(const TechnologyModelId& model_id) const;
|
||||
float rram_rhrs(const TechnologyModelId& model_id) const;
|
||||
TechnologyVariationId rram_variation(const TechnologyModelId& model_id) const;
|
||||
public: /* Public Accessors: Basic data query on variations */
|
||||
std::string variation_name(const TechnologyVariationId& variation_id) const;
|
||||
TechnologyVariationId variation(const std::string& name) const;
|
||||
float variation_abs_value(const TechnologyVariationId& variation_id) const;
|
||||
size_t variation_num_sigma(const TechnologyVariationId& variation_id) const;
|
||||
public: /* Public Mutators: model-related */
|
||||
TechnologyModelId add_model(const std::string& name);
|
||||
void set_model_type(const TechnologyModelId& model_id,
|
||||
const e_tech_lib_model_type& type);
|
||||
void set_model_lib_type(const TechnologyModelId& model_id,
|
||||
const e_tech_lib_type& lib_type);
|
||||
void set_model_corner(const TechnologyModelId& model_id,
|
||||
const std::string& corner);
|
||||
void set_model_ref(const TechnologyModelId& model_id,
|
||||
const std::string& model_ref);
|
||||
void set_model_lib_path(const TechnologyModelId& model_id,
|
||||
const std::string& lib_path);
|
||||
void set_model_vdd(const TechnologyModelId& model_id,
|
||||
const float& vdd);
|
||||
void set_model_pn_ratio(const TechnologyModelId& model_id,
|
||||
const float& pn_ratio);
|
||||
public: /* Public Mutators: transistor-related */
|
||||
void set_transistor_model_name(const TechnologyModelId& model_id,
|
||||
const e_tech_lib_transistor_type& transistor_type,
|
||||
const std::string& model_name);
|
||||
void set_transistor_model_chan_length(const TechnologyModelId& model_id,
|
||||
const e_tech_lib_transistor_type& transistor_type,
|
||||
const float& chan_length);
|
||||
void set_transistor_model_min_width(const TechnologyModelId& model_id,
|
||||
const e_tech_lib_transistor_type& transistor_type,
|
||||
const float& min_width);
|
||||
void set_transistor_model_max_width(const TechnologyModelId& model_id,
|
||||
const e_tech_lib_transistor_type& transistor_type,
|
||||
const float& max_width);
|
||||
void set_transistor_model_variation_name(const TechnologyModelId& model_id,
|
||||
const e_tech_lib_transistor_type& transistor_type,
|
||||
const std::string& variation_name);
|
||||
public: /* Public Mutators: RRAM-related */
|
||||
void set_rram_rlrs(const TechnologyModelId& model_id,
|
||||
const float& rlrs);
|
||||
void set_rram_rhrs(const TechnologyModelId& model_id,
|
||||
const float& rhrs);
|
||||
void set_rram_variation_name(const TechnologyModelId& model_id,
|
||||
const std::string& variation_name);
|
||||
public: /* Public Mutators: variation-related */
|
||||
TechnologyVariationId add_variation(const std::string& name);
|
||||
void set_variation_abs_value(const TechnologyVariationId& variation_id, const float& abs_value);
|
||||
void set_variation_num_sigma(const TechnologyVariationId& variation_id, const size_t& num_sigma);
|
||||
public: /* Public Mutators: linkers */
|
||||
void link_models_to_variations();
|
||||
public: /* Public invalidators/validators */
|
||||
bool valid_model_id(const TechnologyModelId& model_id) const;
|
||||
bool valid_variation_id(const TechnologyVariationId& variation_id) const;
|
||||
private: /* Internal data */
|
||||
/* Transistor-related fundamental information */
|
||||
/* Unique identifier for each model
|
||||
* A model could be either transistors (1 pair of PMOS and NMOS) or RRAMs
|
||||
*/
|
||||
vtr::vector<TechnologyModelId, TechnologyModelId> model_ids_;
|
||||
public: /* Types */
|
||||
typedef vtr::vector<TechnologyModelId, TechnologyModelId>::const_iterator
|
||||
technology_model_iterator;
|
||||
typedef vtr::vector<TechnologyVariationId,
|
||||
TechnologyVariationId>::const_iterator
|
||||
technology_variation_iterator;
|
||||
/* Create range */
|
||||
typedef vtr::Range<technology_model_iterator> technology_model_range;
|
||||
typedef vtr::Range<technology_variation_iterator> technology_variation_range;
|
||||
|
||||
/* Unique name for each model. This is defined by XML file */
|
||||
vtr::vector<TechnologyModelId, std::string> model_names_;
|
||||
public: /* Constructors */
|
||||
TechnologyLibrary();
|
||||
|
||||
/* Type of each model, either transistors or RRAMs */
|
||||
vtr::vector<TechnologyModelId, e_tech_lib_model_type> model_types_;
|
||||
public: /* Accessors: aggregates */
|
||||
technology_model_range models() const;
|
||||
technology_variation_range variations() const;
|
||||
std::vector<TechnologyModelId> models_by_type(
|
||||
const enum e_tech_lib_model_type& type) const;
|
||||
|
||||
/* Type of models of each model, either industry or academia
|
||||
* This will lead to different ways when include these models
|
||||
* For industry models, we use .lib to include library
|
||||
* For academia models, we use .include to include library
|
||||
*/
|
||||
vtr::vector<TechnologyModelId, e_tech_lib_type> model_lib_types_;
|
||||
public: /* Public Accessors: Basic data query on models */
|
||||
std::string model_name(const TechnologyModelId& model_id) const;
|
||||
TechnologyModelId model(const std::string& name) const;
|
||||
enum e_tech_lib_model_type model_type(
|
||||
const TechnologyModelId& model_id) const;
|
||||
enum e_tech_lib_type model_lib_type(const TechnologyModelId& model_id) const;
|
||||
std::string model_corner(const TechnologyModelId& model_id) const;
|
||||
std::string model_ref(const TechnologyModelId& model_id) const;
|
||||
std::string model_lib_path(const TechnologyModelId& model_id) const;
|
||||
float model_vdd(const TechnologyModelId& model_id) const;
|
||||
float model_pn_ratio(const TechnologyModelId& model_id) const;
|
||||
|
||||
/* Name of process corner to be used for each model
|
||||
* Users can define any string for the process corner they are going to use
|
||||
* But the corner name should be consistent with their library files
|
||||
* When this is enabled, the corner name will be added when
|
||||
* include the models
|
||||
* For example, for a industry model, .lib <lib_path> <corner_name>
|
||||
*/
|
||||
vtr::vector<TechnologyModelId, std::string> model_corners_;
|
||||
public: /* Public Accessors: Basic data query on transistors */
|
||||
std::string transistor_model_name(
|
||||
const TechnologyModelId& model_id,
|
||||
const e_tech_lib_transistor_type& transistor_type) const;
|
||||
float transistor_model_chan_length(
|
||||
const TechnologyModelId& model_id,
|
||||
const e_tech_lib_transistor_type& transistor_type) const;
|
||||
float transistor_model_min_width(
|
||||
const TechnologyModelId& model_id,
|
||||
const e_tech_lib_transistor_type& transistor_type) const;
|
||||
float transistor_model_max_width(
|
||||
const TechnologyModelId& model_id,
|
||||
const e_tech_lib_transistor_type& transistor_type) const;
|
||||
TechnologyVariationId transistor_model_variation(
|
||||
const TechnologyModelId& model_id,
|
||||
const e_tech_lib_transistor_type& transistor_type) const;
|
||||
|
||||
/* The string used to instanciate the model models
|
||||
* This will really depend on the type of models
|
||||
* For most industry models, we can use 'M' to instanciate a transisitor
|
||||
* For some academia models, we have to use 'X' to do so
|
||||
*/
|
||||
vtr::vector<TechnologyModelId, std::string> model_refs_;
|
||||
public: /* Public Accessors: Basic data query on RRAM models */
|
||||
float rram_rlrs(const TechnologyModelId& model_id) const;
|
||||
float rram_rhrs(const TechnologyModelId& model_id) const;
|
||||
TechnologyVariationId rram_variation(const TechnologyModelId& model_id) const;
|
||||
|
||||
/* The path to the transistor models
|
||||
* This is going to be the <lib_path> when include the library files
|
||||
* See the example in the comments about process corner
|
||||
*/
|
||||
vtr::vector<TechnologyModelId, std::string> model_lib_paths_;
|
||||
public: /* Public Accessors: Basic data query on variations */
|
||||
std::string variation_name(const TechnologyVariationId& variation_id) const;
|
||||
TechnologyVariationId variation(const std::string& name) const;
|
||||
float variation_abs_value(const TechnologyVariationId& variation_id) const;
|
||||
size_t variation_num_sigma(const TechnologyVariationId& variation_id) const;
|
||||
|
||||
/* Operating voltage for the models. Unit: [V] */
|
||||
vtr::vector<TechnologyModelId, float> model_vdds_;
|
||||
public: /* Public Mutators: model-related */
|
||||
TechnologyModelId add_model(const std::string& name);
|
||||
void set_model_type(const TechnologyModelId& model_id,
|
||||
const e_tech_lib_model_type& type);
|
||||
void set_model_lib_type(const TechnologyModelId& model_id,
|
||||
const e_tech_lib_type& lib_type);
|
||||
void set_model_corner(const TechnologyModelId& model_id,
|
||||
const std::string& corner);
|
||||
void set_model_ref(const TechnologyModelId& model_id,
|
||||
const std::string& model_ref);
|
||||
void set_model_lib_path(const TechnologyModelId& model_id,
|
||||
const std::string& lib_path);
|
||||
void set_model_vdd(const TechnologyModelId& model_id, const float& vdd);
|
||||
void set_model_pn_ratio(const TechnologyModelId& model_id,
|
||||
const float& pn_ratio);
|
||||
|
||||
/* The width ratio between PMOS and NMOS for a model group
|
||||
* This really depend the transistor technology
|
||||
* We recommend users to characterize driving strengths of
|
||||
* PMOS and NMOS using SPICE simulators
|
||||
*/
|
||||
vtr::vector<TechnologyModelId, float> model_pn_ratios_;
|
||||
public: /* Public Mutators: transistor-related */
|
||||
void set_transistor_model_name(
|
||||
const TechnologyModelId& model_id,
|
||||
const e_tech_lib_transistor_type& transistor_type,
|
||||
const std::string& model_name);
|
||||
void set_transistor_model_chan_length(
|
||||
const TechnologyModelId& model_id,
|
||||
const e_tech_lib_transistor_type& transistor_type,
|
||||
const float& chan_length);
|
||||
void set_transistor_model_min_width(
|
||||
const TechnologyModelId& model_id,
|
||||
const e_tech_lib_transistor_type& transistor_type, const float& min_width);
|
||||
void set_transistor_model_max_width(
|
||||
const TechnologyModelId& model_id,
|
||||
const e_tech_lib_transistor_type& transistor_type, const float& max_width);
|
||||
void set_transistor_model_variation_name(
|
||||
const TechnologyModelId& model_id,
|
||||
const e_tech_lib_transistor_type& transistor_type,
|
||||
const std::string& variation_name);
|
||||
|
||||
/* The model name is the name that is defined in your library file.
|
||||
* For example, your NMOS transistor may be defined as
|
||||
* .model nch
|
||||
* in some BSIM models. In this case, nch will be the model name
|
||||
*
|
||||
* In the rest of these transistor-level parameters, we follow the same organization:
|
||||
* PMOS data will be stored in the first element of the array
|
||||
* NMOS data will be stored in the second element of the array
|
||||
*/
|
||||
vtr::vector<TechnologyModelId, std::array<std::string, 2>> transistor_model_names_;
|
||||
public: /* Public Mutators: RRAM-related */
|
||||
void set_rram_rlrs(const TechnologyModelId& model_id, const float& rlrs);
|
||||
void set_rram_rhrs(const TechnologyModelId& model_id, const float& rhrs);
|
||||
void set_rram_variation_name(const TechnologyModelId& model_id,
|
||||
const std::string& variation_name);
|
||||
|
||||
/* The channel length of a transistor.
|
||||
* This should be defined by your technology vendor
|
||||
* For example, a 22nm technology, the channel length is around 22nm
|
||||
*/
|
||||
vtr::vector<TechnologyModelId, std::array<float, 2>> transistor_model_chan_lengths_;
|
||||
public: /* Public Mutators: variation-related */
|
||||
TechnologyVariationId add_variation(const std::string& name);
|
||||
void set_variation_abs_value(const TechnologyVariationId& variation_id,
|
||||
const float& abs_value);
|
||||
void set_variation_num_sigma(const TechnologyVariationId& variation_id,
|
||||
const size_t& num_sigma);
|
||||
|
||||
/* The minimum width of a transistor.
|
||||
* This should be defined by your technology vendor
|
||||
*/
|
||||
vtr::vector<TechnologyModelId, std::array<float, 2>> transistor_model_min_widths_;
|
||||
public: /* Public Mutators: linkers */
|
||||
void link_models_to_variations();
|
||||
|
||||
/* The maximum width of a transistor.
|
||||
* This should be defined by your technology vendor
|
||||
* The maximum width of a transistor will be used to size your transistors
|
||||
* If the required width in circuit models in larger then the max width,
|
||||
* multiple transistor bin will be instanciated.
|
||||
* For FinFET, the maximum width should be the same as min_width
|
||||
*/
|
||||
vtr::vector<TechnologyModelId, std::array<float, 2>> transistor_model_max_widths_;
|
||||
public: /* Public invalidators/validators */
|
||||
bool valid_model_id(const TechnologyModelId& model_id) const;
|
||||
bool valid_variation_id(const TechnologyVariationId& variation_id) const;
|
||||
|
||||
/* The variation name and id binded to PMOS and NMOS transistor
|
||||
* We expect users to provide the exact name of variation defined in this technology library
|
||||
* the name and id will be automatically matched by using function link_model_to_variation()
|
||||
*/
|
||||
vtr::vector<TechnologyModelId, std::array<std::string, 2>> transistor_model_variation_names_;
|
||||
vtr::vector<TechnologyModelId, std::array<TechnologyVariationId, 2>> transistor_model_variation_ids_;
|
||||
private: /* Internal data */
|
||||
/* Transistor-related fundamental information */
|
||||
/* Unique identifier for each model
|
||||
* A model could be either transistors (1 pair of PMOS and NMOS) or RRAMs
|
||||
*/
|
||||
vtr::vector<TechnologyModelId, TechnologyModelId> model_ids_;
|
||||
|
||||
/* ReRAM-related fundamental information:
|
||||
* Low Resistance State (LRS) resistance will be stored in the x() part of vtr::Point
|
||||
* High Resistance State (HRS) resistance will be stored in the y() part of vtr::Point
|
||||
* Unit: [Ohm]
|
||||
*/
|
||||
vtr::vector<TechnologyModelId, vtr::Point<float>> rram_resistances_;
|
||||
/* Unique name for each model. This is defined by XML file */
|
||||
vtr::vector<TechnologyModelId, std::string> model_names_;
|
||||
|
||||
/* The variation name and id binded to this RRAM
|
||||
* We expect users to provide the exact name of variation defined in this technology library
|
||||
* the name and id will be automatically matched by using function link_model_to_variation()
|
||||
*/
|
||||
vtr::vector<TechnologyModelId, std::string> rram_variation_names_;
|
||||
vtr::vector<TechnologyModelId, TechnologyVariationId> rram_variation_ids_;
|
||||
|
||||
/* Unique identifier for each process variation */
|
||||
vtr::vector<TechnologyVariationId, TechnologyVariationId> variation_ids_;
|
||||
vtr::vector<TechnologyVariationId, std::string> variation_names_;
|
||||
|
||||
/* Absoluate and standard deviation of a process variation
|
||||
* These are used to apply manual process variations
|
||||
* in case your technology vender does not provide any
|
||||
*/
|
||||
vtr::vector<TechnologyVariationId, float> variation_abs_values_;
|
||||
vtr::vector<TechnologyVariationId, size_t> variation_num_sigmas_;
|
||||
/* Type of each model, either transistors or RRAMs */
|
||||
vtr::vector<TechnologyModelId, e_tech_lib_model_type> model_types_;
|
||||
|
||||
/* Fast name-to-id lookup */
|
||||
std::map<std::string, TechnologyModelId> model_name2ids_;
|
||||
std::map<std::string, TechnologyVariationId> variation_name2ids_;
|
||||
/* Type of models of each model, either industry or academia
|
||||
* This will lead to different ways when include these models
|
||||
* For industry models, we use .lib to include library
|
||||
* For academia models, we use .include to include library
|
||||
*/
|
||||
vtr::vector<TechnologyModelId, e_tech_lib_type> model_lib_types_;
|
||||
|
||||
/* Name of process corner to be used for each model
|
||||
* Users can define any string for the process corner they are going to use
|
||||
* But the corner name should be consistent with their library files
|
||||
* When this is enabled, the corner name will be added when
|
||||
* include the models
|
||||
* For example, for a industry model, .lib <lib_path> <corner_name>
|
||||
*/
|
||||
vtr::vector<TechnologyModelId, std::string> model_corners_;
|
||||
|
||||
/* The string used to instanciate the model models
|
||||
* This will really depend on the type of models
|
||||
* For most industry models, we can use 'M' to instanciate a transisitor
|
||||
* For some academia models, we have to use 'X' to do so
|
||||
*/
|
||||
vtr::vector<TechnologyModelId, std::string> model_refs_;
|
||||
|
||||
/* The path to the transistor models
|
||||
* This is going to be the <lib_path> when include the library files
|
||||
* See the example in the comments about process corner
|
||||
*/
|
||||
vtr::vector<TechnologyModelId, std::string> model_lib_paths_;
|
||||
|
||||
/* Operating voltage for the models. Unit: [V] */
|
||||
vtr::vector<TechnologyModelId, float> model_vdds_;
|
||||
|
||||
/* The width ratio between PMOS and NMOS for a model group
|
||||
* This really depend the transistor technology
|
||||
* We recommend users to characterize driving strengths of
|
||||
* PMOS and NMOS using SPICE simulators
|
||||
*/
|
||||
vtr::vector<TechnologyModelId, float> model_pn_ratios_;
|
||||
|
||||
/* The model name is the name that is defined in your library file.
|
||||
* For example, your NMOS transistor may be defined as
|
||||
* .model nch
|
||||
* in some BSIM models. In this case, nch will be the model name
|
||||
*
|
||||
* In the rest of these transistor-level parameters, we follow the same
|
||||
* organization: PMOS data will be stored in the first element of the array
|
||||
* NMOS data will be stored in the second element of the array
|
||||
*/
|
||||
vtr::vector<TechnologyModelId, std::array<std::string, 2>>
|
||||
transistor_model_names_;
|
||||
|
||||
/* The channel length of a transistor.
|
||||
* This should be defined by your technology vendor
|
||||
* For example, a 22nm technology, the channel length is around 22nm
|
||||
*/
|
||||
vtr::vector<TechnologyModelId, std::array<float, 2>>
|
||||
transistor_model_chan_lengths_;
|
||||
|
||||
/* The minimum width of a transistor.
|
||||
* This should be defined by your technology vendor
|
||||
*/
|
||||
vtr::vector<TechnologyModelId, std::array<float, 2>>
|
||||
transistor_model_min_widths_;
|
||||
|
||||
/* The maximum width of a transistor.
|
||||
* This should be defined by your technology vendor
|
||||
* The maximum width of a transistor will be used to size your transistors
|
||||
* If the required width in circuit models in larger then the max width,
|
||||
* multiple transistor bin will be instanciated.
|
||||
* For FinFET, the maximum width should be the same as min_width
|
||||
*/
|
||||
vtr::vector<TechnologyModelId, std::array<float, 2>>
|
||||
transistor_model_max_widths_;
|
||||
|
||||
/* The variation name and id binded to PMOS and NMOS transistor
|
||||
* We expect users to provide the exact name of variation defined in this
|
||||
* technology library the name and id will be automatically matched by using
|
||||
* function link_model_to_variation()
|
||||
*/
|
||||
vtr::vector<TechnologyModelId, std::array<std::string, 2>>
|
||||
transistor_model_variation_names_;
|
||||
vtr::vector<TechnologyModelId, std::array<TechnologyVariationId, 2>>
|
||||
transistor_model_variation_ids_;
|
||||
|
||||
/* ReRAM-related fundamental information:
|
||||
* Low Resistance State (LRS) resistance will be stored in the x() part of
|
||||
* vtr::Point High Resistance State (HRS) resistance will be stored in the y()
|
||||
* part of vtr::Point Unit: [Ohm]
|
||||
*/
|
||||
vtr::vector<TechnologyModelId, vtr::Point<float>> rram_resistances_;
|
||||
|
||||
/* The variation name and id binded to this RRAM
|
||||
* We expect users to provide the exact name of variation defined in this
|
||||
* technology library the name and id will be automatically matched by using
|
||||
* function link_model_to_variation()
|
||||
*/
|
||||
vtr::vector<TechnologyModelId, std::string> rram_variation_names_;
|
||||
vtr::vector<TechnologyModelId, TechnologyVariationId> rram_variation_ids_;
|
||||
|
||||
/* Unique identifier for each process variation */
|
||||
vtr::vector<TechnologyVariationId, TechnologyVariationId> variation_ids_;
|
||||
vtr::vector<TechnologyVariationId, std::string> variation_names_;
|
||||
|
||||
/* Absoluate and standard deviation of a process variation
|
||||
* These are used to apply manual process variations
|
||||
* in case your technology vender does not provide any
|
||||
*/
|
||||
vtr::vector<TechnologyVariationId, float> variation_abs_values_;
|
||||
vtr::vector<TechnologyVariationId, size_t> variation_num_sigmas_;
|
||||
|
||||
/* Fast name-to-id lookup */
|
||||
std::map<std::string, TechnologyModelId> model_name2ids_;
|
||||
std::map<std::string, TechnologyVariationId> variation_name2ids_;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/************************************************************************
|
||||
* A header file for TechnologyLibrary class, including critical data declaration
|
||||
* Please include this file only for using any TechnologyLibrary data structure
|
||||
* Refer to circuit_library.h for more details
|
||||
* A header file for TechnologyLibrary class, including critical data
|
||||
*declaration Please include this file only for using any TechnologyLibrary data
|
||||
*structure Refer to circuit_library.h for more details
|
||||
***********************************************************************/
|
||||
|
||||
/************************************************************************
|
||||
* Create strong id for TechnologyDevice to avoid illegal type casting
|
||||
* Create strong id for TechnologyDevice to avoid illegal type casting
|
||||
***********************************************************************/
|
||||
#ifndef TECHNOLOGY_LIBRARY_FWD_H
|
||||
#define TECHNOLOGY_LIBRARY_FWD_H
|
||||
|
|
|
@ -1,19 +1,17 @@
|
|||
/************************************************************************
|
||||
* Member functions for class TileAnnotation
|
||||
***********************************************************************/
|
||||
#include "vtr_assert.h"
|
||||
|
||||
#include "tile_annotation.h"
|
||||
|
||||
#include "vtr_assert.h"
|
||||
|
||||
/* namespace openfpga begins */
|
||||
namespace openfpga {
|
||||
|
||||
/************************************************************************
|
||||
* Constructors
|
||||
***********************************************************************/
|
||||
TileAnnotation::TileAnnotation() {
|
||||
return;
|
||||
}
|
||||
TileAnnotation::TileAnnotation() { return; }
|
||||
|
||||
/************************************************************************
|
||||
* Public Accessors : aggregates
|
||||
|
@ -25,42 +23,50 @@ TileAnnotation::global_port_range TileAnnotation::global_ports() const {
|
|||
/************************************************************************
|
||||
* Public Accessors
|
||||
***********************************************************************/
|
||||
std::string TileAnnotation::global_port_name(const TileGlobalPortId& global_port_id) const {
|
||||
std::string TileAnnotation::global_port_name(
|
||||
const TileGlobalPortId& global_port_id) const {
|
||||
VTR_ASSERT(valid_global_port_id(global_port_id));
|
||||
return global_port_names_[global_port_id];
|
||||
}
|
||||
|
||||
std::vector<std::string> TileAnnotation::global_port_tile_names(const TileGlobalPortId& global_port_id) const {
|
||||
std::vector<std::string> TileAnnotation::global_port_tile_names(
|
||||
const TileGlobalPortId& global_port_id) const {
|
||||
VTR_ASSERT(valid_global_port_id(global_port_id));
|
||||
return global_port_tile_names_[global_port_id];
|
||||
}
|
||||
|
||||
std::vector<BasicPort> TileAnnotation::global_port_tile_ports(const TileGlobalPortId& global_port_id) const {
|
||||
std::vector<BasicPort> TileAnnotation::global_port_tile_ports(
|
||||
const TileGlobalPortId& global_port_id) const {
|
||||
VTR_ASSERT(valid_global_port_id(global_port_id));
|
||||
return global_port_tile_ports_[global_port_id];
|
||||
}
|
||||
|
||||
std::vector<vtr::Point<size_t>> TileAnnotation::global_port_tile_coordinates(const TileGlobalPortId& global_port_id) const {
|
||||
std::vector<vtr::Point<size_t>> TileAnnotation::global_port_tile_coordinates(
|
||||
const TileGlobalPortId& global_port_id) const {
|
||||
VTR_ASSERT(valid_global_port_id(global_port_id));
|
||||
return global_port_tile_coordinates_[global_port_id];
|
||||
}
|
||||
|
||||
bool TileAnnotation::global_port_is_clock(const TileGlobalPortId& global_port_id) const {
|
||||
bool TileAnnotation::global_port_is_clock(
|
||||
const TileGlobalPortId& global_port_id) const {
|
||||
VTR_ASSERT(valid_global_port_id(global_port_id));
|
||||
return global_port_is_clock_[global_port_id];
|
||||
}
|
||||
|
||||
bool TileAnnotation::global_port_is_set(const TileGlobalPortId& global_port_id) const {
|
||||
bool TileAnnotation::global_port_is_set(
|
||||
const TileGlobalPortId& global_port_id) const {
|
||||
VTR_ASSERT(valid_global_port_id(global_port_id));
|
||||
return global_port_is_set_[global_port_id];
|
||||
}
|
||||
|
||||
bool TileAnnotation::global_port_is_reset(const TileGlobalPortId& global_port_id) const {
|
||||
bool TileAnnotation::global_port_is_reset(
|
||||
const TileGlobalPortId& global_port_id) const {
|
||||
VTR_ASSERT(valid_global_port_id(global_port_id));
|
||||
return global_port_is_reset_[global_port_id];
|
||||
}
|
||||
|
||||
size_t TileAnnotation::global_port_default_value(const TileGlobalPortId& global_port_id) const {
|
||||
size_t TileAnnotation::global_port_default_value(
|
||||
const TileGlobalPortId& global_port_id) const {
|
||||
VTR_ASSERT(valid_global_port_id(global_port_id));
|
||||
return global_port_default_values_[global_port_id];
|
||||
}
|
||||
|
@ -68,9 +74,11 @@ size_t TileAnnotation::global_port_default_value(const TileGlobalPortId& global_
|
|||
/************************************************************************
|
||||
* Public Mutators
|
||||
***********************************************************************/
|
||||
TileGlobalPortId TileAnnotation::create_global_port(const std::string& port_name) {
|
||||
TileGlobalPortId TileAnnotation::create_global_port(
|
||||
const std::string& port_name) {
|
||||
/* Ensure that the name is unique */
|
||||
std::map<std::string, TileGlobalPortId>::iterator it = global_port_name2ids_.find(port_name);
|
||||
std::map<std::string, TileGlobalPortId>::iterator it =
|
||||
global_port_name2ids_.find(port_name);
|
||||
if (it != global_port_name2ids_.end()) {
|
||||
return TileGlobalPortId::INVALID();
|
||||
}
|
||||
|
@ -93,49 +101,51 @@ TileGlobalPortId TileAnnotation::create_global_port(const std::string& port_name
|
|||
return port_id;
|
||||
}
|
||||
|
||||
void TileAnnotation::add_global_port_tile_information(const TileGlobalPortId& global_port_id,
|
||||
const std::string& tile_name,
|
||||
const BasicPort& tile_port,
|
||||
const vtr::Point<size_t>& tile_coord) {
|
||||
void TileAnnotation::add_global_port_tile_information(
|
||||
const TileGlobalPortId& global_port_id, const std::string& tile_name,
|
||||
const BasicPort& tile_port, const vtr::Point<size_t>& tile_coord) {
|
||||
VTR_ASSERT(valid_global_port_id(global_port_id));
|
||||
global_port_tile_names_[global_port_id].push_back(tile_name);
|
||||
global_port_tile_ports_[global_port_id].push_back(tile_port);
|
||||
global_port_tile_coordinates_[global_port_id].push_back(tile_coord);
|
||||
}
|
||||
|
||||
void TileAnnotation::set_global_port_is_clock(const TileGlobalPortId& global_port_id,
|
||||
const bool& is_clock) {
|
||||
void TileAnnotation::set_global_port_is_clock(
|
||||
const TileGlobalPortId& global_port_id, const bool& is_clock) {
|
||||
VTR_ASSERT(valid_global_port_id(global_port_id));
|
||||
global_port_is_clock_[global_port_id] = is_clock;
|
||||
}
|
||||
|
||||
void TileAnnotation::set_global_port_is_set(const TileGlobalPortId& global_port_id,
|
||||
const bool& is_set) {
|
||||
void TileAnnotation::set_global_port_is_set(
|
||||
const TileGlobalPortId& global_port_id, const bool& is_set) {
|
||||
VTR_ASSERT(valid_global_port_id(global_port_id));
|
||||
global_port_is_set_[global_port_id] = is_set;
|
||||
}
|
||||
|
||||
void TileAnnotation::set_global_port_is_reset(const TileGlobalPortId& global_port_id,
|
||||
const bool& is_reset) {
|
||||
void TileAnnotation::set_global_port_is_reset(
|
||||
const TileGlobalPortId& global_port_id, const bool& is_reset) {
|
||||
VTR_ASSERT(valid_global_port_id(global_port_id));
|
||||
global_port_is_reset_[global_port_id] = is_reset;
|
||||
}
|
||||
|
||||
void TileAnnotation::set_global_port_default_value(const TileGlobalPortId& global_port_id,
|
||||
const size_t& default_value) {
|
||||
void TileAnnotation::set_global_port_default_value(
|
||||
const TileGlobalPortId& global_port_id, const size_t& default_value) {
|
||||
VTR_ASSERT(valid_global_port_id(global_port_id));
|
||||
global_port_default_values_[global_port_id] = default_value;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Internal invalidators/validators
|
||||
* Internal invalidators/validators
|
||||
***********************************************************************/
|
||||
/* Validators */
|
||||
bool TileAnnotation::valid_global_port_id(const TileGlobalPortId& global_port_id) const {
|
||||
return ( size_t(global_port_id) < global_port_ids_.size() ) && ( global_port_id == global_port_ids_[global_port_id] );
|
||||
bool TileAnnotation::valid_global_port_id(
|
||||
const TileGlobalPortId& global_port_id) const {
|
||||
return (size_t(global_port_id) < global_port_ids_.size()) &&
|
||||
(global_port_id == global_port_ids_[global_port_id]);
|
||||
}
|
||||
|
||||
bool TileAnnotation::valid_global_port_attributes(const TileGlobalPortId& global_port_id) const {
|
||||
bool TileAnnotation::valid_global_port_attributes(
|
||||
const TileGlobalPortId& global_port_id) const {
|
||||
VTR_ASSERT(valid_global_port_id(global_port_id));
|
||||
|
||||
int attribute_counter = 0;
|
||||
|
@ -155,4 +165,4 @@ bool TileAnnotation::valid_global_port_attributes(const TileGlobalPortId& global
|
|||
return ((0 == attribute_counter) || (1 == attribute_counter));
|
||||
}
|
||||
|
||||
} /* namespace openfpga ends */
|
||||
} // namespace openfpga
|
||||
|
|
|
@ -4,16 +4,14 @@
|
|||
/********************************************************************
|
||||
* Include header files required by the data structure definition
|
||||
*******************************************************************/
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <array>
|
||||
|
||||
#include "vtr_vector.h"
|
||||
#include "vtr_geometry.h"
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include "openfpga_port.h"
|
||||
|
||||
#include "tile_annotation_fwd.h"
|
||||
#include "vtr_geometry.h"
|
||||
#include "vtr_vector.h"
|
||||
|
||||
/* namespace openfpga begins */
|
||||
namespace openfpga {
|
||||
|
@ -21,7 +19,7 @@ namespace openfpga {
|
|||
/********************************************************************
|
||||
* This file include the declaration of data structures
|
||||
* to store physical tile annotation, including
|
||||
* 1. global port definition where a tile port can be treated as a
|
||||
* 1. global port definition where a tile port can be treated as a
|
||||
* global port of the FPGA fabric
|
||||
*
|
||||
* Note:
|
||||
|
@ -30,63 +28,77 @@ namespace openfpga {
|
|||
* to other data structures, please create another one in other header files
|
||||
*******************************************************************/
|
||||
class TileAnnotation {
|
||||
public: /* Types */
|
||||
typedef vtr::vector<TileGlobalPortId, TileGlobalPortId>::const_iterator global_port_iterator;
|
||||
/* Create range */
|
||||
typedef vtr::Range<global_port_iterator> global_port_range;
|
||||
public: /* Constructor */
|
||||
TileAnnotation();
|
||||
public: /* Public accessors: aggregators */
|
||||
global_port_range global_ports() const;
|
||||
public: /* Public accessors */
|
||||
std::string global_port_name(const TileGlobalPortId& global_port_id) const;
|
||||
std::vector<std::string> global_port_tile_names(const TileGlobalPortId& global_port_id) const;
|
||||
std::vector<BasicPort> global_port_tile_ports(const TileGlobalPortId& global_port_id) const;
|
||||
std::vector<vtr::Point<size_t>> global_port_tile_coordinates(const TileGlobalPortId& global_port_id) const;
|
||||
bool global_port_is_clock(const TileGlobalPortId& global_port_id) const;
|
||||
bool global_port_is_set(const TileGlobalPortId& global_port_id) const;
|
||||
bool global_port_is_reset(const TileGlobalPortId& global_port_id) const;
|
||||
size_t global_port_default_value(const TileGlobalPortId& global_port_id) const;
|
||||
public: /* Public mutators */
|
||||
/* By default, we do not set it as a clock.
|
||||
* Users should set it through the set_global_port_is_clock() function
|
||||
*/
|
||||
TileGlobalPortId create_global_port(const std::string& port_name);
|
||||
/* Add tile port information */
|
||||
void add_global_port_tile_information(const TileGlobalPortId& global_port_id,
|
||||
const std::string& tile_name,
|
||||
const BasicPort& tile_port,
|
||||
const vtr::Point<size_t>& tile_coord);
|
||||
void set_global_port_is_clock(const TileGlobalPortId& global_port_id,
|
||||
const bool& is_clock);
|
||||
void set_global_port_is_set(const TileGlobalPortId& global_port_id,
|
||||
const bool& is_set);
|
||||
void set_global_port_is_reset(const TileGlobalPortId& global_port_id,
|
||||
const bool& is_reset);
|
||||
void set_global_port_default_value(const TileGlobalPortId& global_port_id,
|
||||
const size_t& default_value);
|
||||
public: /* Public validator */
|
||||
bool valid_global_port_id(const TileGlobalPortId& global_port_id) const;
|
||||
/* Validate attributes of a given global port
|
||||
* - A port can only be defined as clock or set or reset
|
||||
*/
|
||||
bool valid_global_port_attributes(const TileGlobalPortId& global_port_id) const;
|
||||
private: /* Internal data */
|
||||
/* Global port information for tiles */
|
||||
vtr::vector<TileGlobalPortId, TileGlobalPortId> global_port_ids_;
|
||||
vtr::vector<TileGlobalPortId, std::string> global_port_names_;
|
||||
vtr::vector<TileGlobalPortId, std::vector<std::string>> global_port_tile_names_;
|
||||
vtr::vector<TileGlobalPortId, std::vector<vtr::Point<size_t>>> global_port_tile_coordinates_;
|
||||
vtr::vector<TileGlobalPortId, std::vector<BasicPort>> global_port_tile_ports_;
|
||||
vtr::vector<TileGlobalPortId, bool> global_port_is_clock_;
|
||||
vtr::vector<TileGlobalPortId, bool> global_port_is_reset_;
|
||||
vtr::vector<TileGlobalPortId, bool> global_port_is_set_;
|
||||
vtr::vector<TileGlobalPortId, size_t> global_port_default_values_;
|
||||
public: /* Types */
|
||||
typedef vtr::vector<TileGlobalPortId, TileGlobalPortId>::const_iterator
|
||||
global_port_iterator;
|
||||
/* Create range */
|
||||
typedef vtr::Range<global_port_iterator> global_port_range;
|
||||
|
||||
/* A fast lookup for port names */
|
||||
std::map<std::string, TileGlobalPortId> global_port_name2ids_;
|
||||
public: /* Constructor */
|
||||
TileAnnotation();
|
||||
|
||||
public: /* Public accessors: aggregators */
|
||||
global_port_range global_ports() const;
|
||||
|
||||
public: /* Public accessors */
|
||||
std::string global_port_name(const TileGlobalPortId& global_port_id) const;
|
||||
std::vector<std::string> global_port_tile_names(
|
||||
const TileGlobalPortId& global_port_id) const;
|
||||
std::vector<BasicPort> global_port_tile_ports(
|
||||
const TileGlobalPortId& global_port_id) const;
|
||||
std::vector<vtr::Point<size_t>> global_port_tile_coordinates(
|
||||
const TileGlobalPortId& global_port_id) const;
|
||||
bool global_port_is_clock(const TileGlobalPortId& global_port_id) const;
|
||||
bool global_port_is_set(const TileGlobalPortId& global_port_id) const;
|
||||
bool global_port_is_reset(const TileGlobalPortId& global_port_id) const;
|
||||
size_t global_port_default_value(
|
||||
const TileGlobalPortId& global_port_id) const;
|
||||
|
||||
public: /* Public mutators */
|
||||
/* By default, we do not set it as a clock.
|
||||
* Users should set it through the set_global_port_is_clock() function
|
||||
*/
|
||||
TileGlobalPortId create_global_port(const std::string& port_name);
|
||||
/* Add tile port information */
|
||||
void add_global_port_tile_information(const TileGlobalPortId& global_port_id,
|
||||
const std::string& tile_name,
|
||||
const BasicPort& tile_port,
|
||||
const vtr::Point<size_t>& tile_coord);
|
||||
void set_global_port_is_clock(const TileGlobalPortId& global_port_id,
|
||||
const bool& is_clock);
|
||||
void set_global_port_is_set(const TileGlobalPortId& global_port_id,
|
||||
const bool& is_set);
|
||||
void set_global_port_is_reset(const TileGlobalPortId& global_port_id,
|
||||
const bool& is_reset);
|
||||
void set_global_port_default_value(const TileGlobalPortId& global_port_id,
|
||||
const size_t& default_value);
|
||||
|
||||
public: /* Public validator */
|
||||
bool valid_global_port_id(const TileGlobalPortId& global_port_id) const;
|
||||
/* Validate attributes of a given global port
|
||||
* - A port can only be defined as clock or set or reset
|
||||
*/
|
||||
bool valid_global_port_attributes(
|
||||
const TileGlobalPortId& global_port_id) const;
|
||||
|
||||
private: /* Internal data */
|
||||
/* Global port information for tiles */
|
||||
vtr::vector<TileGlobalPortId, TileGlobalPortId> global_port_ids_;
|
||||
vtr::vector<TileGlobalPortId, std::string> global_port_names_;
|
||||
vtr::vector<TileGlobalPortId, std::vector<std::string>>
|
||||
global_port_tile_names_;
|
||||
vtr::vector<TileGlobalPortId, std::vector<vtr::Point<size_t>>>
|
||||
global_port_tile_coordinates_;
|
||||
vtr::vector<TileGlobalPortId, std::vector<BasicPort>> global_port_tile_ports_;
|
||||
vtr::vector<TileGlobalPortId, bool> global_port_is_clock_;
|
||||
vtr::vector<TileGlobalPortId, bool> global_port_is_reset_;
|
||||
vtr::vector<TileGlobalPortId, bool> global_port_is_set_;
|
||||
vtr::vector<TileGlobalPortId, size_t> global_port_default_values_;
|
||||
|
||||
/* A fast lookup for port names */
|
||||
std::map<std::string, TileGlobalPortId> global_port_name2ids_;
|
||||
};
|
||||
|
||||
} /* namespace openfpga ends */
|
||||
} // namespace openfpga
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/************************************************************************
|
||||
* A header file for TileAnnotation class, including critical data declaration
|
||||
* Please include this file only for using any TileAnnotation data structure
|
||||
* Refer to tile_annotation.h for more details
|
||||
* Refer to tile_annotation.h for more details
|
||||
***********************************************************************/
|
||||
|
||||
/************************************************************************
|
||||
* Create strong id for tile global ports to avoid illegal type casting
|
||||
* Create strong id for tile global ports to avoid illegal type casting
|
||||
***********************************************************************/
|
||||
#ifndef TILE_ANNOTATION_FWD_H
|
||||
#define TILE_ANNOTATION_FWD_H
|
||||
|
|
|
@ -2,33 +2,41 @@
|
|||
* This file includes functions that outputs a bitstream setting to XML format
|
||||
*******************************************************************/
|
||||
/* Headers from system goes first */
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
/* Headers from vtr util library */
|
||||
#include "openfpga_digest.h"
|
||||
#include "vtr_assert.h"
|
||||
#include "vtr_log.h"
|
||||
#include "openfpga_digest.h"
|
||||
|
||||
/* Headers from readarchopenfpga library */
|
||||
#include "write_xml_utils.h"
|
||||
#include "write_xml_bitstream_setting.h"
|
||||
#include "write_xml_utils.h"
|
||||
|
||||
/********************************************************************
|
||||
* Generate the full hierarchy name for a pb_type in bitstream setting
|
||||
*******************************************************************/
|
||||
static
|
||||
std::string generate_bitstream_setting_pb_type_hierarchy_name(const openfpga::BitstreamSetting& bitstream_setting,
|
||||
const BitstreamPbTypeSettingId& bitstream_pb_type_setting_id) {
|
||||
static std::string generate_bitstream_setting_pb_type_hierarchy_name(
|
||||
const openfpga::BitstreamSetting& bitstream_setting,
|
||||
const BitstreamPbTypeSettingId& bitstream_pb_type_setting_id) {
|
||||
/* Iterate over the parent_pb_type and modes names, they should well match */
|
||||
VTR_ASSERT_SAFE(bitstream_setting.parent_pb_type_names(bitstream_pb_type_setting_id).size() == bitstream_setting.parent_mode_names(bitstream_pb_type_setting_id).size());
|
||||
VTR_ASSERT_SAFE(
|
||||
bitstream_setting.parent_pb_type_names(bitstream_pb_type_setting_id)
|
||||
.size() ==
|
||||
bitstream_setting.parent_mode_names(bitstream_pb_type_setting_id).size());
|
||||
|
||||
std::string hie_name;
|
||||
|
||||
for (size_t i = 0 ; i < bitstream_setting.parent_pb_type_names(bitstream_pb_type_setting_id).size(); ++i) {
|
||||
hie_name += bitstream_setting.parent_pb_type_names(bitstream_pb_type_setting_id)[i];
|
||||
for (size_t i = 0;
|
||||
i < bitstream_setting.parent_pb_type_names(bitstream_pb_type_setting_id)
|
||||
.size();
|
||||
++i) {
|
||||
hie_name +=
|
||||
bitstream_setting.parent_pb_type_names(bitstream_pb_type_setting_id)[i];
|
||||
hie_name += std::string("[");
|
||||
hie_name += bitstream_setting.parent_mode_names(bitstream_pb_type_setting_id)[i];
|
||||
hie_name +=
|
||||
bitstream_setting.parent_mode_names(bitstream_pb_type_setting_id)[i];
|
||||
hie_name += std::string("]");
|
||||
hie_name += std::string(".");
|
||||
}
|
||||
|
@ -42,18 +50,26 @@ std::string generate_bitstream_setting_pb_type_hierarchy_name(const openfpga::Bi
|
|||
/********************************************************************
|
||||
* Generate the full hierarchy name for an interconnect in bitstream setting
|
||||
*******************************************************************/
|
||||
static
|
||||
std::string generate_bitstream_setting_interconnect_hierarchy_name(const openfpga::BitstreamSetting& bitstream_setting,
|
||||
const BitstreamInterconnectSettingId& bitstream_interc_setting_id) {
|
||||
static std::string generate_bitstream_setting_interconnect_hierarchy_name(
|
||||
const openfpga::BitstreamSetting& bitstream_setting,
|
||||
const BitstreamInterconnectSettingId& bitstream_interc_setting_id) {
|
||||
/* Iterate over the parent_pb_type and modes names, they should well match */
|
||||
VTR_ASSERT_SAFE(bitstream_setting.parent_pb_type_names(bitstream_interc_setting_id).size() == bitstream_setting.parent_mode_names(bitstream_interc_setting_id).size());
|
||||
VTR_ASSERT_SAFE(
|
||||
bitstream_setting.parent_pb_type_names(bitstream_interc_setting_id)
|
||||
.size() ==
|
||||
bitstream_setting.parent_mode_names(bitstream_interc_setting_id).size());
|
||||
|
||||
std::string hie_name;
|
||||
|
||||
for (size_t i = 0 ; i < bitstream_setting.parent_pb_type_names(bitstream_interc_setting_id).size(); ++i) {
|
||||
hie_name += bitstream_setting.parent_pb_type_names(bitstream_interc_setting_id)[i];
|
||||
for (size_t i = 0;
|
||||
i < bitstream_setting.parent_pb_type_names(bitstream_interc_setting_id)
|
||||
.size();
|
||||
++i) {
|
||||
hie_name +=
|
||||
bitstream_setting.parent_pb_type_names(bitstream_interc_setting_id)[i];
|
||||
hie_name += std::string("[");
|
||||
hie_name += bitstream_setting.parent_mode_names(bitstream_interc_setting_id)[i];
|
||||
hie_name +=
|
||||
bitstream_setting.parent_mode_names(bitstream_interc_setting_id)[i];
|
||||
hie_name += std::string("]");
|
||||
hie_name += std::string(".");
|
||||
}
|
||||
|
@ -67,71 +83,97 @@ std::string generate_bitstream_setting_interconnect_hierarchy_name(const openfpg
|
|||
/********************************************************************
|
||||
* A writer to output a bitstream pb_type setting to XML format
|
||||
*******************************************************************/
|
||||
static
|
||||
void write_xml_bitstream_pb_type_setting(std::fstream& fp,
|
||||
const char* fname,
|
||||
const openfpga::BitstreamSetting& bitstream_setting,
|
||||
const BitstreamPbTypeSettingId& bitstream_pb_type_setting_id) {
|
||||
static void write_xml_bitstream_pb_type_setting(
|
||||
std::fstream& fp, const char* fname,
|
||||
const openfpga::BitstreamSetting& bitstream_setting,
|
||||
const BitstreamPbTypeSettingId& bitstream_pb_type_setting_id) {
|
||||
/* Validate the file stream */
|
||||
openfpga::check_file_stream(fname, fp);
|
||||
|
||||
fp << "\t" << "<pb_type";
|
||||
fp << "\t"
|
||||
<< "<pb_type";
|
||||
|
||||
/* Generate the full hierarchy name of the pb_type */
|
||||
write_xml_attribute(fp, "name", generate_bitstream_setting_pb_type_hierarchy_name(bitstream_setting, bitstream_pb_type_setting_id).c_str());
|
||||
write_xml_attribute(fp, "name",
|
||||
generate_bitstream_setting_pb_type_hierarchy_name(
|
||||
bitstream_setting, bitstream_pb_type_setting_id)
|
||||
.c_str());
|
||||
|
||||
write_xml_attribute(fp, "source", bitstream_setting.pb_type_bitstream_source(bitstream_pb_type_setting_id).c_str());
|
||||
write_xml_attribute(fp, "content", bitstream_setting.pb_type_bitstream_content(bitstream_pb_type_setting_id).c_str());
|
||||
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));
|
||||
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";
|
||||
fp << "/>"
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* A writer to output a bitstream interconnect setting to XML format
|
||||
*******************************************************************/
|
||||
static
|
||||
void write_xml_bitstream_interconnect_setting(std::fstream& fp,
|
||||
const char* fname,
|
||||
const openfpga::BitstreamSetting& bitstream_setting,
|
||||
const BitstreamInterconnectSettingId& bitstream_interc_setting_id) {
|
||||
static void write_xml_bitstream_interconnect_setting(
|
||||
std::fstream& fp, const char* fname,
|
||||
const openfpga::BitstreamSetting& bitstream_setting,
|
||||
const BitstreamInterconnectSettingId& bitstream_interc_setting_id) {
|
||||
/* Validate the file stream */
|
||||
openfpga::check_file_stream(fname, fp);
|
||||
|
||||
fp << "\t" << "<pb_type";
|
||||
fp << "\t"
|
||||
<< "<pb_type";
|
||||
|
||||
/* Generate the full hierarchy name of the pb_type */
|
||||
write_xml_attribute(fp, "name", generate_bitstream_setting_interconnect_hierarchy_name(bitstream_setting, bitstream_interc_setting_id).c_str());
|
||||
write_xml_attribute(fp, "name",
|
||||
generate_bitstream_setting_interconnect_hierarchy_name(
|
||||
bitstream_setting, bitstream_interc_setting_id)
|
||||
.c_str());
|
||||
|
||||
write_xml_attribute(fp, "default_path", bitstream_setting.default_path(bitstream_interc_setting_id).c_str());
|
||||
write_xml_attribute(
|
||||
fp, "default_path",
|
||||
bitstream_setting.default_path(bitstream_interc_setting_id).c_str());
|
||||
|
||||
fp << "/>" << "\n";
|
||||
fp << "/>"
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* A writer to output a bitstream setting to XML format
|
||||
*******************************************************************/
|
||||
void write_xml_bitstream_setting(std::fstream& fp,
|
||||
const char* fname,
|
||||
const openfpga::BitstreamSetting& bitstream_setting) {
|
||||
void write_xml_bitstream_setting(
|
||||
std::fstream& fp, const char* fname,
|
||||
const openfpga::BitstreamSetting& bitstream_setting) {
|
||||
/* Validate the file stream */
|
||||
openfpga::check_file_stream(fname, fp);
|
||||
|
||||
/* Write the root node <openfpga_bitstream_setting>
|
||||
*/
|
||||
fp << "<openfpga_bitstream_setting>" << "\n";
|
||||
fp << "<openfpga_bitstream_setting>"
|
||||
<< "\n";
|
||||
|
||||
/* Write pb_type -related settings */
|
||||
for (const auto& bitstream_pb_type_setting_id : bitstream_setting.pb_type_settings()) {
|
||||
write_xml_bitstream_pb_type_setting(fp, fname, bitstream_setting, bitstream_pb_type_setting_id);
|
||||
/* Write pb_type -related settings */
|
||||
for (const auto& bitstream_pb_type_setting_id :
|
||||
bitstream_setting.pb_type_settings()) {
|
||||
write_xml_bitstream_pb_type_setting(fp, fname, bitstream_setting,
|
||||
bitstream_pb_type_setting_id);
|
||||
}
|
||||
|
||||
/* Write interconnect -related settings */
|
||||
for (const auto& bitstream_interc_setting_id : bitstream_setting.interconnect_settings()) {
|
||||
write_xml_bitstream_interconnect_setting(fp, fname, bitstream_setting, bitstream_interc_setting_id);
|
||||
/* Write interconnect -related settings */
|
||||
for (const auto& bitstream_interc_setting_id :
|
||||
bitstream_setting.interconnect_settings()) {
|
||||
write_xml_bitstream_interconnect_setting(fp, fname, bitstream_setting,
|
||||
bitstream_interc_setting_id);
|
||||
}
|
||||
|
||||
/* Write the root node <openfpga_bitstream_setting> */
|
||||
fp << "</openfpga_bitstream_setting>" << "\n";
|
||||
fp << "</openfpga_bitstream_setting>"
|
||||
<< "\n";
|
||||
}
|
||||
|
|
|
@ -5,13 +5,14 @@
|
|||
* Include header files that are required by function declaration
|
||||
*******************************************************************/
|
||||
#include <fstream>
|
||||
|
||||
#include "bitstream_setting.h"
|
||||
|
||||
/********************************************************************
|
||||
* Function declaration
|
||||
*******************************************************************/
|
||||
void write_xml_bitstream_setting(std::fstream& fp,
|
||||
const char* fname,
|
||||
const openfpga::BitstreamSetting& bitstream_setting);
|
||||
void write_xml_bitstream_setting(
|
||||
std::fstream& fp, const char* fname,
|
||||
const openfpga::BitstreamSetting& bitstream_setting);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -2,30 +2,31 @@
|
|||
* This file includes functions that outputs a circuit library to XML format
|
||||
*******************************************************************/
|
||||
/* Headers from system goes first */
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
/* Headers from vtr util library */
|
||||
#include "vtr_log.h"
|
||||
#include "openfpga_digest.h"
|
||||
#include "vtr_log.h"
|
||||
|
||||
/* Headers from readarchopenfpga library */
|
||||
#include "write_xml_utils.h"
|
||||
#include "write_xml_circuit_library.h"
|
||||
#include "write_xml_utils.h"
|
||||
|
||||
/********************************************************************
|
||||
* A writer to output the design technology of a circuit model to XML format
|
||||
*******************************************************************/
|
||||
static
|
||||
void write_xml_design_technology(std::fstream& fp,
|
||||
const char* fname,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
const CircuitModelId& model) {
|
||||
static void write_xml_design_technology(std::fstream& fp, const char* fname,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
const CircuitModelId& model) {
|
||||
/* Validate the file stream */
|
||||
openfpga::check_file_stream(fname, fp);
|
||||
|
||||
fp << "\t\t\t" << "<design_technology";
|
||||
write_xml_attribute(fp, "type", CIRCUIT_MODEL_DESIGN_TECH_TYPE_STRING[circuit_lib.design_tech_type(model)]);
|
||||
fp << "\t\t\t"
|
||||
<< "<design_technology";
|
||||
write_xml_attribute(
|
||||
fp, "type",
|
||||
CIRCUIT_MODEL_DESIGN_TECH_TYPE_STRING[circuit_lib.design_tech_type(model)]);
|
||||
|
||||
if (true == circuit_lib.is_power_gated(model)) {
|
||||
write_xml_attribute(fp, "power_gated", "true");
|
||||
|
@ -33,19 +34,33 @@ void write_xml_design_technology(std::fstream& fp,
|
|||
|
||||
/* Buffer-related information */
|
||||
if (CIRCUIT_MODEL_INVBUF == circuit_lib.model_type(model)) {
|
||||
write_xml_attribute(fp, "topology", CIRCUIT_MODEL_BUFFER_TYPE_STRING[circuit_lib.buffer_type(model)]);
|
||||
write_xml_attribute(fp, "size", std::to_string(circuit_lib.buffer_size(model)).c_str());
|
||||
write_xml_attribute(
|
||||
fp, "topology",
|
||||
CIRCUIT_MODEL_BUFFER_TYPE_STRING[circuit_lib.buffer_type(model)]);
|
||||
write_xml_attribute(fp, "size",
|
||||
std::to_string(circuit_lib.buffer_size(model)).c_str());
|
||||
if (1 < circuit_lib.buffer_num_levels(model)) {
|
||||
write_xml_attribute(fp, "num_level", std::to_string(circuit_lib.buffer_num_levels(model)).c_str());
|
||||
write_xml_attribute(fp, "f_per_stage", std::to_string(circuit_lib.buffer_f_per_stage(model)).c_str());
|
||||
write_xml_attribute(
|
||||
fp, "num_level",
|
||||
std::to_string(circuit_lib.buffer_num_levels(model)).c_str());
|
||||
write_xml_attribute(
|
||||
fp, "f_per_stage",
|
||||
std::to_string(circuit_lib.buffer_f_per_stage(model)).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
/* Pass-gate-logic -related information */
|
||||
if (CIRCUIT_MODEL_PASSGATE == circuit_lib.model_type(model)) {
|
||||
write_xml_attribute(fp, "topology", CIRCUIT_MODEL_PASSGATE_TYPE_STRING[circuit_lib.pass_gate_logic_type(model)]);
|
||||
write_xml_attribute(fp, "pmos_size", std::to_string(circuit_lib.pass_gate_logic_pmos_size(model)).c_str());
|
||||
write_xml_attribute(fp, "nmos_size", std::to_string(circuit_lib.pass_gate_logic_nmos_size(model)).c_str());
|
||||
write_xml_attribute(
|
||||
fp, "topology",
|
||||
CIRCUIT_MODEL_PASSGATE_TYPE_STRING[circuit_lib.pass_gate_logic_type(
|
||||
model)]);
|
||||
write_xml_attribute(
|
||||
fp, "pmos_size",
|
||||
std::to_string(circuit_lib.pass_gate_logic_pmos_size(model)).c_str());
|
||||
write_xml_attribute(
|
||||
fp, "nmos_size",
|
||||
std::to_string(circuit_lib.pass_gate_logic_nmos_size(model)).c_str());
|
||||
}
|
||||
|
||||
/* Look-Up Table (LUT)-related information */
|
||||
|
@ -57,68 +72,87 @@ void write_xml_design_technology(std::fstream& fp,
|
|||
|
||||
/* Multiplexer-related information */
|
||||
if (CIRCUIT_MODEL_MUX == circuit_lib.model_type(model)) {
|
||||
write_xml_attribute(fp, "structure", CIRCUIT_MODEL_STRUCTURE_TYPE_STRING[circuit_lib.mux_structure(model)]);
|
||||
write_xml_attribute(
|
||||
fp, "structure",
|
||||
CIRCUIT_MODEL_STRUCTURE_TYPE_STRING[circuit_lib.mux_structure(model)]);
|
||||
if (true == circuit_lib.mux_add_const_input(model)) {
|
||||
write_xml_attribute(fp, "add_const_input", "true");
|
||||
write_xml_attribute(fp, "const_input_val", std::to_string(circuit_lib.mux_const_input_value(model)).c_str());
|
||||
write_xml_attribute(fp, "add_const_input", "true");
|
||||
write_xml_attribute(
|
||||
fp, "const_input_val",
|
||||
std::to_string(circuit_lib.mux_const_input_value(model)).c_str());
|
||||
}
|
||||
if (CIRCUIT_MODEL_STRUCTURE_MULTILEVEL == circuit_lib.mux_structure(model)) {
|
||||
write_xml_attribute(fp, "num_level", std::to_string(circuit_lib.mux_num_levels(model)).c_str());
|
||||
if (CIRCUIT_MODEL_STRUCTURE_MULTILEVEL ==
|
||||
circuit_lib.mux_structure(model)) {
|
||||
write_xml_attribute(
|
||||
fp, "num_level",
|
||||
std::to_string(circuit_lib.mux_num_levels(model)).c_str());
|
||||
}
|
||||
if (true == circuit_lib.mux_use_advanced_rram_design(model)) {
|
||||
write_xml_attribute(fp, "advanced_rram_design", "true");
|
||||
write_xml_attribute(fp, "advanced_rram_design", "true");
|
||||
}
|
||||
if (true == circuit_lib.mux_use_local_encoder(model)) {
|
||||
write_xml_attribute(fp, "local_encoder", "true");
|
||||
write_xml_attribute(fp, "local_encoder", "true");
|
||||
}
|
||||
}
|
||||
|
||||
/* Gate-related information */
|
||||
if (CIRCUIT_MODEL_GATE == circuit_lib.model_type(model)) {
|
||||
write_xml_attribute(fp, "topology", CIRCUIT_MODEL_GATE_TYPE_STRING[circuit_lib.gate_type(model)]);
|
||||
write_xml_attribute(
|
||||
fp, "topology",
|
||||
CIRCUIT_MODEL_GATE_TYPE_STRING[circuit_lib.gate_type(model)]);
|
||||
}
|
||||
|
||||
|
||||
/* ReRAM-related information */
|
||||
if (CIRCUIT_MODEL_DESIGN_RRAM == circuit_lib.design_tech_type(model)) {
|
||||
write_xml_attribute(fp, "ron", std::to_string(circuit_lib.rram_rlrs(model)).c_str());
|
||||
write_xml_attribute(fp, "roff", std::to_string(circuit_lib.rram_rhrs(model)).c_str());
|
||||
write_xml_attribute(fp, "wprog_set_pmos", std::to_string(circuit_lib.rram_wprog_set_pmos(model)).c_str());
|
||||
write_xml_attribute(fp, "wprog_set_nmos", std::to_string(circuit_lib.rram_wprog_set_nmos(model)).c_str());
|
||||
write_xml_attribute(fp, "wprog_reset_pmos", std::to_string(circuit_lib.rram_wprog_reset_pmos(model)).c_str());
|
||||
write_xml_attribute(fp, "wprog_reset_nmos", std::to_string(circuit_lib.rram_wprog_reset_nmos(model)).c_str());
|
||||
write_xml_attribute(fp, "ron",
|
||||
std::to_string(circuit_lib.rram_rlrs(model)).c_str());
|
||||
write_xml_attribute(fp, "roff",
|
||||
std::to_string(circuit_lib.rram_rhrs(model)).c_str());
|
||||
write_xml_attribute(
|
||||
fp, "wprog_set_pmos",
|
||||
std::to_string(circuit_lib.rram_wprog_set_pmos(model)).c_str());
|
||||
write_xml_attribute(
|
||||
fp, "wprog_set_nmos",
|
||||
std::to_string(circuit_lib.rram_wprog_set_nmos(model)).c_str());
|
||||
write_xml_attribute(
|
||||
fp, "wprog_reset_pmos",
|
||||
std::to_string(circuit_lib.rram_wprog_reset_pmos(model)).c_str());
|
||||
write_xml_attribute(
|
||||
fp, "wprog_reset_nmos",
|
||||
std::to_string(circuit_lib.rram_wprog_reset_nmos(model)).c_str());
|
||||
}
|
||||
|
||||
/* Finish all the attributes, we can return here */
|
||||
fp << "/>" << "\n";
|
||||
fp << "/>"
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* A writer to output the device technology of a circuit model to XML format
|
||||
*******************************************************************/
|
||||
static
|
||||
void write_xml_device_technology(std::fstream& fp,
|
||||
const char* fname,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
const CircuitModelId& model) {
|
||||
static void write_xml_device_technology(std::fstream& fp, const char* fname,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
const CircuitModelId& model) {
|
||||
/* Validate the file stream */
|
||||
openfpga::check_file_stream(fname, fp);
|
||||
|
||||
|
||||
if (!circuit_lib.device_model_name(model).empty()) {
|
||||
fp << "\t\t\t" << "<device_technology";
|
||||
write_xml_attribute(fp, "device_model_name", circuit_lib.device_model_name(model).c_str());
|
||||
fp << "\t\t\t"
|
||||
<< "<device_technology";
|
||||
write_xml_attribute(fp, "device_model_name",
|
||||
circuit_lib.device_model_name(model).c_str());
|
||||
/* Finish all the attributes, we can return here */
|
||||
fp << "/>" << "\n";
|
||||
fp << "/>"
|
||||
<< "\n";
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* A writer to output a circuit port to XML format
|
||||
*******************************************************************/
|
||||
static
|
||||
void write_xml_circuit_port(std::fstream& fp,
|
||||
const char* fname,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
const CircuitPortId& port) {
|
||||
static void write_xml_circuit_port(std::fstream& fp, const char* fname,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
const CircuitPortId& port) {
|
||||
/* Validate the file stream */
|
||||
openfpga::check_file_stream(fname, fp);
|
||||
|
||||
|
@ -126,54 +160,63 @@ void write_xml_circuit_port(std::fstream& fp,
|
|||
const CircuitModelId& model = circuit_lib.port_parent_model(port);
|
||||
|
||||
/* Generic information about a port */
|
||||
fp << "\t\t\t" << "<port";
|
||||
write_xml_attribute(fp, "type", CIRCUIT_MODEL_PORT_TYPE_STRING[circuit_lib.port_type(port)]);
|
||||
write_xml_attribute(fp, "prefix", circuit_lib.port_prefix(port).c_str());
|
||||
|
||||
fp << "\t\t\t"
|
||||
<< "<port";
|
||||
write_xml_attribute(
|
||||
fp, "type", CIRCUIT_MODEL_PORT_TYPE_STRING[circuit_lib.port_type(port)]);
|
||||
write_xml_attribute(fp, "prefix", circuit_lib.port_prefix(port).c_str());
|
||||
|
||||
/* Output the lib_name when it is different than prefix */
|
||||
if (circuit_lib.port_prefix(port) != circuit_lib.port_lib_name(port)) {
|
||||
write_xml_attribute(fp, "lib_name", circuit_lib.port_lib_name(port).c_str());
|
||||
}
|
||||
write_xml_attribute(fp, "lib_name",
|
||||
circuit_lib.port_lib_name(port).c_str());
|
||||
}
|
||||
|
||||
write_xml_attribute(fp, "size", std::to_string(circuit_lib.port_size(port)).c_str());
|
||||
write_xml_attribute(fp, "size",
|
||||
std::to_string(circuit_lib.port_size(port)).c_str());
|
||||
|
||||
/* Output the default value only when this is a global port */
|
||||
if (true == circuit_lib.port_is_global(port)) {
|
||||
write_xml_attribute(fp, "default_val", std::to_string(circuit_lib.port_default_value(port)).c_str());
|
||||
write_xml_attribute(
|
||||
fp, "default_val",
|
||||
std::to_string(circuit_lib.port_default_value(port)).c_str());
|
||||
}
|
||||
|
||||
/* SRAM port may be for mode selection. Output it only when it is true */
|
||||
if (CIRCUIT_MODEL_PORT_SRAM == circuit_lib.port_type(port)) {
|
||||
if (true == circuit_lib.port_is_mode_select(port)) {
|
||||
write_xml_attribute(fp, "mode_select", "true");
|
||||
write_xml_attribute(fp, "mode_select", "true");
|
||||
}
|
||||
}
|
||||
|
||||
/* Output the tri-state map of the port
|
||||
/* Output the tri-state map of the port
|
||||
* This is only applicable to input ports of a LUT
|
||||
*/
|
||||
if ( (CIRCUIT_MODEL_LUT == circuit_lib.model_type(model))
|
||||
&& (CIRCUIT_MODEL_PORT_INPUT == circuit_lib.port_type(port)) ) {
|
||||
if ((CIRCUIT_MODEL_LUT == circuit_lib.model_type(model)) &&
|
||||
(CIRCUIT_MODEL_PORT_INPUT == circuit_lib.port_type(port))) {
|
||||
if (!circuit_lib.port_tri_state_map(port).empty()) {
|
||||
write_xml_attribute(fp, "tri_state_map", circuit_lib.port_tri_state_map(port).c_str());
|
||||
write_xml_attribute(fp, "tri_state_map",
|
||||
circuit_lib.port_tri_state_map(port).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
/* Identify the fracturable-level of the port in LUTs, by default it will be -1
|
||||
* This is only applicable to output ports of a LUT
|
||||
/* Identify the fracturable-level of the port in LUTs, by default it will be
|
||||
* -1 This is only applicable to output ports of a LUT
|
||||
*/
|
||||
if ( (CIRCUIT_MODEL_LUT == circuit_lib.model_type(model))
|
||||
&& (CIRCUIT_MODEL_PORT_OUTPUT == circuit_lib.port_type(port)) ) {
|
||||
if ((CIRCUIT_MODEL_LUT == circuit_lib.model_type(model)) &&
|
||||
(CIRCUIT_MODEL_PORT_OUTPUT == circuit_lib.port_type(port))) {
|
||||
if (size_t(-1) != circuit_lib.port_lut_frac_level(port)) {
|
||||
write_xml_attribute(fp, "lut_frac_level", std::to_string(circuit_lib.port_lut_frac_level(port)).c_str());
|
||||
write_xml_attribute(
|
||||
fp, "lut_frac_level",
|
||||
std::to_string(circuit_lib.port_lut_frac_level(port)).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
/* Output the output mask of the port
|
||||
/* Output the output mask of the port
|
||||
* This is only applicable to output ports of a LUT
|
||||
*/
|
||||
if ( (CIRCUIT_MODEL_LUT == circuit_lib.model_type(model))
|
||||
&& (CIRCUIT_MODEL_PORT_OUTPUT == circuit_lib.port_type(port)) ) {
|
||||
if ((CIRCUIT_MODEL_LUT == circuit_lib.model_type(model)) &&
|
||||
(CIRCUIT_MODEL_PORT_OUTPUT == circuit_lib.port_type(port))) {
|
||||
std::string output_mask_string;
|
||||
for (const size_t& mask : circuit_lib.port_lut_output_mask(port)) {
|
||||
if (!output_mask_string.empty()) {
|
||||
|
@ -182,103 +225,107 @@ void write_xml_circuit_port(std::fstream& fp,
|
|||
output_mask_string += std::to_string(mask);
|
||||
}
|
||||
if (!output_mask_string.empty()) {
|
||||
write_xml_attribute(fp, "lut_output_mask", output_mask_string.c_str());
|
||||
write_xml_attribute(fp, "lut_output_mask", output_mask_string.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
/* LUT harden port attributes */
|
||||
if (CIRCUIT_MODEL_LUT == circuit_lib.model_type(model)) {
|
||||
if (true == circuit_lib.port_is_harden_lut_port(port)) {
|
||||
write_xml_attribute(fp, "is_harden_lut_port", "true");
|
||||
write_xml_attribute(fp, "is_harden_lut_port", "true");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* I/O port attributes */
|
||||
if (true == circuit_lib.port_is_io(port)) {
|
||||
write_xml_attribute(fp, "is_io", "true");
|
||||
write_xml_attribute(fp, "is_io", "true");
|
||||
}
|
||||
|
||||
if (true == circuit_lib.port_is_data_io(port)) {
|
||||
write_xml_attribute(fp, "is_data_io", "true");
|
||||
write_xml_attribute(fp, "is_data_io", "true");
|
||||
}
|
||||
|
||||
/* Global, reset, set port attributes */
|
||||
if (true == circuit_lib.port_is_global(port)) {
|
||||
write_xml_attribute(fp, "is_global", "true");
|
||||
write_xml_attribute(fp, "is_global", "true");
|
||||
}
|
||||
|
||||
if (true == circuit_lib.port_is_reset(port)) {
|
||||
write_xml_attribute(fp, "is_reset", "true");
|
||||
write_xml_attribute(fp, "is_reset", "true");
|
||||
}
|
||||
|
||||
if (true == circuit_lib.port_is_set(port)) {
|
||||
write_xml_attribute(fp, "is_set", "true");
|
||||
write_xml_attribute(fp, "is_set", "true");
|
||||
}
|
||||
|
||||
if (true == circuit_lib.port_is_prog(port)) {
|
||||
write_xml_attribute(fp, "is_prog", "true");
|
||||
write_xml_attribute(fp, "is_prog", "true");
|
||||
}
|
||||
|
||||
if (true == circuit_lib.port_is_shift_register(port)) {
|
||||
write_xml_attribute(fp, "is_shift_register", "true");
|
||||
write_xml_attribute(fp, "is_shift_register", "true");
|
||||
}
|
||||
|
||||
if (true == circuit_lib.port_is_config_enable(port)) {
|
||||
write_xml_attribute(fp, "is_config_enable", "true");
|
||||
write_xml_attribute(fp, "is_config_enable", "true");
|
||||
}
|
||||
|
||||
/* Output the name of circuit model that this port is linked to */
|
||||
if (!circuit_lib.port_tri_state_model_name(port).empty()) {
|
||||
write_xml_attribute(fp, "circuit_model_name", circuit_lib.port_tri_state_model_name(port).c_str());
|
||||
write_xml_attribute(fp, "circuit_model_name",
|
||||
circuit_lib.port_tri_state_model_name(port).c_str());
|
||||
}
|
||||
|
||||
/* Find the name of circuit model that port is used for inversion of signals,
|
||||
* This is only applicable to BL/WL/BLB/WLB ports
|
||||
*/
|
||||
if ( (CIRCUIT_MODEL_PORT_BL == circuit_lib.port_type(port))
|
||||
|| (CIRCUIT_MODEL_PORT_WL == circuit_lib.port_type(port))
|
||||
|| (CIRCUIT_MODEL_PORT_BLB == circuit_lib.port_type(port))
|
||||
|| (CIRCUIT_MODEL_PORT_WLB == circuit_lib.port_type(port)) ) {
|
||||
if ((CIRCUIT_MODEL_PORT_BL == circuit_lib.port_type(port)) ||
|
||||
(CIRCUIT_MODEL_PORT_WL == circuit_lib.port_type(port)) ||
|
||||
(CIRCUIT_MODEL_PORT_BLB == circuit_lib.port_type(port)) ||
|
||||
(CIRCUIT_MODEL_PORT_WLB == circuit_lib.port_type(port))) {
|
||||
if (!circuit_lib.port_inv_model_name(port).empty()) {
|
||||
write_xml_attribute(fp, "inv_circuit_model_name", circuit_lib.port_inv_model_name(port).c_str());
|
||||
write_xml_attribute(fp, "inv_circuit_model_name",
|
||||
circuit_lib.port_inv_model_name(port).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
/* Finish all the attributes, we can return here */
|
||||
fp << "/>" << "\n";
|
||||
fp << "/>"
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* A writer to output wire parasitics of a circuit model to XML format
|
||||
*******************************************************************/
|
||||
static
|
||||
void write_xml_wire_param(std::fstream& fp,
|
||||
const char* fname,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
const CircuitModelId& model) {
|
||||
static void write_xml_wire_param(std::fstream& fp, const char* fname,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
const CircuitModelId& model) {
|
||||
/* Validate the file stream */
|
||||
openfpga::check_file_stream(fname, fp);
|
||||
|
||||
fp << "\t\t\t" << "<wire_param";
|
||||
fp << "\t\t\t"
|
||||
<< "<wire_param";
|
||||
|
||||
write_xml_attribute(fp, "model_type", WIRE_MODEL_TYPE_STRING[circuit_lib.wire_type(model)]);
|
||||
write_xml_attribute(fp, "R", std::to_string(circuit_lib.wire_r(model)).c_str());
|
||||
write_xml_attribute(fp, "C", std::to_string(circuit_lib.wire_c(model)).c_str());
|
||||
write_xml_attribute(fp, "num_level", std::to_string(circuit_lib.wire_num_level(model)).c_str());
|
||||
write_xml_attribute(fp, "model_type",
|
||||
WIRE_MODEL_TYPE_STRING[circuit_lib.wire_type(model)]);
|
||||
write_xml_attribute(fp, "R",
|
||||
std::to_string(circuit_lib.wire_r(model)).c_str());
|
||||
write_xml_attribute(fp, "C",
|
||||
std::to_string(circuit_lib.wire_c(model)).c_str());
|
||||
write_xml_attribute(
|
||||
fp, "num_level", std::to_string(circuit_lib.wire_num_level(model)).c_str());
|
||||
|
||||
/* Finish all the attributes, we can return here */
|
||||
fp << "/>" << "\n";
|
||||
fp << "/>"
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* A writer to output delay matrices of a circuit model to XML format
|
||||
*******************************************************************/
|
||||
static
|
||||
void write_xml_delay_matrix(std::fstream& fp,
|
||||
const char* fname,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
const CircuitModelId& model) {
|
||||
static void write_xml_delay_matrix(std::fstream& fp, const char* fname,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
const CircuitModelId& model) {
|
||||
/* Validate the file stream */
|
||||
openfpga::check_file_stream(fname, fp);
|
||||
|
||||
|
@ -286,17 +333,19 @@ void write_xml_delay_matrix(std::fstream& fp,
|
|||
std::vector<CircuitPortId> out_ports;
|
||||
/* Collect the input ports and output ports */
|
||||
for (const auto& timing_edge : circuit_lib.timing_edges_by_model(model)) {
|
||||
/* For each input port of each edge, build a list of unique ports */
|
||||
CircuitPortId src_port = circuit_lib.timing_edge_src_port(timing_edge);
|
||||
if (in_ports.end() == std::find(in_ports.begin(), in_ports.end(), src_port)) {
|
||||
in_ports.push_back(src_port);
|
||||
}
|
||||
/* For each input port of each edge, build a list of unique ports */
|
||||
CircuitPortId src_port = circuit_lib.timing_edge_src_port(timing_edge);
|
||||
if (in_ports.end() ==
|
||||
std::find(in_ports.begin(), in_ports.end(), src_port)) {
|
||||
in_ports.push_back(src_port);
|
||||
}
|
||||
|
||||
/* For each input port of each edge, build a list of unique ports */
|
||||
CircuitPortId sink_port = circuit_lib.timing_edge_sink_port(timing_edge);
|
||||
if (out_ports.end() == std::find(out_ports.begin(), out_ports.end(), sink_port)) {
|
||||
out_ports.push_back(sink_port);
|
||||
}
|
||||
/* For each input port of each edge, build a list of unique ports */
|
||||
CircuitPortId sink_port = circuit_lib.timing_edge_sink_port(timing_edge);
|
||||
if (out_ports.end() ==
|
||||
std::find(out_ports.begin(), out_ports.end(), sink_port)) {
|
||||
out_ports.push_back(sink_port);
|
||||
}
|
||||
}
|
||||
|
||||
/* Build the string of in_port list */
|
||||
|
@ -306,7 +355,7 @@ void write_xml_delay_matrix(std::fstream& fp,
|
|||
in_port_string += std::string(" ");
|
||||
}
|
||||
in_port_string += circuit_lib.port_prefix(in_port);
|
||||
}
|
||||
}
|
||||
|
||||
/* Build the string of out_port list */
|
||||
std::string out_port_string;
|
||||
|
@ -315,41 +364,45 @@ void write_xml_delay_matrix(std::fstream& fp,
|
|||
out_port_string += std::string(" ");
|
||||
}
|
||||
out_port_string += circuit_lib.port_prefix(out_port);
|
||||
}
|
||||
}
|
||||
|
||||
/* Output rising edges */
|
||||
fp << "\t\t\t";
|
||||
fp << "<delay_matrix";
|
||||
write_xml_attribute(fp, "type", CIRCUIT_MODEL_DELAY_TYPE_STRING[CIRCUIT_MODEL_DELAY_RISE]);
|
||||
write_xml_attribute(fp, "in_port", in_port_string.c_str());
|
||||
write_xml_attribute(fp, "out_port", out_port_string.c_str());
|
||||
write_xml_attribute(
|
||||
fp, "type", CIRCUIT_MODEL_DELAY_TYPE_STRING[CIRCUIT_MODEL_DELAY_RISE]);
|
||||
write_xml_attribute(fp, "in_port", in_port_string.c_str());
|
||||
write_xml_attribute(fp, "out_port", out_port_string.c_str());
|
||||
fp << ">\n";
|
||||
|
||||
|
||||
for (const CircuitPortId& out_port : out_ports) {
|
||||
for (const size_t& out_pin : circuit_lib.pins(out_port)) {
|
||||
fp << "\t\t\t\t";
|
||||
size_t counter = 0; /* Count the numbers of delays in one line */
|
||||
size_t counter = 0; /* Count the numbers of delays in one line */
|
||||
for (const CircuitPortId& in_port : in_ports) {
|
||||
for (const size_t& in_pin : circuit_lib.pins(in_port)) {
|
||||
for (const auto& timing_edge : circuit_lib.timing_edges_by_model(model)) {
|
||||
CircuitPortId src_port = circuit_lib.timing_edge_src_port(timing_edge);
|
||||
for (const auto& timing_edge :
|
||||
circuit_lib.timing_edges_by_model(model)) {
|
||||
CircuitPortId src_port =
|
||||
circuit_lib.timing_edge_src_port(timing_edge);
|
||||
size_t src_pin = circuit_lib.timing_edge_src_pin(timing_edge);
|
||||
|
||||
CircuitPortId sink_port = circuit_lib.timing_edge_sink_port(timing_edge);
|
||||
CircuitPortId sink_port =
|
||||
circuit_lib.timing_edge_sink_port(timing_edge);
|
||||
size_t sink_pin = circuit_lib.timing_edge_sink_pin(timing_edge);
|
||||
|
||||
/* Bypass unwanted edges */
|
||||
if ( (src_port != in_port)
|
||||
|| (src_pin != in_pin)
|
||||
|| (sink_port != out_port)
|
||||
|| (sink_pin != out_pin) ) {
|
||||
if ((src_port != in_port) || (src_pin != in_pin) ||
|
||||
(sink_port != out_port) || (sink_pin != out_pin)) {
|
||||
continue;
|
||||
}
|
||||
/* This is the edge we want, output the rise delay */
|
||||
if (0 < counter) {
|
||||
fp << std::string(" ");
|
||||
}
|
||||
fp << std::scientific << circuit_lib.timing_edge_delay(timing_edge, CIRCUIT_MODEL_DELAY_RISE);
|
||||
fp << std::scientific
|
||||
<< circuit_lib.timing_edge_delay(timing_edge,
|
||||
CIRCUIT_MODEL_DELAY_RISE);
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
|
@ -360,41 +413,46 @@ void write_xml_delay_matrix(std::fstream& fp,
|
|||
}
|
||||
|
||||
fp << "\t\t\t";
|
||||
fp << "</delay_matrix>" << "\n";
|
||||
fp << "</delay_matrix>"
|
||||
<< "\n";
|
||||
|
||||
/* Output falling edges */
|
||||
fp << "\t\t\t";
|
||||
fp << "<delay_matrix";
|
||||
write_xml_attribute(fp, "type", CIRCUIT_MODEL_DELAY_TYPE_STRING[CIRCUIT_MODEL_DELAY_FALL]);
|
||||
write_xml_attribute(fp, "in_port", in_port_string.c_str());
|
||||
write_xml_attribute(fp, "out_port", out_port_string.c_str());
|
||||
write_xml_attribute(
|
||||
fp, "type", CIRCUIT_MODEL_DELAY_TYPE_STRING[CIRCUIT_MODEL_DELAY_FALL]);
|
||||
write_xml_attribute(fp, "in_port", in_port_string.c_str());
|
||||
write_xml_attribute(fp, "out_port", out_port_string.c_str());
|
||||
fp << ">\n";
|
||||
|
||||
|
||||
for (const CircuitPortId& out_port : out_ports) {
|
||||
for (const size_t& out_pin : circuit_lib.pins(out_port)) {
|
||||
fp << "\t\t\t\t";
|
||||
size_t counter = 0; /* Count the numbers of delays in one line */
|
||||
size_t counter = 0; /* Count the numbers of delays in one line */
|
||||
for (const CircuitPortId& in_port : in_ports) {
|
||||
for (const size_t& in_pin : circuit_lib.pins(in_port)) {
|
||||
for (const auto& timing_edge : circuit_lib.timing_edges_by_model(model)) {
|
||||
CircuitPortId src_port = circuit_lib.timing_edge_src_port(timing_edge);
|
||||
for (const auto& timing_edge :
|
||||
circuit_lib.timing_edges_by_model(model)) {
|
||||
CircuitPortId src_port =
|
||||
circuit_lib.timing_edge_src_port(timing_edge);
|
||||
size_t src_pin = circuit_lib.timing_edge_src_pin(timing_edge);
|
||||
|
||||
CircuitPortId sink_port = circuit_lib.timing_edge_sink_port(timing_edge);
|
||||
CircuitPortId sink_port =
|
||||
circuit_lib.timing_edge_sink_port(timing_edge);
|
||||
size_t sink_pin = circuit_lib.timing_edge_sink_pin(timing_edge);
|
||||
|
||||
/* Bypass unwanted edges */
|
||||
if ( (src_port != in_port)
|
||||
|| (src_pin != in_pin)
|
||||
|| (sink_port != out_port)
|
||||
|| (sink_pin != out_pin) ) {
|
||||
if ((src_port != in_port) || (src_pin != in_pin) ||
|
||||
(sink_port != out_port) || (sink_pin != out_pin)) {
|
||||
continue;
|
||||
}
|
||||
/* This is the edge we want, output the rise delay */
|
||||
if (0 < counter) {
|
||||
fp << std::string(" ");
|
||||
}
|
||||
fp << std::scientific << circuit_lib.timing_edge_delay(timing_edge, CIRCUIT_MODEL_DELAY_FALL);
|
||||
fp << std::scientific
|
||||
<< circuit_lib.timing_edge_delay(timing_edge,
|
||||
CIRCUIT_MODEL_DELAY_FALL);
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
|
@ -405,38 +463,42 @@ void write_xml_delay_matrix(std::fstream& fp,
|
|||
}
|
||||
|
||||
fp << "\t\t\t";
|
||||
fp << "</delay_matrix>" << "\n";
|
||||
fp << "</delay_matrix>"
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* A writer to output a circuit model to XML format
|
||||
*******************************************************************/
|
||||
static
|
||||
void write_xml_circuit_model(std::fstream& fp,
|
||||
const char* fname,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
const CircuitModelId& model) {
|
||||
static void write_xml_circuit_model(std::fstream& fp, const char* fname,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
const CircuitModelId& model) {
|
||||
/* Validate the file stream */
|
||||
openfpga::check_file_stream(fname, fp);
|
||||
|
||||
/* Write the definition of circuit model */
|
||||
fp << "\t\t" << "<circuit_model";
|
||||
write_xml_attribute(fp, "type", CIRCUIT_MODEL_TYPE_STRING[circuit_lib.model_type(model)]);
|
||||
write_xml_attribute(fp, "name", circuit_lib.model_name(model).c_str());
|
||||
write_xml_attribute(fp, "prefix", circuit_lib.model_prefix(model).c_str());
|
||||
if (true == circuit_lib.model_is_default(model)) {
|
||||
write_xml_attribute(fp, "is_default", "true");
|
||||
fp << "\t\t"
|
||||
<< "<circuit_model";
|
||||
write_xml_attribute(fp, "type",
|
||||
CIRCUIT_MODEL_TYPE_STRING[circuit_lib.model_type(model)]);
|
||||
write_xml_attribute(fp, "name", circuit_lib.model_name(model).c_str());
|
||||
write_xml_attribute(fp, "prefix", circuit_lib.model_prefix(model).c_str());
|
||||
if (true == circuit_lib.model_is_default(model)) {
|
||||
write_xml_attribute(fp, "is_default", "true");
|
||||
}
|
||||
if (true == circuit_lib.dump_structural_verilog(model)) {
|
||||
write_xml_attribute(fp, "dump_structural_verilog", "true");
|
||||
if (true == circuit_lib.dump_structural_verilog(model)) {
|
||||
write_xml_attribute(fp, "dump_structural_verilog", "true");
|
||||
}
|
||||
if (!circuit_lib.model_spice_netlist(model).empty()) {
|
||||
write_xml_attribute(fp, "spice_netlist", circuit_lib.model_spice_netlist(model).c_str());
|
||||
write_xml_attribute(fp, "spice_netlist",
|
||||
circuit_lib.model_spice_netlist(model).c_str());
|
||||
}
|
||||
if (!circuit_lib.model_verilog_netlist(model).empty()) {
|
||||
write_xml_attribute(fp, "verilog_netlist", circuit_lib.model_verilog_netlist(model).c_str());
|
||||
write_xml_attribute(fp, "verilog_netlist",
|
||||
circuit_lib.model_verilog_netlist(model).c_str());
|
||||
}
|
||||
fp << ">" << "\n";
|
||||
fp << ">"
|
||||
<< "\n";
|
||||
|
||||
/* Write the design technology of circuit model */
|
||||
write_xml_design_technology(fp, fname, circuit_lib, model);
|
||||
|
@ -444,63 +506,93 @@ void write_xml_circuit_model(std::fstream& fp,
|
|||
/* Write the device technology of circuit model */
|
||||
write_xml_device_technology(fp, fname, circuit_lib, model);
|
||||
|
||||
/* Write the input buffer information of circuit model,
|
||||
/* Write the input buffer information of circuit model,
|
||||
* only applicable when this circuit model is neither inverter nor buffer
|
||||
*/
|
||||
if (CIRCUIT_MODEL_INVBUF != circuit_lib.model_type(model)) {
|
||||
if (true == circuit_lib.is_input_buffered(model)) {
|
||||
fp << "\t\t\t" << "<input_buffer";
|
||||
write_xml_attribute(fp, "exist", circuit_lib.is_input_buffered(model));
|
||||
write_xml_attribute(fp, "circuit_model_name", circuit_lib.model_name(circuit_lib.input_buffer_model(model)).c_str());
|
||||
fp << "/>" << "\n";
|
||||
fp << "\t\t\t"
|
||||
<< "<input_buffer";
|
||||
write_xml_attribute(fp, "exist", circuit_lib.is_input_buffered(model));
|
||||
write_xml_attribute(
|
||||
fp, "circuit_model_name",
|
||||
circuit_lib.model_name(circuit_lib.input_buffer_model(model)).c_str());
|
||||
fp << "/>"
|
||||
<< "\n";
|
||||
}
|
||||
}
|
||||
|
||||
/* Write the output buffer information of circuit model */
|
||||
if (CIRCUIT_MODEL_INVBUF != circuit_lib.model_type(model)) {
|
||||
if (true == circuit_lib.is_output_buffered(model)) {
|
||||
fp << "\t\t\t" << "<output_buffer";
|
||||
write_xml_attribute(fp, "exist", circuit_lib.is_input_buffered(model));
|
||||
write_xml_attribute(fp, "circuit_model_name", circuit_lib.model_name(circuit_lib.output_buffer_model(model)).c_str());
|
||||
fp << "/>" << "\n";
|
||||
fp << "\t\t\t"
|
||||
<< "<output_buffer";
|
||||
write_xml_attribute(fp, "exist", circuit_lib.is_input_buffered(model));
|
||||
write_xml_attribute(
|
||||
fp, "circuit_model_name",
|
||||
circuit_lib.model_name(circuit_lib.output_buffer_model(model)).c_str());
|
||||
fp << "/>"
|
||||
<< "\n";
|
||||
}
|
||||
}
|
||||
|
||||
if (CIRCUIT_MODEL_LUT == circuit_lib.model_type(model)) {
|
||||
/* Write the lut input buffer information of circuit model
|
||||
* This is a mandatory attribute for LUT, so it must exist
|
||||
* This is a mandatory attribute for LUT, so it must exist
|
||||
*/
|
||||
fp << "\t\t\t" << "<lut_input_buffer";
|
||||
write_xml_attribute(fp, "exist", true);
|
||||
write_xml_attribute(fp, "circuit_model_name", circuit_lib.model_name(circuit_lib.lut_input_buffer_model(model)).c_str());
|
||||
fp << "/>" << "\n";
|
||||
fp << "\t\t\t"
|
||||
<< "<lut_input_buffer";
|
||||
write_xml_attribute(fp, "exist", true);
|
||||
write_xml_attribute(
|
||||
fp, "circuit_model_name",
|
||||
circuit_lib.model_name(circuit_lib.lut_input_buffer_model(model))
|
||||
.c_str());
|
||||
fp << "/>"
|
||||
<< "\n";
|
||||
|
||||
/* Write the lut input inverter information of circuit model
|
||||
* This is a mandatory attribute for LUT, so it must exist
|
||||
* This is a mandatory attribute for LUT, so it must exist
|
||||
*/
|
||||
fp << "\t\t\t" << "<lut_input_inverter";
|
||||
write_xml_attribute(fp, "exist", true);
|
||||
write_xml_attribute(fp, "circuit_model_name", circuit_lib.model_name(circuit_lib.lut_input_inverter_model(model)).c_str());
|
||||
fp << "/>" << "\n";
|
||||
fp << "\t\t\t"
|
||||
<< "<lut_input_inverter";
|
||||
write_xml_attribute(fp, "exist", true);
|
||||
write_xml_attribute(
|
||||
fp, "circuit_model_name",
|
||||
circuit_lib.model_name(circuit_lib.lut_input_inverter_model(model))
|
||||
.c_str());
|
||||
fp << "/>"
|
||||
<< "\n";
|
||||
|
||||
/* Write the lut intermediate buffer information of circuit model */
|
||||
if (true == circuit_lib.is_lut_intermediate_buffered(model)) {
|
||||
fp << "\t\t\t" << "<lut_intermediate_buffer";
|
||||
write_xml_attribute(fp, "exist", circuit_lib.is_lut_intermediate_buffered(model));
|
||||
write_xml_attribute(fp, "circuit_model_name", circuit_lib.model_name(circuit_lib.lut_intermediate_buffer_model(model)).c_str());
|
||||
fp << "\t\t\t"
|
||||
<< "<lut_intermediate_buffer";
|
||||
write_xml_attribute(fp, "exist",
|
||||
circuit_lib.is_lut_intermediate_buffered(model));
|
||||
write_xml_attribute(
|
||||
fp, "circuit_model_name",
|
||||
circuit_lib.model_name(circuit_lib.lut_intermediate_buffer_model(model))
|
||||
.c_str());
|
||||
if (!circuit_lib.lut_intermediate_buffer_location_map(model).empty()) {
|
||||
write_xml_attribute(fp, "location_map", circuit_lib.lut_intermediate_buffer_location_map(model).c_str());
|
||||
write_xml_attribute(
|
||||
fp, "location_map",
|
||||
circuit_lib.lut_intermediate_buffer_location_map(model).c_str());
|
||||
}
|
||||
fp << "/>" << "\n";
|
||||
fp << "/>"
|
||||
<< "\n";
|
||||
}
|
||||
}
|
||||
|
||||
/* Write the pass-gate-logic information of circuit model */
|
||||
if ( (CIRCUIT_MODEL_LUT == circuit_lib.model_type(model))
|
||||
|| (CIRCUIT_MODEL_MUX == circuit_lib.model_type(model)) ) {
|
||||
fp << "\t\t\t" << "<pass_gate_logic";
|
||||
write_xml_attribute(fp, "circuit_model_name", circuit_lib.model_name(circuit_lib.pass_gate_logic_model(model)).c_str());
|
||||
fp << "/>" << "\n";
|
||||
if ((CIRCUIT_MODEL_LUT == circuit_lib.model_type(model)) ||
|
||||
(CIRCUIT_MODEL_MUX == circuit_lib.model_type(model))) {
|
||||
fp << "\t\t\t"
|
||||
<< "<pass_gate_logic";
|
||||
write_xml_attribute(
|
||||
fp, "circuit_model_name",
|
||||
circuit_lib.model_name(circuit_lib.pass_gate_logic_model(model)).c_str());
|
||||
fp << "/>"
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
/* Write the ports of circuit model */
|
||||
|
@ -509,47 +601,51 @@ void write_xml_circuit_model(std::fstream& fp,
|
|||
}
|
||||
|
||||
/* Write the wire parasticis of circuit model */
|
||||
if ( (CIRCUIT_MODEL_WIRE == circuit_lib.model_type(model))
|
||||
|| (CIRCUIT_MODEL_CHAN_WIRE == circuit_lib.model_type(model)) ) {
|
||||
if ((CIRCUIT_MODEL_WIRE == circuit_lib.model_type(model)) ||
|
||||
(CIRCUIT_MODEL_CHAN_WIRE == circuit_lib.model_type(model))) {
|
||||
write_xml_wire_param(fp, fname, circuit_lib, model);
|
||||
}
|
||||
|
||||
/* Write the delay matrix of circuit model
|
||||
* Skip circuit models without delay matrices
|
||||
* Skip circuit models without delay matrices
|
||||
*/
|
||||
if (0 < circuit_lib.num_delay_info(model)) {
|
||||
write_xml_delay_matrix(fp, fname, circuit_lib, model);
|
||||
}
|
||||
|
||||
/* Put an end to the XML definition of this circuit model */
|
||||
fp << "\t\t" << "</circuit_model>\n";
|
||||
fp << "\t\t"
|
||||
<< "</circuit_model>\n";
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* A writer to output a circuit library to XML format
|
||||
* Note:
|
||||
* This function should be run after that the following methods of
|
||||
* CircuitLibrary are executed
|
||||
* Note:
|
||||
* This function should be run after that the following methods of
|
||||
* CircuitLibrary are executed
|
||||
* 1. build_model_links();
|
||||
* 2. build_timing_graph();
|
||||
*******************************************************************/
|
||||
void write_xml_circuit_library(std::fstream& fp,
|
||||
const char* fname,
|
||||
void write_xml_circuit_library(std::fstream& fp, const char* fname,
|
||||
const CircuitLibrary& circuit_lib) {
|
||||
/* Validate the file stream */
|
||||
openfpga::check_file_stream(fname, fp);
|
||||
|
||||
/* Write the root node for circuit_library,
|
||||
* we apply a tab becuase circuit library is a subnode
|
||||
|
||||
/* Write the root node for circuit_library,
|
||||
* we apply a tab becuase circuit library is a subnode
|
||||
* under the root node <openfpga_arch>
|
||||
*/
|
||||
fp << "\t" << "<circuit_library>" << "\n";
|
||||
fp << "\t"
|
||||
<< "<circuit_library>"
|
||||
<< "\n";
|
||||
|
||||
/* Write circuit model one by one */
|
||||
/* Write circuit model one by one */
|
||||
for (const CircuitModelId& model : circuit_lib.models()) {
|
||||
write_xml_circuit_model(fp, fname, circuit_lib, model);
|
||||
}
|
||||
}
|
||||
|
||||
/* Write the root node for circuit_library */
|
||||
fp << "\t" << "</circuit_library>" << "\n";
|
||||
fp << "\t"
|
||||
<< "</circuit_library>"
|
||||
<< "\n";
|
||||
}
|
||||
|
|
|
@ -5,13 +5,13 @@
|
|||
* Include header files that are required by function declaration
|
||||
*******************************************************************/
|
||||
#include <fstream>
|
||||
|
||||
#include "circuit_library.h"
|
||||
|
||||
/********************************************************************
|
||||
* Function declaration
|
||||
*******************************************************************/
|
||||
void write_xml_circuit_library(std::fstream& fp,
|
||||
const char* fname,
|
||||
void write_xml_circuit_library(std::fstream& fp, const char* fname,
|
||||
const CircuitLibrary& circuit_lib);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,49 +1,67 @@
|
|||
/********************************************************************
|
||||
* This file includes functions that outputs a configuration protocol to XML format
|
||||
* This file includes functions that outputs a configuration protocol to XML
|
||||
*format
|
||||
*******************************************************************/
|
||||
/* Headers from system goes first */
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
/* Headers from vtr util library */
|
||||
#include "openfpga_digest.h"
|
||||
#include "vtr_assert.h"
|
||||
#include "vtr_log.h"
|
||||
#include "openfpga_digest.h"
|
||||
|
||||
/* Headers from readarchopenfpga library */
|
||||
#include "write_xml_utils.h"
|
||||
#include "write_xml_config_protocol.h"
|
||||
#include "write_xml_utils.h"
|
||||
|
||||
/********************************************************************
|
||||
* A writer to output a configuration memory organization to XML format
|
||||
*******************************************************************/
|
||||
static
|
||||
void write_xml_config_organization(std::fstream& fp,
|
||||
const char* fname,
|
||||
const ConfigProtocol& config_protocol,
|
||||
const CircuitLibrary& circuit_lib) {
|
||||
static void write_xml_config_organization(std::fstream& fp, const char* fname,
|
||||
const ConfigProtocol& config_protocol,
|
||||
const CircuitLibrary& circuit_lib) {
|
||||
/* Validate the file stream */
|
||||
openfpga::check_file_stream(fname, fp);
|
||||
|
||||
fp << "\t\t" << "<organization";
|
||||
write_xml_attribute(fp, "type", CONFIG_PROTOCOL_TYPE_STRING[config_protocol.type()]);
|
||||
write_xml_attribute(fp, "circuit_model_name", circuit_lib.model_name(config_protocol.memory_model()).c_str());
|
||||
fp << "/>" << "\n";
|
||||
fp << "\t\t"
|
||||
<< "<organization";
|
||||
write_xml_attribute(fp, "type",
|
||||
CONFIG_PROTOCOL_TYPE_STRING[config_protocol.type()]);
|
||||
write_xml_attribute(
|
||||
fp, "circuit_model_name",
|
||||
circuit_lib.model_name(config_protocol.memory_model()).c_str());
|
||||
fp << "/>"
|
||||
<< "\n";
|
||||
|
||||
/* Output BL/WL protocols */
|
||||
fp << "\t\t\t" << "<bl";
|
||||
write_xml_attribute(fp, "protocol", BLWL_PROTOCOL_TYPE_STRING[config_protocol.bl_protocol_type()]);
|
||||
write_xml_attribute(fp, "circuit_model_name", circuit_lib.model_name(config_protocol.bl_memory_model()).c_str());
|
||||
fp << "\t\t\t"
|
||||
<< "<bl";
|
||||
write_xml_attribute(
|
||||
fp, "protocol",
|
||||
BLWL_PROTOCOL_TYPE_STRING[config_protocol.bl_protocol_type()]);
|
||||
write_xml_attribute(
|
||||
fp, "circuit_model_name",
|
||||
circuit_lib.model_name(config_protocol.bl_memory_model()).c_str());
|
||||
write_xml_attribute(fp, "num_banks", config_protocol.bl_num_banks());
|
||||
fp << "/>" << "\n";
|
||||
fp << "/>"
|
||||
<< "\n";
|
||||
|
||||
fp << "\t\t\t" << "<wl";
|
||||
write_xml_attribute(fp, "protocol", BLWL_PROTOCOL_TYPE_STRING[config_protocol.wl_protocol_type()]);
|
||||
write_xml_attribute(fp, "circuit_model_name", circuit_lib.model_name(config_protocol.wl_memory_model()).c_str());
|
||||
fp << "\t\t\t"
|
||||
<< "<wl";
|
||||
write_xml_attribute(
|
||||
fp, "protocol",
|
||||
BLWL_PROTOCOL_TYPE_STRING[config_protocol.wl_protocol_type()]);
|
||||
write_xml_attribute(
|
||||
fp, "circuit_model_name",
|
||||
circuit_lib.model_name(config_protocol.wl_memory_model()).c_str());
|
||||
write_xml_attribute(fp, "num_banks", config_protocol.wl_num_banks());
|
||||
fp << "/>" << "\n";
|
||||
fp << "/>"
|
||||
<< "\n";
|
||||
|
||||
fp << "\t" << "</organization>" << "\n";
|
||||
fp << "\t"
|
||||
<< "</organization>"
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
|
@ -52,19 +70,22 @@ void write_xml_config_organization(std::fstream& fp,
|
|||
* This function should be run AFTER the function
|
||||
* link_config_protocol_to_circuit_library()
|
||||
*******************************************************************/
|
||||
void write_xml_config_protocol(std::fstream& fp,
|
||||
const char* fname,
|
||||
void write_xml_config_protocol(std::fstream& fp, const char* fname,
|
||||
const ConfigProtocol& config_protocol,
|
||||
const CircuitLibrary& circuit_lib) {
|
||||
/* Validate the file stream */
|
||||
openfpga::check_file_stream(fname, fp);
|
||||
|
||||
/* Write the root node */
|
||||
fp << "\t" << "<configuration_protocol>" << "\n";
|
||||
|
||||
/* Write configuration memory organization */
|
||||
/* Write the root node */
|
||||
fp << "\t"
|
||||
<< "<configuration_protocol>"
|
||||
<< "\n";
|
||||
|
||||
/* Write configuration memory organization */
|
||||
write_xml_config_organization(fp, fname, config_protocol, circuit_lib);
|
||||
|
||||
/* Finish writing the root node */
|
||||
fp << "\t" << "</configuration_protocol>" << "\n";
|
||||
fp << "\t"
|
||||
<< "</configuration_protocol>"
|
||||
<< "\n";
|
||||
}
|
||||
|
|
|
@ -5,14 +5,14 @@
|
|||
* Include header files that are required by function declaration
|
||||
*******************************************************************/
|
||||
#include <fstream>
|
||||
#include "config_protocol.h"
|
||||
|
||||
#include "circuit_library.h"
|
||||
#include "config_protocol.h"
|
||||
|
||||
/********************************************************************
|
||||
* Function declaration
|
||||
*******************************************************************/
|
||||
void write_xml_config_protocol(std::fstream& fp,
|
||||
const char* fname,
|
||||
void write_xml_config_protocol(std::fstream& fp, const char* fname,
|
||||
const ConfigProtocol& config_protocol,
|
||||
const CircuitLibrary& circuit_lib);
|
||||
|
||||
|
|
|
@ -11,20 +11,20 @@
|
|||
#include "openfpga_digest.h"
|
||||
|
||||
/* Headers from readarchopenfpga library */
|
||||
#include "write_xml_circuit_library.h"
|
||||
#include "write_xml_technology_library.h"
|
||||
#include "write_xml_simulation_setting.h"
|
||||
#include "write_xml_bitstream_setting.h"
|
||||
#include "write_xml_circuit_library.h"
|
||||
#include "write_xml_config_protocol.h"
|
||||
#include "write_xml_routing_circuit.h"
|
||||
#include "write_xml_tile_annotation.h"
|
||||
#include "write_xml_pb_type_annotation.h"
|
||||
#include "write_xml_openfpga_arch.h"
|
||||
#include "write_xml_pb_type_annotation.h"
|
||||
#include "write_xml_routing_circuit.h"
|
||||
#include "write_xml_simulation_setting.h"
|
||||
#include "write_xml_technology_library.h"
|
||||
#include "write_xml_tile_annotation.h"
|
||||
|
||||
/********************************************************************
|
||||
* A writer to output an OpenFPGA arch database to XML format
|
||||
*******************************************************************/
|
||||
void write_xml_openfpga_arch(const char* fname,
|
||||
void write_xml_openfpga_arch(const char* fname,
|
||||
const openfpga::Arch& openfpga_arch) {
|
||||
vtr::ScopedStartFinishTimer timer("Write OpenFPGA architecture");
|
||||
|
||||
|
@ -37,7 +37,8 @@ void write_xml_openfpga_arch(const char* fname,
|
|||
openfpga::check_file_stream(fname, fp);
|
||||
|
||||
/* Write the root node for openfpga_arch */
|
||||
fp << "<openfpga_architecture>" << "\n";
|
||||
fp << "<openfpga_architecture>"
|
||||
<< "\n";
|
||||
|
||||
/* Write the technology library */
|
||||
write_xml_technology_library(fp, fname, openfpga_arch.tech_lib);
|
||||
|
@ -46,27 +47,35 @@ void write_xml_openfpga_arch(const char* fname,
|
|||
write_xml_circuit_library(fp, fname, openfpga_arch.circuit_lib);
|
||||
|
||||
/* Write the configuration protocol */
|
||||
write_xml_config_protocol(fp, fname, openfpga_arch.config_protocol, openfpga_arch.circuit_lib);
|
||||
write_xml_config_protocol(fp, fname, openfpga_arch.config_protocol,
|
||||
openfpga_arch.circuit_lib);
|
||||
|
||||
/* Write the connection block circuit definition */
|
||||
write_xml_cb_switch_circuit(fp, fname, openfpga_arch.circuit_lib, openfpga_arch.cb_switch2circuit);
|
||||
write_xml_cb_switch_circuit(fp, fname, openfpga_arch.circuit_lib,
|
||||
openfpga_arch.cb_switch2circuit);
|
||||
|
||||
/* Write the switch block circuit definition */
|
||||
write_xml_sb_switch_circuit(fp, fname, openfpga_arch.circuit_lib, openfpga_arch.sb_switch2circuit);
|
||||
write_xml_sb_switch_circuit(fp, fname, openfpga_arch.circuit_lib,
|
||||
openfpga_arch.sb_switch2circuit);
|
||||
|
||||
/* Write the routing segment circuit definition */
|
||||
write_xml_routing_segment_circuit(fp, fname, openfpga_arch.circuit_lib, openfpga_arch.routing_seg2circuit);
|
||||
write_xml_routing_segment_circuit(fp, fname, openfpga_arch.circuit_lib,
|
||||
openfpga_arch.routing_seg2circuit);
|
||||
|
||||
/* Write the direct connection circuit definition */
|
||||
write_xml_direct_circuit(fp, fname, openfpga_arch.circuit_lib, openfpga_arch.arch_direct);
|
||||
write_xml_direct_circuit(fp, fname, openfpga_arch.circuit_lib,
|
||||
openfpga_arch.arch_direct);
|
||||
|
||||
/* Write the pb_type annotations */
|
||||
openfpga::write_xml_tile_annotations(fp, fname, openfpga_arch.tile_annotations);
|
||||
openfpga::write_xml_tile_annotations(fp, fname,
|
||||
openfpga_arch.tile_annotations);
|
||||
|
||||
/* Write the pb_type annotations */
|
||||
openfpga::write_xml_pb_type_annotations(fp, fname, openfpga_arch.pb_type_annotations);
|
||||
openfpga::write_xml_pb_type_annotations(fp, fname,
|
||||
openfpga_arch.pb_type_annotations);
|
||||
|
||||
fp << "</openfpga_architecture>" << "\n";
|
||||
fp << "</openfpga_architecture>"
|
||||
<< "\n";
|
||||
|
||||
/* Close the file stream */
|
||||
fp.close();
|
||||
|
@ -75,8 +84,8 @@ void write_xml_openfpga_arch(const char* fname,
|
|||
/********************************************************************
|
||||
* A writer to output an OpenFPGA simulation setting database to XML format
|
||||
*******************************************************************/
|
||||
void write_xml_openfpga_simulation_settings(const char* fname,
|
||||
const openfpga::SimulationSetting& openfpga_sim_setting) {
|
||||
void write_xml_openfpga_simulation_settings(
|
||||
const char* fname, const openfpga::SimulationSetting& openfpga_sim_setting) {
|
||||
vtr::ScopedStartFinishTimer timer("Write OpenFPGA simulation settings");
|
||||
|
||||
/* Create a file handler */
|
||||
|
@ -97,8 +106,9 @@ void write_xml_openfpga_simulation_settings(const char* fname,
|
|||
/********************************************************************
|
||||
* A writer to output an OpenFPGA bitstream setting database to XML format
|
||||
*******************************************************************/
|
||||
void write_xml_openfpga_bitstream_settings(const char* fname,
|
||||
const openfpga::BitstreamSetting& openfpga_bitstream_setting) {
|
||||
void write_xml_openfpga_bitstream_settings(
|
||||
const char* fname,
|
||||
const openfpga::BitstreamSetting& openfpga_bitstream_setting) {
|
||||
vtr::ScopedStartFinishTimer timer("Write OpenFPGA bitstream settings");
|
||||
|
||||
/* Create a file handler */
|
||||
|
|
|
@ -5,19 +5,21 @@
|
|||
* Include header files that are required by function declaration
|
||||
*******************************************************************/
|
||||
#include <string>
|
||||
|
||||
#include "openfpga_arch.h"
|
||||
|
||||
/********************************************************************
|
||||
* Function declaration
|
||||
*******************************************************************/
|
||||
void write_xml_openfpga_arch(const char* xml_fname,
|
||||
void write_xml_openfpga_arch(const char* xml_fname,
|
||||
const openfpga::Arch& openfpga_arch);
|
||||
|
||||
void write_xml_openfpga_simulation_settings(const char* xml_fname,
|
||||
const openfpga::SimulationSetting& openfpga_sim_setting);
|
||||
|
||||
void write_xml_openfpga_bitstream_settings(const char* fname,
|
||||
const openfpga::BitstreamSetting& openfpga_bitstream_setting);
|
||||
void write_xml_openfpga_simulation_settings(
|
||||
const char* xml_fname,
|
||||
const openfpga::SimulationSetting& openfpga_sim_setting);
|
||||
|
||||
void write_xml_openfpga_bitstream_settings(
|
||||
const char* fname,
|
||||
const openfpga::BitstreamSetting& openfpga_bitstream_setting);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -2,17 +2,17 @@
|
|||
* This file includes functions that outputs pb_type annotations to XML format
|
||||
*******************************************************************/
|
||||
/* Headers from system goes first */
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
/* Headers from vtr util library */
|
||||
#include "openfpga_digest.h"
|
||||
#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"
|
||||
#include "write_xml_utils.h"
|
||||
|
||||
/* namespace openfpga begins */
|
||||
namespace openfpga {
|
||||
|
@ -20,14 +20,16 @@ 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) {
|
||||
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());
|
||||
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) {
|
||||
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];
|
||||
|
@ -44,14 +46,16 @@ std::string generate_operating_pb_type_hierarchy_name(const PbTypeAnnotation& pb
|
|||
/********************************************************************
|
||||
* Generate the full hierarchy name for a operating pb_type
|
||||
*******************************************************************/
|
||||
static
|
||||
std::string generate_physical_pb_type_hierarchy_name(const PbTypeAnnotation& pb_type_annotation) {
|
||||
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());
|
||||
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) {
|
||||
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];
|
||||
|
@ -69,8 +73,7 @@ std::string generate_physical_pb_type_hierarchy_name(const PbTypeAnnotation& pb_
|
|||
* FIXME: Use a common function to output ports
|
||||
* Generate the full hierarchy name for a operating pb_type
|
||||
*******************************************************************/
|
||||
static
|
||||
std::string generate_physical_pb_port_name(const BasicPort& pb_port) {
|
||||
static std::string generate_physical_pb_port_name(const BasicPort& pb_port) {
|
||||
std::string port_name;
|
||||
|
||||
/* Output format: <port_name>[<LSB>:<MSB>] */
|
||||
|
@ -87,111 +90,135 @@ std::string generate_physical_pb_port_name(const BasicPort& pb_port) {
|
|||
/********************************************************************
|
||||
* 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) {
|
||||
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 << "\t\t\t"
|
||||
<< "<interconnect";
|
||||
|
||||
fp << "/>" << "\n";
|
||||
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) {
|
||||
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";
|
||||
|
||||
fp << "\t\t\t"
|
||||
<< "<port";
|
||||
|
||||
write_xml_attribute(fp, "name", port_name.c_str());
|
||||
|
||||
std::string physical_mode_port_attr;
|
||||
for (const auto& physical_pb_port_pair : pb_type_annotation.physical_pb_type_port(port_name)) {
|
||||
for (const auto& physical_pb_port_pair :
|
||||
pb_type_annotation.physical_pb_type_port(port_name)) {
|
||||
if (false == physical_mode_port_attr.empty()) {
|
||||
physical_mode_port_attr += " ";
|
||||
}
|
||||
physical_mode_port_attr += generate_physical_pb_port_name(physical_pb_port_pair.first);
|
||||
physical_mode_port_attr +=
|
||||
generate_physical_pb_port_name(physical_pb_port_pair.first);
|
||||
}
|
||||
write_xml_attribute(fp, "physical_mode_port", physical_mode_port_attr.c_str());
|
||||
write_xml_attribute(fp, "physical_mode_port",
|
||||
physical_mode_port_attr.c_str());
|
||||
|
||||
std::string physical_mode_pin_initial_offset_attr;
|
||||
for (const auto& physical_pb_port_pair : pb_type_annotation.physical_pb_type_port(port_name)) {
|
||||
for (const auto& physical_pb_port_pair :
|
||||
pb_type_annotation.physical_pb_type_port(port_name)) {
|
||||
if (false == physical_mode_pin_initial_offset_attr.empty()) {
|
||||
physical_mode_pin_initial_offset_attr += " ";
|
||||
}
|
||||
physical_mode_pin_initial_offset_attr += std::to_string(physical_pb_port_pair.second[0]);
|
||||
physical_mode_pin_initial_offset_attr +=
|
||||
std::to_string(physical_pb_port_pair.second[0]);
|
||||
}
|
||||
write_xml_attribute(fp, "physical_mode_pin_initial_offset", physical_mode_pin_initial_offset_attr.c_str());
|
||||
write_xml_attribute(fp, "physical_mode_pin_initial_offset",
|
||||
physical_mode_pin_initial_offset_attr.c_str());
|
||||
|
||||
std::string physical_mode_pin_rotate_offset_attr;
|
||||
for (const auto& physical_pb_port_pair : pb_type_annotation.physical_pb_type_port(port_name)) {
|
||||
for (const auto& physical_pb_port_pair :
|
||||
pb_type_annotation.physical_pb_type_port(port_name)) {
|
||||
if (false == physical_mode_pin_rotate_offset_attr.empty()) {
|
||||
physical_mode_pin_rotate_offset_attr += " ";
|
||||
}
|
||||
physical_mode_pin_rotate_offset_attr += std::to_string(physical_pb_port_pair.second[1]);
|
||||
physical_mode_pin_rotate_offset_attr +=
|
||||
std::to_string(physical_pb_port_pair.second[1]);
|
||||
}
|
||||
write_xml_attribute(fp, "physical_mode_pin_rotate_offset", physical_mode_pin_rotate_offset_attr.c_str());
|
||||
write_xml_attribute(fp, "physical_mode_pin_rotate_offset",
|
||||
physical_mode_pin_rotate_offset_attr.c_str());
|
||||
std::string physical_mode_port_rotate_offset_attr;
|
||||
for (const auto& physical_pb_port_pair : pb_type_annotation.physical_pb_type_port(port_name)) {
|
||||
for (const auto& physical_pb_port_pair :
|
||||
pb_type_annotation.physical_pb_type_port(port_name)) {
|
||||
if (false == physical_mode_port_rotate_offset_attr.empty()) {
|
||||
physical_mode_port_rotate_offset_attr += " ";
|
||||
}
|
||||
physical_mode_port_rotate_offset_attr += std::to_string(physical_pb_port_pair.second[2]);
|
||||
physical_mode_port_rotate_offset_attr +=
|
||||
std::to_string(physical_pb_port_pair.second[2]);
|
||||
}
|
||||
write_xml_attribute(fp, "physical_mode_port_rotate_offset", physical_mode_port_rotate_offset_attr.c_str());
|
||||
fp << "/>" << "\n";
|
||||
write_xml_attribute(fp, "physical_mode_port_rotate_offset",
|
||||
physical_mode_port_rotate_offset_attr.c_str());
|
||||
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) {
|
||||
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";
|
||||
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_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());
|
||||
|
||||
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());
|
||||
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());
|
||||
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()) {
|
||||
if (!pb_type_annotation.mode_bits().empty()) {
|
||||
/* Convert the vector of integer to string */
|
||||
std::string mode_bits_str;
|
||||
for (const size_t& bit : pb_type_annotation.mode_bits()) {
|
||||
|
@ -201,62 +228,75 @@ void write_xml_pb_type_annotation(std::fstream& fp,
|
|||
}
|
||||
|
||||
/* 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());
|
||||
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());
|
||||
/* 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
|
||||
* Otherwise we can finish here
|
||||
*/
|
||||
if ( (0 == pb_type_annotation.interconnect_names().size())
|
||||
&& (0 == pb_type_annotation.port_names().size()) ) {
|
||||
fp << "/>" << "\n";
|
||||
if ((0 == pb_type_annotation.interconnect_names().size()) &&
|
||||
(0 == pb_type_annotation.port_names().size())) {
|
||||
fp << "/>"
|
||||
<< "\n";
|
||||
return;
|
||||
}
|
||||
|
||||
fp << ">" << "\n";
|
||||
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);
|
||||
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";
|
||||
|
||||
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) {
|
||||
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
|
||||
|
||||
/* 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";
|
||||
fp << "\t"
|
||||
<< "<pb_type_annotations>"
|
||||
<< "\n";
|
||||
|
||||
/* Write device model one by one */
|
||||
/* 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";
|
||||
fp << "\t"
|
||||
<< "</pb_type_annotations>"
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
} /* namespace openfpga ends */
|
||||
} // namespace openfpga
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* Include header files that are required by function declaration
|
||||
*******************************************************************/
|
||||
#include <fstream>
|
||||
|
||||
#include "pb_type_annotation.h"
|
||||
|
||||
/********************************************************************
|
||||
|
@ -13,10 +14,10 @@
|
|||
/* namespace openfpga begins */
|
||||
namespace openfpga {
|
||||
|
||||
void write_xml_pb_type_annotations(std::fstream& fp,
|
||||
const char* fname,
|
||||
const std::vector<PbTypeAnnotation>& pb_type_annotations);
|
||||
void write_xml_pb_type_annotations(
|
||||
std::fstream& fp, const char* fname,
|
||||
const std::vector<PbTypeAnnotation>& pb_type_annotations);
|
||||
|
||||
} /* namespace openfpga ends */
|
||||
} // namespace openfpga
|
||||
|
||||
#endif
|
||||
|
|
|
@ -3,129 +3,145 @@
|
|||
* to XML format
|
||||
*******************************************************************/
|
||||
/* Headers from system goes first */
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
/* Headers from vtr util library */
|
||||
#include "openfpga_digest.h"
|
||||
#include "vtr_assert.h"
|
||||
#include "vtr_log.h"
|
||||
#include "openfpga_digest.h"
|
||||
|
||||
/* Headers from readarchopenfpga library */
|
||||
#include "write_xml_utils.h"
|
||||
#include "write_xml_routing_circuit.h"
|
||||
#include "write_xml_utils.h"
|
||||
|
||||
/********************************************************************
|
||||
* Write switch circuit model definition in XML format
|
||||
*******************************************************************/
|
||||
static
|
||||
void write_xml_routing_component_circuit(std::fstream& fp,
|
||||
const char* fname,
|
||||
const std::string& routing_component_name,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
const std::map<std::string, CircuitModelId>& switch2circuit) {
|
||||
static void write_xml_routing_component_circuit(
|
||||
std::fstream& fp, const char* fname,
|
||||
const std::string& routing_component_name, const CircuitLibrary& circuit_lib,
|
||||
const std::map<std::string, CircuitModelId>& switch2circuit) {
|
||||
/* Validate the file stream */
|
||||
openfpga::check_file_stream(fname, fp);
|
||||
|
||||
/* Iterate over the mapping */
|
||||
for (std::map<std::string, CircuitModelId>::const_iterator it = switch2circuit.begin();
|
||||
it != switch2circuit.end();
|
||||
++it) {
|
||||
fp << "\t\t" << "<" << routing_component_name;
|
||||
write_xml_attribute(fp, "name", it->first.c_str());
|
||||
write_xml_attribute(fp, "circuit_model_name", circuit_lib.model_name(it->second).c_str());
|
||||
fp << "/>" << "\n";
|
||||
for (std::map<std::string, CircuitModelId>::const_iterator it =
|
||||
switch2circuit.begin();
|
||||
it != switch2circuit.end(); ++it) {
|
||||
fp << "\t\t"
|
||||
<< "<" << routing_component_name;
|
||||
write_xml_attribute(fp, "name", it->first.c_str());
|
||||
write_xml_attribute(fp, "circuit_model_name",
|
||||
circuit_lib.model_name(it->second).c_str());
|
||||
fp << "/>"
|
||||
<< "\n";
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Write switch circuit model definition in XML format
|
||||
*******************************************************************/
|
||||
static
|
||||
void write_xml_direct_component_circuit(std::fstream& fp,
|
||||
const char* fname,
|
||||
const std::string& direct_tag_name,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
const ArchDirect& arch_direct,
|
||||
const ArchDirectId& direct_id) {
|
||||
static void write_xml_direct_component_circuit(
|
||||
std::fstream& fp, const char* fname, const std::string& direct_tag_name,
|
||||
const CircuitLibrary& circuit_lib, const ArchDirect& arch_direct,
|
||||
const ArchDirectId& direct_id) {
|
||||
/* Validate the file stream */
|
||||
openfpga::check_file_stream(fname, fp);
|
||||
|
||||
/* Iterate over the mapping */
|
||||
fp << "\t\t" << "<" << direct_tag_name;
|
||||
write_xml_attribute(fp, "name", arch_direct.name(direct_id).c_str());
|
||||
write_xml_attribute(fp, "circuit_model_name", circuit_lib.model_name(arch_direct.circuit_model(direct_id)).c_str());
|
||||
write_xml_attribute(fp, "type", DIRECT_TYPE_STRING[arch_direct.type(direct_id)]);
|
||||
write_xml_attribute(fp, "x_dir", DIRECT_DIRECTION_STRING[arch_direct.x_dir(direct_id)]);
|
||||
write_xml_attribute(fp, "y_dir", DIRECT_DIRECTION_STRING[arch_direct.y_dir(direct_id)]);
|
||||
fp << "/>" << "\n";
|
||||
fp << "\t\t"
|
||||
<< "<" << direct_tag_name;
|
||||
write_xml_attribute(fp, "name", arch_direct.name(direct_id).c_str());
|
||||
write_xml_attribute(
|
||||
fp, "circuit_model_name",
|
||||
circuit_lib.model_name(arch_direct.circuit_model(direct_id)).c_str());
|
||||
write_xml_attribute(fp, "type",
|
||||
DIRECT_TYPE_STRING[arch_direct.type(direct_id)]);
|
||||
write_xml_attribute(fp, "x_dir",
|
||||
DIRECT_DIRECTION_STRING[arch_direct.x_dir(direct_id)]);
|
||||
write_xml_attribute(fp, "y_dir",
|
||||
DIRECT_DIRECTION_STRING[arch_direct.y_dir(direct_id)]);
|
||||
fp << "/>"
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Write Connection block circuit models in XML format
|
||||
*******************************************************************/
|
||||
void write_xml_cb_switch_circuit(std::fstream& fp,
|
||||
const char* fname,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
const std::map<std::string, CircuitModelId>& switch2circuit) {
|
||||
void write_xml_cb_switch_circuit(
|
||||
std::fstream& fp, const char* fname, const CircuitLibrary& circuit_lib,
|
||||
const std::map<std::string, CircuitModelId>& switch2circuit) {
|
||||
/* Validate the file stream */
|
||||
openfpga::check_file_stream(fname, fp);
|
||||
|
||||
/* Write the root node */
|
||||
fp << "\t" << "<connection_block>" << "\n";
|
||||
|
||||
/* Write each switch circuit definition */
|
||||
write_xml_routing_component_circuit(fp, fname, std::string("switch"), circuit_lib, switch2circuit);
|
||||
/* Write the root node */
|
||||
fp << "\t"
|
||||
<< "<connection_block>"
|
||||
<< "\n";
|
||||
|
||||
/* Write each switch circuit definition */
|
||||
write_xml_routing_component_circuit(fp, fname, std::string("switch"),
|
||||
circuit_lib, switch2circuit);
|
||||
|
||||
/* Finish writing the root node */
|
||||
fp << "\t" << "</connection_block>" << "\n";
|
||||
fp << "\t"
|
||||
<< "</connection_block>"
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Write Switch block circuit models in XML format
|
||||
*******************************************************************/
|
||||
void write_xml_sb_switch_circuit(std::fstream& fp,
|
||||
const char* fname,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
const std::map<std::string, CircuitModelId>& switch2circuit) {
|
||||
void write_xml_sb_switch_circuit(
|
||||
std::fstream& fp, const char* fname, const CircuitLibrary& circuit_lib,
|
||||
const std::map<std::string, CircuitModelId>& switch2circuit) {
|
||||
/* Validate the file stream */
|
||||
openfpga::check_file_stream(fname, fp);
|
||||
|
||||
/* Write the root node */
|
||||
fp << "\t" << "<switch_block>" << "\n";
|
||||
|
||||
/* Write each switch circuit definition */
|
||||
write_xml_routing_component_circuit(fp, fname, std::string("switch"), circuit_lib, switch2circuit);
|
||||
/* Write the root node */
|
||||
fp << "\t"
|
||||
<< "<switch_block>"
|
||||
<< "\n";
|
||||
|
||||
/* Write each switch circuit definition */
|
||||
write_xml_routing_component_circuit(fp, fname, std::string("switch"),
|
||||
circuit_lib, switch2circuit);
|
||||
|
||||
/* Finish writing the root node */
|
||||
fp << "\t" << "</switch_block>" << "\n";
|
||||
fp << "\t"
|
||||
<< "</switch_block>"
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Write routing segment circuit models in XML format
|
||||
*******************************************************************/
|
||||
void write_xml_routing_segment_circuit(std::fstream& fp,
|
||||
const char* fname,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
const std::map<std::string, CircuitModelId>& seg2circuit) {
|
||||
void write_xml_routing_segment_circuit(
|
||||
std::fstream& fp, const char* fname, const CircuitLibrary& circuit_lib,
|
||||
const std::map<std::string, CircuitModelId>& seg2circuit) {
|
||||
/* Validate the file stream */
|
||||
openfpga::check_file_stream(fname, fp);
|
||||
|
||||
/* Write the root node */
|
||||
fp << "\t" << "<routing_segment>" << "\n";
|
||||
|
||||
/* Write each routing segment circuit definition */
|
||||
write_xml_routing_component_circuit(fp, fname, std::string("segment"), circuit_lib, seg2circuit);
|
||||
/* Write the root node */
|
||||
fp << "\t"
|
||||
<< "<routing_segment>"
|
||||
<< "\n";
|
||||
|
||||
/* Write each routing segment circuit definition */
|
||||
write_xml_routing_component_circuit(fp, fname, std::string("segment"),
|
||||
circuit_lib, seg2circuit);
|
||||
|
||||
/* Finish writing the root node */
|
||||
fp << "\t" << "</routing_segment>" << "\n";
|
||||
fp << "\t"
|
||||
<< "</routing_segment>"
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Write direction connection circuit models in XML format
|
||||
*******************************************************************/
|
||||
void write_xml_direct_circuit(std::fstream& fp,
|
||||
const char* fname,
|
||||
void write_xml_direct_circuit(std::fstream& fp, const char* fname,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
const ArchDirect& arch_direct) {
|
||||
/* If the direct2circuit is empty, we do not output XML */
|
||||
|
@ -135,15 +151,20 @@ void write_xml_direct_circuit(std::fstream& fp,
|
|||
|
||||
/* Validate the file stream */
|
||||
openfpga::check_file_stream(fname, fp);
|
||||
|
||||
/* Write the root node */
|
||||
fp << "\t" << "<direct_connection>" << "\n";
|
||||
|
||||
/* Write each direct connection circuit definition */
|
||||
/* Write the root node */
|
||||
fp << "\t"
|
||||
<< "<direct_connection>"
|
||||
<< "\n";
|
||||
|
||||
/* Write each direct connection circuit definition */
|
||||
for (const ArchDirectId& direct_id : arch_direct.directs()) {
|
||||
write_xml_direct_component_circuit(fp, fname, std::string("direct"), circuit_lib, arch_direct, direct_id);
|
||||
write_xml_direct_component_circuit(fp, fname, std::string("direct"),
|
||||
circuit_lib, arch_direct, direct_id);
|
||||
}
|
||||
|
||||
/* Finish writing the root node */
|
||||
fp << "\t" << "</direct_connection>" << "\n";
|
||||
fp << "\t"
|
||||
<< "</direct_connection>"
|
||||
<< "\n";
|
||||
}
|
||||
|
|
|
@ -8,29 +8,25 @@
|
|||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "circuit_library.h"
|
||||
#include "arch_direct.h"
|
||||
#include "circuit_library.h"
|
||||
|
||||
/********************************************************************
|
||||
* Function declaration
|
||||
*******************************************************************/
|
||||
void write_xml_cb_switch_circuit(std::fstream& fp,
|
||||
const char* fname,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
const std::map<std::string, CircuitModelId>& switch2circuit);
|
||||
void write_xml_cb_switch_circuit(
|
||||
std::fstream& fp, const char* fname, const CircuitLibrary& circuit_lib,
|
||||
const std::map<std::string, CircuitModelId>& switch2circuit);
|
||||
|
||||
void write_xml_sb_switch_circuit(std::fstream& fp,
|
||||
const char* fname,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
const std::map<std::string, CircuitModelId>& switch2circuit);
|
||||
void write_xml_sb_switch_circuit(
|
||||
std::fstream& fp, const char* fname, const CircuitLibrary& circuit_lib,
|
||||
const std::map<std::string, CircuitModelId>& switch2circuit);
|
||||
|
||||
void write_xml_routing_segment_circuit(std::fstream& fp,
|
||||
const char* fname,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
const std::map<std::string, CircuitModelId>& seg2circuit);
|
||||
void write_xml_routing_segment_circuit(
|
||||
std::fstream& fp, const char* fname, const CircuitLibrary& circuit_lib,
|
||||
const std::map<std::string, CircuitModelId>& seg2circuit);
|
||||
|
||||
void write_xml_direct_circuit(std::fstream& fp,
|
||||
const char* fname,
|
||||
void write_xml_direct_circuit(std::fstream& fp, const char* fname,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
const ArchDirect& arch_direct);
|
||||
|
||||
|
|
|
@ -2,117 +2,159 @@
|
|||
* This file includes functions that outputs a simulation setting to XML format
|
||||
*******************************************************************/
|
||||
/* Headers from system goes first */
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
/* Headers from vtr util library */
|
||||
#include "openfpga_digest.h"
|
||||
#include "vtr_assert.h"
|
||||
#include "vtr_log.h"
|
||||
#include "openfpga_digest.h"
|
||||
|
||||
/* Headers from readarchopenfpga library */
|
||||
#include "write_xml_utils.h"
|
||||
#include "write_xml_simulation_setting.h"
|
||||
#include "write_xml_utils.h"
|
||||
|
||||
/********************************************************************
|
||||
* A writer to output a clock setting in a simulation setting to XML format
|
||||
*******************************************************************/
|
||||
static
|
||||
void write_xml_clock_setting(std::fstream& fp,
|
||||
const char* fname,
|
||||
const openfpga::SimulationSetting& sim_setting) {
|
||||
static void write_xml_clock_setting(
|
||||
std::fstream& fp, const char* fname,
|
||||
const openfpga::SimulationSetting& sim_setting) {
|
||||
/* Validate the file stream */
|
||||
openfpga::check_file_stream(fname, fp);
|
||||
|
||||
fp << "\t" << "<clock_setting>" << "\n";
|
||||
fp << "\t"
|
||||
<< "<clock_setting>"
|
||||
<< "\n";
|
||||
|
||||
fp << "\t\t" << "<operating";
|
||||
write_xml_attribute(fp, "frequency", sim_setting.default_operating_clock_frequency());
|
||||
fp << "\t\t"
|
||||
<< "<operating";
|
||||
write_xml_attribute(fp, "frequency",
|
||||
sim_setting.default_operating_clock_frequency());
|
||||
|
||||
if (true == sim_setting.auto_select_num_clock_cycles()) {
|
||||
write_xml_attribute(fp, "num_cycles", "auto");
|
||||
} else {
|
||||
VTR_ASSERT_SAFE(false == sim_setting.auto_select_num_clock_cycles());
|
||||
write_xml_attribute(fp, "num_cycles", std::to_string(sim_setting.num_clock_cycles()).c_str());
|
||||
write_xml_attribute(fp, "num_cycles",
|
||||
std::to_string(sim_setting.num_clock_cycles()).c_str());
|
||||
}
|
||||
|
||||
write_xml_attribute(fp, "slack", std::to_string(sim_setting.operating_clock_frequency_slack()).c_str());
|
||||
write_xml_attribute(
|
||||
fp, "slack",
|
||||
std::to_string(sim_setting.operating_clock_frequency_slack()).c_str());
|
||||
|
||||
fp << ">"
|
||||
<< "\n";
|
||||
|
||||
fp << ">" << "\n";
|
||||
|
||||
/* Output clock information one by one */
|
||||
for (const SimulationClockId& clock_id : sim_setting.operating_clocks()) {
|
||||
fp << "\t\t\t" << "<clock";
|
||||
fp << "\t\t\t"
|
||||
<< "<clock";
|
||||
write_xml_attribute(fp, "name", sim_setting.clock_name(clock_id).c_str());
|
||||
write_xml_attribute(fp, "port", generate_xml_port_name(sim_setting.clock_port(clock_id)).c_str());
|
||||
write_xml_attribute(fp, "frequency", std::to_string(sim_setting.clock_frequency(clock_id)).c_str());
|
||||
fp << ">" << "\n";
|
||||
write_xml_attribute(
|
||||
fp, "port",
|
||||
generate_xml_port_name(sim_setting.clock_port(clock_id)).c_str());
|
||||
write_xml_attribute(
|
||||
fp, "frequency",
|
||||
std::to_string(sim_setting.clock_frequency(clock_id)).c_str());
|
||||
fp << ">"
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
fp << "\t\t" << "</operating";
|
||||
fp << ">" << "\n";
|
||||
|
||||
fp << "\t\t" << "<programming";
|
||||
write_xml_attribute(fp, "frequency", sim_setting.programming_clock_frequency());
|
||||
fp << ">" << "\n";
|
||||
fp << "\t\t"
|
||||
<< "</operating";
|
||||
fp << ">"
|
||||
<< "\n";
|
||||
|
||||
fp << "\t\t"
|
||||
<< "<programming";
|
||||
write_xml_attribute(fp, "frequency",
|
||||
sim_setting.programming_clock_frequency());
|
||||
fp << ">"
|
||||
<< "\n";
|
||||
|
||||
/* Output clock information one by one */
|
||||
for (const SimulationClockId& clock_id : sim_setting.programming_clocks()) {
|
||||
fp << "\t\t\t" << "<clock";
|
||||
fp << "\t\t\t"
|
||||
<< "<clock";
|
||||
write_xml_attribute(fp, "name", sim_setting.clock_name(clock_id).c_str());
|
||||
write_xml_attribute(fp, "port", generate_xml_port_name(sim_setting.clock_port(clock_id)).c_str());
|
||||
write_xml_attribute(fp, "frequency", std::to_string(sim_setting.clock_frequency(clock_id)).c_str());
|
||||
write_xml_attribute(fp, "is_shift_register", std::to_string(sim_setting.clock_is_shift_register(clock_id)).c_str());
|
||||
fp << ">" << "\n";
|
||||
write_xml_attribute(
|
||||
fp, "port",
|
||||
generate_xml_port_name(sim_setting.clock_port(clock_id)).c_str());
|
||||
write_xml_attribute(
|
||||
fp, "frequency",
|
||||
std::to_string(sim_setting.clock_frequency(clock_id)).c_str());
|
||||
write_xml_attribute(
|
||||
fp, "is_shift_register",
|
||||
std::to_string(sim_setting.clock_is_shift_register(clock_id)).c_str());
|
||||
fp << ">"
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
fp << "\t\t" << "</programming";
|
||||
fp << ">" << "\n";
|
||||
fp << "\t\t"
|
||||
<< "</programming";
|
||||
fp << ">"
|
||||
<< "\n";
|
||||
|
||||
fp << "\t" << "</clock_setting>" << "\n";
|
||||
fp << "\t"
|
||||
<< "</clock_setting>"
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* A writer to output a simulator option in a simulation setting to XML format
|
||||
*******************************************************************/
|
||||
static
|
||||
void write_xml_simulator_option(std::fstream& fp,
|
||||
const char* fname,
|
||||
const openfpga::SimulationSetting& sim_setting) {
|
||||
static void write_xml_simulator_option(
|
||||
std::fstream& fp, const char* fname,
|
||||
const openfpga::SimulationSetting& sim_setting) {
|
||||
/* Validate the file stream */
|
||||
openfpga::check_file_stream(fname, fp);
|
||||
|
||||
fp << "\t" << "<simulator_option>" << "\n";
|
||||
fp << "\t"
|
||||
<< "<simulator_option>"
|
||||
<< "\n";
|
||||
|
||||
fp << "\t\t" << "<operating_condition";
|
||||
fp << "\t\t"
|
||||
<< "<operating_condition";
|
||||
write_xml_attribute(fp, "temperature", sim_setting.simulation_temperature());
|
||||
fp << "/>" << "\n";
|
||||
fp << "/>"
|
||||
<< "\n";
|
||||
|
||||
fp << "\t\t" << "<output_log";
|
||||
fp << "\t\t"
|
||||
<< "<output_log";
|
||||
write_xml_attribute(fp, "verbose", sim_setting.verbose_output());
|
||||
write_xml_attribute(fp, "captab", sim_setting.capacitance_output());
|
||||
fp << "/>" << "\n";
|
||||
fp << "/>"
|
||||
<< "\n";
|
||||
|
||||
fp << "\t\t" << "<accuracy";
|
||||
write_xml_attribute(fp, "type", SIM_ACCURACY_TYPE_STRING[sim_setting.simulation_accuracy_type()]);
|
||||
fp << "\t\t"
|
||||
<< "<accuracy";
|
||||
write_xml_attribute(
|
||||
fp, "type",
|
||||
SIM_ACCURACY_TYPE_STRING[sim_setting.simulation_accuracy_type()]);
|
||||
write_xml_attribute(fp, "value", sim_setting.simulation_accuracy());
|
||||
fp << "/>" << "\n";
|
||||
fp << "/>"
|
||||
<< "\n";
|
||||
|
||||
fp << "\t\t" << "<runtime";
|
||||
fp << "\t\t"
|
||||
<< "<runtime";
|
||||
write_xml_attribute(fp, "fast_simulation", sim_setting.fast_simulation());
|
||||
fp << "/>" << "\n";
|
||||
fp << "/>"
|
||||
<< "\n";
|
||||
|
||||
fp << "\t" << "</simulator_option>" << "\n";
|
||||
fp << "\t"
|
||||
<< "</simulator_option>"
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* A writer to output a monte carlo simulation setting
|
||||
* in a simulation setting to XML format
|
||||
*******************************************************************/
|
||||
static
|
||||
void write_xml_monte_carlo(std::fstream& fp,
|
||||
const char* fname,
|
||||
const openfpga::SimulationSetting& sim_setting) {
|
||||
static void write_xml_monte_carlo(
|
||||
std::fstream& fp, const char* fname,
|
||||
const openfpga::SimulationSetting& sim_setting) {
|
||||
/* Validate the file stream */
|
||||
openfpga::check_file_stream(fname, fp);
|
||||
|
||||
|
@ -123,147 +165,207 @@ void write_xml_monte_carlo(std::fstream& fp,
|
|||
return;
|
||||
}
|
||||
|
||||
fp << "\t\t" << "<monte_carlo";
|
||||
fp << "\t\t"
|
||||
<< "<monte_carlo";
|
||||
|
||||
write_xml_attribute(fp, "num_simulation_points", std::to_string(sim_setting.monte_carlo_simulation_points()).c_str());
|
||||
|
||||
fp << "/>" << "\n";
|
||||
write_xml_attribute(
|
||||
fp, "num_simulation_points",
|
||||
std::to_string(sim_setting.monte_carlo_simulation_points()).c_str());
|
||||
|
||||
fp << "/>"
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* A writer to output the slew measurement setting in a simulation setting to XML format
|
||||
* A writer to output the slew measurement setting in a simulation setting to
|
||||
*XML format
|
||||
*******************************************************************/
|
||||
static
|
||||
void write_xml_slew_measurement(std::fstream& fp,
|
||||
const char* fname,
|
||||
const openfpga::SimulationSetting& sim_setting,
|
||||
const e_sim_signal_type& signal_type) {
|
||||
static void write_xml_slew_measurement(
|
||||
std::fstream& fp, const char* fname,
|
||||
const openfpga::SimulationSetting& sim_setting,
|
||||
const e_sim_signal_type& signal_type) {
|
||||
/* Validate the file stream */
|
||||
openfpga::check_file_stream(fname, fp);
|
||||
|
||||
fp << "\t\t\t" << "<" << SIM_SIGNAL_TYPE_STRING[signal_type];
|
||||
fp << "\t\t\t"
|
||||
<< "<" << SIM_SIGNAL_TYPE_STRING[signal_type];
|
||||
|
||||
write_xml_attribute(fp, "upper_thres_pct", sim_setting.measure_slew_upper_threshold(signal_type));
|
||||
write_xml_attribute(fp, "lower_thres_pct", sim_setting.measure_slew_lower_threshold(signal_type));
|
||||
|
||||
fp << "/>" << "\n";
|
||||
write_xml_attribute(fp, "upper_thres_pct",
|
||||
sim_setting.measure_slew_upper_threshold(signal_type));
|
||||
write_xml_attribute(fp, "lower_thres_pct",
|
||||
sim_setting.measure_slew_lower_threshold(signal_type));
|
||||
|
||||
fp << "/>"
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* A writer to output the delay measurement setting in a simulation setting to XML format
|
||||
* A writer to output the delay measurement setting in a simulation setting to
|
||||
*XML format
|
||||
*******************************************************************/
|
||||
static
|
||||
void write_xml_delay_measurement(std::fstream& fp,
|
||||
const char* fname,
|
||||
const openfpga::SimulationSetting& sim_setting,
|
||||
const e_sim_signal_type& signal_type) {
|
||||
static void write_xml_delay_measurement(
|
||||
std::fstream& fp, const char* fname,
|
||||
const openfpga::SimulationSetting& sim_setting,
|
||||
const e_sim_signal_type& signal_type) {
|
||||
/* Validate the file stream */
|
||||
openfpga::check_file_stream(fname, fp);
|
||||
|
||||
fp << "\t\t\t" << "<" << SIM_SIGNAL_TYPE_STRING[signal_type];
|
||||
fp << "\t\t\t"
|
||||
<< "<" << SIM_SIGNAL_TYPE_STRING[signal_type];
|
||||
|
||||
write_xml_attribute(fp, "input_thres_pct", sim_setting.measure_delay_input_threshold(signal_type));
|
||||
write_xml_attribute(fp, "output_thres_pct", sim_setting.measure_delay_output_threshold(signal_type));
|
||||
|
||||
fp << "/>" << "\n";
|
||||
write_xml_attribute(fp, "input_thres_pct",
|
||||
sim_setting.measure_delay_input_threshold(signal_type));
|
||||
write_xml_attribute(fp, "output_thres_pct",
|
||||
sim_setting.measure_delay_output_threshold(signal_type));
|
||||
|
||||
fp << "/>"
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* A writer to output a measurement setting in a simulation setting to XML format
|
||||
* A writer to output a measurement setting in a simulation setting to XML
|
||||
*format
|
||||
*******************************************************************/
|
||||
static
|
||||
void write_xml_measurement(std::fstream& fp,
|
||||
const char* fname,
|
||||
const openfpga::SimulationSetting& sim_setting) {
|
||||
static void write_xml_measurement(
|
||||
std::fstream& fp, const char* fname,
|
||||
const openfpga::SimulationSetting& sim_setting) {
|
||||
/* Validate the file stream */
|
||||
openfpga::check_file_stream(fname, fp);
|
||||
|
||||
fp << "\t" << "<measurement_setting>" << "\n";
|
||||
fp << "\t"
|
||||
<< "<measurement_setting>"
|
||||
<< "\n";
|
||||
|
||||
fp << "\t\t" << "<slew>" << "\n";
|
||||
fp << "\t\t"
|
||||
<< "<slew>"
|
||||
<< "\n";
|
||||
write_xml_slew_measurement(fp, fname, sim_setting, SIM_SIGNAL_RISE);
|
||||
write_xml_slew_measurement(fp, fname, sim_setting, SIM_SIGNAL_FALL);
|
||||
fp << "\t\t" << "</slew>" << "\n";
|
||||
fp << "\t\t"
|
||||
<< "</slew>"
|
||||
<< "\n";
|
||||
|
||||
fp << "\t\t" << "<delay>" << "\n";
|
||||
fp << "\t\t"
|
||||
<< "<delay>"
|
||||
<< "\n";
|
||||
write_xml_delay_measurement(fp, fname, sim_setting, SIM_SIGNAL_RISE);
|
||||
write_xml_delay_measurement(fp, fname, sim_setting, SIM_SIGNAL_FALL);
|
||||
fp << "\t\t" << "</delay>" << "\n";
|
||||
fp << "\t\t"
|
||||
<< "</delay>"
|
||||
<< "\n";
|
||||
|
||||
fp << "\t" << "</measurement_setting>" << "\n";
|
||||
fp << "\t"
|
||||
<< "</measurement_setting>"
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* A writer to output a stimulus setting in a simulation setting to XML format
|
||||
*******************************************************************/
|
||||
static
|
||||
void write_xml_stimulus(std::fstream& fp,
|
||||
const char* fname,
|
||||
const openfpga::SimulationSetting& sim_setting) {
|
||||
static void write_xml_stimulus(std::fstream& fp, const char* fname,
|
||||
const openfpga::SimulationSetting& sim_setting) {
|
||||
/* Validate the file stream */
|
||||
openfpga::check_file_stream(fname, fp);
|
||||
|
||||
fp << "\t" << "<stimulus>" << "\n";
|
||||
fp << "\t"
|
||||
<< "<stimulus>"
|
||||
<< "\n";
|
||||
|
||||
fp << "\t\t" << "<clock>" << "\n";
|
||||
fp << "\t\t"
|
||||
<< "<clock>"
|
||||
<< "\n";
|
||||
|
||||
fp << "\t\t\t" << "<rise";
|
||||
write_xml_attribute(fp, "slew_type", SIM_ACCURACY_TYPE_STRING[sim_setting.stimuli_clock_slew_type(SIM_SIGNAL_RISE)]);
|
||||
write_xml_attribute(fp, "slew_time", sim_setting.stimuli_clock_slew(SIM_SIGNAL_RISE));
|
||||
fp << "/>" << "\n";
|
||||
fp << "\t\t\t"
|
||||
<< "<rise";
|
||||
write_xml_attribute(
|
||||
fp, "slew_type",
|
||||
SIM_ACCURACY_TYPE_STRING[sim_setting.stimuli_clock_slew_type(
|
||||
SIM_SIGNAL_RISE)]);
|
||||
write_xml_attribute(fp, "slew_time",
|
||||
sim_setting.stimuli_clock_slew(SIM_SIGNAL_RISE));
|
||||
fp << "/>"
|
||||
<< "\n";
|
||||
|
||||
fp << "\t\t\t" << "<fall";
|
||||
write_xml_attribute(fp, "slew_type", SIM_ACCURACY_TYPE_STRING[sim_setting.stimuli_clock_slew_type(SIM_SIGNAL_FALL)]);
|
||||
write_xml_attribute(fp, "slew_time", sim_setting.stimuli_clock_slew(SIM_SIGNAL_FALL));
|
||||
fp << "/>" << "\n";
|
||||
fp << "\t\t\t"
|
||||
<< "<fall";
|
||||
write_xml_attribute(
|
||||
fp, "slew_type",
|
||||
SIM_ACCURACY_TYPE_STRING[sim_setting.stimuli_clock_slew_type(
|
||||
SIM_SIGNAL_FALL)]);
|
||||
write_xml_attribute(fp, "slew_time",
|
||||
sim_setting.stimuli_clock_slew(SIM_SIGNAL_FALL));
|
||||
fp << "/>"
|
||||
<< "\n";
|
||||
|
||||
fp << "\t\t" << "</clock>" << "\n";
|
||||
fp << "\t\t"
|
||||
<< "</clock>"
|
||||
<< "\n";
|
||||
|
||||
fp << "\t\t" << "<input>" << "\n";
|
||||
fp << "\t\t"
|
||||
<< "<input>"
|
||||
<< "\n";
|
||||
|
||||
fp << "\t\t\t" << "<rise";
|
||||
write_xml_attribute(fp, "slew_type", SIM_ACCURACY_TYPE_STRING[sim_setting.stimuli_input_slew_type(SIM_SIGNAL_RISE)]);
|
||||
write_xml_attribute(fp, "slew_time", sim_setting.stimuli_input_slew(SIM_SIGNAL_RISE));
|
||||
fp << "/>" << "\n";
|
||||
fp << "\t\t\t"
|
||||
<< "<rise";
|
||||
write_xml_attribute(
|
||||
fp, "slew_type",
|
||||
SIM_ACCURACY_TYPE_STRING[sim_setting.stimuli_input_slew_type(
|
||||
SIM_SIGNAL_RISE)]);
|
||||
write_xml_attribute(fp, "slew_time",
|
||||
sim_setting.stimuli_input_slew(SIM_SIGNAL_RISE));
|
||||
fp << "/>"
|
||||
<< "\n";
|
||||
|
||||
fp << "\t\t\t" << "<fall";
|
||||
write_xml_attribute(fp, "slew_type", SIM_ACCURACY_TYPE_STRING[sim_setting.stimuli_input_slew_type(SIM_SIGNAL_FALL)]);
|
||||
write_xml_attribute(fp, "slew_time", sim_setting.stimuli_input_slew(SIM_SIGNAL_FALL));
|
||||
fp << "/>" << "\n";
|
||||
fp << "\t\t\t"
|
||||
<< "<fall";
|
||||
write_xml_attribute(
|
||||
fp, "slew_type",
|
||||
SIM_ACCURACY_TYPE_STRING[sim_setting.stimuli_input_slew_type(
|
||||
SIM_SIGNAL_FALL)]);
|
||||
write_xml_attribute(fp, "slew_time",
|
||||
sim_setting.stimuli_input_slew(SIM_SIGNAL_FALL));
|
||||
fp << "/>"
|
||||
<< "\n";
|
||||
|
||||
fp << "\t\t" << "</input>" << "\n";
|
||||
fp << "\t\t"
|
||||
<< "</input>"
|
||||
<< "\n";
|
||||
|
||||
fp << "\t" << "</stimulus>" << "\n";
|
||||
fp << "\t"
|
||||
<< "</stimulus>"
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* A writer to output a simulation setting to XML format
|
||||
*******************************************************************/
|
||||
void write_xml_simulation_setting(std::fstream& fp,
|
||||
const char* fname,
|
||||
const openfpga::SimulationSetting& sim_setting) {
|
||||
void write_xml_simulation_setting(
|
||||
std::fstream& fp, const char* fname,
|
||||
const openfpga::SimulationSetting& sim_setting) {
|
||||
/* Validate the file stream */
|
||||
openfpga::check_file_stream(fname, fp);
|
||||
|
||||
/* Write the root node <openfpga_simulation_setting>
|
||||
*/
|
||||
fp << "<openfpga_simulation_setting>" << "\n";
|
||||
fp << "<openfpga_simulation_setting>"
|
||||
<< "\n";
|
||||
|
||||
/* Write clock settings */
|
||||
/* Write clock settings */
|
||||
write_xml_clock_setting(fp, fname, sim_setting);
|
||||
|
||||
/* Write simulator option */
|
||||
/* Write simulator option */
|
||||
write_xml_simulator_option(fp, fname, sim_setting);
|
||||
|
||||
/* Write monte carlo simulation setting */
|
||||
/* Write monte carlo simulation setting */
|
||||
write_xml_monte_carlo(fp, fname, sim_setting);
|
||||
|
||||
/* Write measurement setting */
|
||||
/* Write measurement setting */
|
||||
write_xml_measurement(fp, fname, sim_setting);
|
||||
|
||||
/* Write stimuli setting */
|
||||
/* Write stimuli setting */
|
||||
write_xml_stimulus(fp, fname, sim_setting);
|
||||
|
||||
/* Write the root node <openfpga_simulation_setting> */
|
||||
fp << "</openfpga_simulation_setting>" << "\n";
|
||||
fp << "</openfpga_simulation_setting>"
|
||||
<< "\n";
|
||||
}
|
||||
|
|
|
@ -5,13 +5,14 @@
|
|||
* Include header files that are required by function declaration
|
||||
*******************************************************************/
|
||||
#include <fstream>
|
||||
|
||||
#include "simulation_setting.h"
|
||||
|
||||
/********************************************************************
|
||||
* Function declaration
|
||||
*******************************************************************/
|
||||
void write_xml_simulation_setting(std::fstream& fp,
|
||||
const char* fname,
|
||||
const openfpga::SimulationSetting& sim_setting);
|
||||
void write_xml_simulation_setting(
|
||||
std::fstream& fp, const char* fname,
|
||||
const openfpga::SimulationSetting& sim_setting);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -2,159 +2,224 @@
|
|||
* This file includes functions that outputs a technology library to XML format
|
||||
*******************************************************************/
|
||||
/* Headers from system goes first */
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
/* Headers from vtr util library */
|
||||
#include "vtr_log.h"
|
||||
#include "openfpga_digest.h"
|
||||
#include "vtr_log.h"
|
||||
|
||||
/* Headers from readarchopenfpga library */
|
||||
#include "write_xml_utils.h"
|
||||
#include "write_xml_technology_library.h"
|
||||
#include "write_xml_utils.h"
|
||||
|
||||
/********************************************************************
|
||||
* A writer to output a device model in a technology library to XML format
|
||||
*******************************************************************/
|
||||
static
|
||||
void write_xml_device_model(std::fstream& fp,
|
||||
const char* fname,
|
||||
const TechnologyLibrary& tech_lib,
|
||||
const TechnologyModelId& device_model) {
|
||||
static void write_xml_device_model(std::fstream& fp, const char* fname,
|
||||
const TechnologyLibrary& tech_lib,
|
||||
const TechnologyModelId& device_model) {
|
||||
/* Validate the file stream */
|
||||
openfpga::check_file_stream(fname, fp);
|
||||
|
||||
fp << "\t\t\t" << "<device_model";
|
||||
fp << "\t\t\t"
|
||||
<< "<device_model";
|
||||
|
||||
/* Write up name and type of the device model */
|
||||
write_xml_attribute(fp, "name", tech_lib.model_name(device_model).c_str());
|
||||
write_xml_attribute(fp, "type", TECH_LIB_MODEL_TYPE_STRING[tech_lib.model_type(device_model)]);
|
||||
write_xml_attribute(
|
||||
fp, "type", TECH_LIB_MODEL_TYPE_STRING[tech_lib.model_type(device_model)]);
|
||||
|
||||
fp << ">" << "\n";
|
||||
fp << ">"
|
||||
<< "\n";
|
||||
|
||||
/* Write library settings */
|
||||
fp << "\t\t\t\t" << "<lib";
|
||||
fp << "\t\t\t\t"
|
||||
<< "<lib";
|
||||
|
||||
write_xml_attribute(fp, "type", TECH_LIB_TYPE_STRING[tech_lib.model_lib_type(device_model)]);
|
||||
write_xml_attribute(
|
||||
fp, "type", TECH_LIB_TYPE_STRING[tech_lib.model_lib_type(device_model)]);
|
||||
|
||||
if (TECH_LIB_INDUSTRY == tech_lib.model_lib_type(device_model)) {
|
||||
write_xml_attribute(fp, "corner", tech_lib.model_corner(device_model).c_str());
|
||||
write_xml_attribute(fp, "corner",
|
||||
tech_lib.model_corner(device_model).c_str());
|
||||
}
|
||||
|
||||
write_xml_attribute(fp, "ref", tech_lib.model_ref(device_model).c_str());
|
||||
write_xml_attribute(fp, "path", tech_lib.model_lib_path(device_model).c_str());
|
||||
write_xml_attribute(fp, "path",
|
||||
tech_lib.model_lib_path(device_model).c_str());
|
||||
|
||||
fp << ">" << "\n";
|
||||
fp << ">"
|
||||
<< "\n";
|
||||
|
||||
/* Write design parameters. This is ONLY applicable to transistors */
|
||||
if (TECH_LIB_MODEL_TRANSISTOR == tech_lib.model_type(device_model)) {
|
||||
fp << "\t\t\t\t" << "<design";
|
||||
write_xml_attribute(fp, "vdd", std::to_string(tech_lib.model_vdd(device_model)).c_str());
|
||||
write_xml_attribute(fp, "pn_ratio", std::to_string(tech_lib.model_pn_ratio(device_model)).c_str());
|
||||
fp << ">" << "\n";
|
||||
fp << "\t\t\t\t"
|
||||
<< "<design";
|
||||
write_xml_attribute(
|
||||
fp, "vdd", std::to_string(tech_lib.model_vdd(device_model)).c_str());
|
||||
write_xml_attribute(
|
||||
fp, "pn_ratio",
|
||||
std::to_string(tech_lib.model_pn_ratio(device_model)).c_str());
|
||||
fp << ">"
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
/* Write PMOS and NMOS. This is ONLY applicable to transistors */
|
||||
if (TECH_LIB_MODEL_TRANSISTOR == tech_lib.model_type(device_model)) {
|
||||
fp << "\t\t\t\t" << "<pmos";
|
||||
write_xml_attribute(fp, "name", tech_lib.transistor_model_name(device_model, TECH_LIB_TRANSISTOR_PMOS).c_str());
|
||||
write_xml_attribute(fp, "chan_length", tech_lib.transistor_model_chan_length(device_model, TECH_LIB_TRANSISTOR_PMOS));
|
||||
write_xml_attribute(fp, "min_width", tech_lib.transistor_model_min_width(device_model, TECH_LIB_TRANSISTOR_PMOS));
|
||||
write_xml_attribute(fp, "max_width", tech_lib.transistor_model_max_width(device_model, TECH_LIB_TRANSISTOR_PMOS));
|
||||
if (TechnologyVariationId::INVALID() != tech_lib.transistor_model_variation(device_model, TECH_LIB_TRANSISTOR_PMOS)) {
|
||||
write_xml_attribute(fp, "variation", tech_lib.variation_name(tech_lib.transistor_model_variation(device_model, TECH_LIB_TRANSISTOR_PMOS)).c_str());
|
||||
fp << "\t\t\t\t"
|
||||
<< "<pmos";
|
||||
write_xml_attribute(
|
||||
fp, "name",
|
||||
tech_lib.transistor_model_name(device_model, TECH_LIB_TRANSISTOR_PMOS)
|
||||
.c_str());
|
||||
write_xml_attribute(fp, "chan_length",
|
||||
tech_lib.transistor_model_chan_length(
|
||||
device_model, TECH_LIB_TRANSISTOR_PMOS));
|
||||
write_xml_attribute(fp, "min_width",
|
||||
tech_lib.transistor_model_min_width(
|
||||
device_model, TECH_LIB_TRANSISTOR_PMOS));
|
||||
write_xml_attribute(fp, "max_width",
|
||||
tech_lib.transistor_model_max_width(
|
||||
device_model, TECH_LIB_TRANSISTOR_PMOS));
|
||||
if (TechnologyVariationId::INVALID() !=
|
||||
tech_lib.transistor_model_variation(device_model,
|
||||
TECH_LIB_TRANSISTOR_PMOS)) {
|
||||
write_xml_attribute(fp, "variation",
|
||||
tech_lib
|
||||
.variation_name(tech_lib.transistor_model_variation(
|
||||
device_model, TECH_LIB_TRANSISTOR_PMOS))
|
||||
.c_str());
|
||||
}
|
||||
fp << "/>" << "\n";
|
||||
fp << "/>"
|
||||
<< "\n";
|
||||
|
||||
fp << "\t\t\t\t" << "<nmos";
|
||||
write_xml_attribute(fp, "name", tech_lib.transistor_model_name(device_model, TECH_LIB_TRANSISTOR_NMOS).c_str());
|
||||
write_xml_attribute(fp, "chan_length", tech_lib.transistor_model_chan_length(device_model, TECH_LIB_TRANSISTOR_NMOS));
|
||||
write_xml_attribute(fp, "min_width", tech_lib.transistor_model_min_width(device_model, TECH_LIB_TRANSISTOR_NMOS));
|
||||
if (TechnologyVariationId::INVALID() != tech_lib.transistor_model_variation(device_model, TECH_LIB_TRANSISTOR_NMOS)) {
|
||||
write_xml_attribute(fp, "variation", tech_lib.variation_name(tech_lib.transistor_model_variation(device_model, TECH_LIB_TRANSISTOR_NMOS)).c_str());
|
||||
fp << "\t\t\t\t"
|
||||
<< "<nmos";
|
||||
write_xml_attribute(
|
||||
fp, "name",
|
||||
tech_lib.transistor_model_name(device_model, TECH_LIB_TRANSISTOR_NMOS)
|
||||
.c_str());
|
||||
write_xml_attribute(fp, "chan_length",
|
||||
tech_lib.transistor_model_chan_length(
|
||||
device_model, TECH_LIB_TRANSISTOR_NMOS));
|
||||
write_xml_attribute(fp, "min_width",
|
||||
tech_lib.transistor_model_min_width(
|
||||
device_model, TECH_LIB_TRANSISTOR_NMOS));
|
||||
if (TechnologyVariationId::INVALID() !=
|
||||
tech_lib.transistor_model_variation(device_model,
|
||||
TECH_LIB_TRANSISTOR_NMOS)) {
|
||||
write_xml_attribute(fp, "variation",
|
||||
tech_lib
|
||||
.variation_name(tech_lib.transistor_model_variation(
|
||||
device_model, TECH_LIB_TRANSISTOR_NMOS))
|
||||
.c_str());
|
||||
}
|
||||
fp << "/>" << "\n";
|
||||
fp << "/>"
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
/* Write RRAM device parameters. This is ONLY applicable to RRAM */
|
||||
if (TECH_LIB_MODEL_RRAM == tech_lib.model_type(device_model)) {
|
||||
fp << "\t\t\t\t" << "<rram";
|
||||
fp << "\t\t\t\t"
|
||||
<< "<rram";
|
||||
|
||||
write_xml_attribute(fp, "rlrs", tech_lib.rram_rlrs(device_model));
|
||||
write_xml_attribute(fp, "rhrs", tech_lib.rram_rhrs(device_model));
|
||||
|
||||
if (TechnologyVariationId::INVALID() != tech_lib.rram_variation(device_model)) {
|
||||
write_xml_attribute(fp, "variation", tech_lib.variation_name(tech_lib.rram_variation(device_model)).c_str());
|
||||
if (TechnologyVariationId::INVALID() !=
|
||||
tech_lib.rram_variation(device_model)) {
|
||||
write_xml_attribute(
|
||||
fp, "variation",
|
||||
tech_lib.variation_name(tech_lib.rram_variation(device_model)).c_str());
|
||||
}
|
||||
fp << "/>" << "\n";
|
||||
fp << "/>"
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
/* Finished XML dumping for this device model */
|
||||
fp << "\t\t\t" << "</device_model>" << "\n";
|
||||
fp << "\t\t\t"
|
||||
<< "</device_model>"
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* A writer to output a device variation in a technology library to XML format
|
||||
*******************************************************************/
|
||||
static
|
||||
void write_xml_device_variation(std::fstream& fp,
|
||||
const char* fname,
|
||||
const TechnologyLibrary& tech_lib,
|
||||
const TechnologyVariationId& device_variation) {
|
||||
static void write_xml_device_variation(
|
||||
std::fstream& fp, const char* fname, const TechnologyLibrary& tech_lib,
|
||||
const TechnologyVariationId& device_variation) {
|
||||
/* Validate the file stream */
|
||||
openfpga::check_file_stream(fname, fp);
|
||||
|
||||
fp << "\t\t\t" << "<variation";
|
||||
fp << "\t\t\t"
|
||||
<< "<variation";
|
||||
|
||||
/* Write up name of the device variation */
|
||||
write_xml_attribute(fp, "name", tech_lib.variation_name(device_variation).c_str());
|
||||
write_xml_attribute(fp, "abs_deviation", tech_lib.variation_abs_value(device_variation));
|
||||
write_xml_attribute(fp, "num_sigma", std::to_string(tech_lib.variation_num_sigma(device_variation)).c_str());
|
||||
write_xml_attribute(fp, "name",
|
||||
tech_lib.variation_name(device_variation).c_str());
|
||||
write_xml_attribute(fp, "abs_deviation",
|
||||
tech_lib.variation_abs_value(device_variation));
|
||||
write_xml_attribute(
|
||||
fp, "num_sigma",
|
||||
std::to_string(tech_lib.variation_num_sigma(device_variation)).c_str());
|
||||
|
||||
fp << "/>" << "\n";
|
||||
fp << "/>"
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* A writer to output a technology library to XML format
|
||||
* Note:
|
||||
* This function should be run after that the following methods of
|
||||
* TechnologyLibrary are executed
|
||||
* Note:
|
||||
* This function should be run after that the following methods of
|
||||
* TechnologyLibrary are executed
|
||||
* 1. link_models_to_variations();
|
||||
*******************************************************************/
|
||||
void write_xml_technology_library(std::fstream& fp,
|
||||
const char* fname,
|
||||
void write_xml_technology_library(std::fstream& fp, const char* fname,
|
||||
const TechnologyLibrary& tech_lib) {
|
||||
/* Validate the file stream */
|
||||
openfpga::check_file_stream(fname, fp);
|
||||
|
||||
/* Write the root node for technology_library,
|
||||
* we apply a tab becuase technology library is a subnode
|
||||
|
||||
/* Write the root node for technology_library,
|
||||
* we apply a tab becuase technology library is a subnode
|
||||
* under the root node <openfpga_arch>
|
||||
*/
|
||||
fp << "\t" << "<technology_library>" << "\n";
|
||||
fp << "\t"
|
||||
<< "<technology_library>"
|
||||
<< "\n";
|
||||
|
||||
/* Write device library node */
|
||||
fp << "\t\t" << "<device_library>" << "\n";
|
||||
|
||||
/* Write device model one by one */
|
||||
/* Write device library node */
|
||||
fp << "\t\t"
|
||||
<< "<device_library>"
|
||||
<< "\n";
|
||||
|
||||
/* Write device model one by one */
|
||||
for (const TechnologyModelId& device_model : tech_lib.models()) {
|
||||
write_xml_device_model(fp, fname, tech_lib, device_model);
|
||||
}
|
||||
|
||||
/* Finish writing device library node */
|
||||
fp << "\t\t" << "</device_library>" << "\n";
|
||||
/* Finish writing device library node */
|
||||
fp << "\t\t"
|
||||
<< "</device_library>"
|
||||
<< "\n";
|
||||
|
||||
/* Write variation library node */
|
||||
fp << "\t\t" << "<variation_library>" << "\n";
|
||||
/* Write variation library node */
|
||||
fp << "\t\t"
|
||||
<< "<variation_library>"
|
||||
<< "\n";
|
||||
|
||||
/* Write variation model one by one */
|
||||
/* Write variation model one by one */
|
||||
for (const TechnologyVariationId& variation : tech_lib.variations()) {
|
||||
write_xml_device_variation(fp, fname, tech_lib, variation);
|
||||
}
|
||||
|
||||
/* Finish writing variation library node */
|
||||
fp << "\t\t" << "</variation_library>" << "\n";
|
||||
/* Finish writing variation library node */
|
||||
fp << "\t\t"
|
||||
<< "</variation_library>"
|
||||
<< "\n";
|
||||
|
||||
/* Write the root node for circuit_library */
|
||||
fp << "\t" << "</technology_library>" << "\n";
|
||||
fp << "\t"
|
||||
<< "</technology_library>"
|
||||
<< "\n";
|
||||
}
|
||||
|
|
|
@ -5,13 +5,13 @@
|
|||
* Include header files that are required by function declaration
|
||||
*******************************************************************/
|
||||
#include <fstream>
|
||||
|
||||
#include "technology_library.h"
|
||||
|
||||
/********************************************************************
|
||||
* Function declaration
|
||||
*******************************************************************/
|
||||
void write_xml_technology_library(std::fstream& fp,
|
||||
const char* fname,
|
||||
void write_xml_technology_library(std::fstream& fp, const char* fname,
|
||||
const TechnologyLibrary& tech_lib);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -2,17 +2,17 @@
|
|||
* This file includes functions that outputs tile annotations to XML format
|
||||
*******************************************************************/
|
||||
/* Headers from system goes first */
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
/* Headers from vtr util library */
|
||||
#include "openfpga_digest.h"
|
||||
#include "vtr_assert.h"
|
||||
#include "vtr_log.h"
|
||||
#include "openfpga_digest.h"
|
||||
|
||||
/* Headers from readarchopenfpga library */
|
||||
#include "write_xml_utils.h"
|
||||
#include "write_xml_tile_annotation.h"
|
||||
#include "write_xml_utils.h"
|
||||
|
||||
/* namespace openfpga begins */
|
||||
namespace openfpga {
|
||||
|
@ -20,62 +20,92 @@ namespace openfpga {
|
|||
/********************************************************************
|
||||
* A writer to output a device variation in a technology library to XML format
|
||||
*******************************************************************/
|
||||
static
|
||||
void write_xml_tile_annotation_global_port(std::fstream& fp,
|
||||
const char* fname,
|
||||
const openfpga::TileAnnotation& tile_annotation,
|
||||
const TileGlobalPortId& global_port_id) {
|
||||
static void write_xml_tile_annotation_global_port(
|
||||
std::fstream& fp, const char* fname,
|
||||
const openfpga::TileAnnotation& tile_annotation,
|
||||
const TileGlobalPortId& global_port_id) {
|
||||
/* Validate the file stream */
|
||||
openfpga::check_file_stream(fname, fp);
|
||||
|
||||
fp << "\t\t" << "<global_port ";
|
||||
fp << "\t\t"
|
||||
<< "<global_port ";
|
||||
|
||||
write_xml_attribute(fp, "name", tile_annotation.global_port_name(global_port_id).c_str());
|
||||
write_xml_attribute(fp, "name",
|
||||
tile_annotation.global_port_name(global_port_id).c_str());
|
||||
|
||||
write_xml_attribute(fp, "is_clock", tile_annotation.global_port_is_clock(global_port_id));
|
||||
write_xml_attribute(fp, "is_clock",
|
||||
tile_annotation.global_port_is_clock(global_port_id));
|
||||
|
||||
write_xml_attribute(fp, "is_set", tile_annotation.global_port_is_set(global_port_id));
|
||||
write_xml_attribute(fp, "is_set",
|
||||
tile_annotation.global_port_is_set(global_port_id));
|
||||
|
||||
write_xml_attribute(fp, "is_reset", tile_annotation.global_port_is_reset(global_port_id));
|
||||
write_xml_attribute(fp, "is_reset",
|
||||
tile_annotation.global_port_is_reset(global_port_id));
|
||||
|
||||
write_xml_attribute(fp, "default_value", tile_annotation.global_port_default_value(global_port_id));
|
||||
|
||||
fp << ">" << "\n";
|
||||
write_xml_attribute(
|
||||
fp, "default_value",
|
||||
tile_annotation.global_port_default_value(global_port_id));
|
||||
|
||||
for (size_t tile_info_id = 0; tile_info_id < tile_annotation.global_port_tile_names(global_port_id).size(); ++tile_info_id) {
|
||||
fp << "\t\t\t" << "<tile ";
|
||||
write_xml_attribute(fp, "name", tile_annotation.global_port_tile_names(global_port_id)[tile_info_id].c_str());
|
||||
write_xml_attribute(fp, "port", generate_xml_port_name(tile_annotation.global_port_tile_ports(global_port_id)[tile_info_id]).c_str());
|
||||
write_xml_attribute(fp, "x", tile_annotation.global_port_tile_coordinates(global_port_id)[tile_info_id].x());
|
||||
write_xml_attribute(fp, "y", tile_annotation.global_port_tile_coordinates(global_port_id)[tile_info_id].y());
|
||||
fp << ">"
|
||||
<< "\n";
|
||||
|
||||
for (size_t tile_info_id = 0;
|
||||
tile_info_id <
|
||||
tile_annotation.global_port_tile_names(global_port_id).size();
|
||||
++tile_info_id) {
|
||||
fp << "\t\t\t"
|
||||
<< "<tile ";
|
||||
write_xml_attribute(
|
||||
fp, "name",
|
||||
tile_annotation.global_port_tile_names(global_port_id)[tile_info_id]
|
||||
.c_str());
|
||||
write_xml_attribute(
|
||||
fp, "port",
|
||||
generate_xml_port_name(
|
||||
tile_annotation.global_port_tile_ports(global_port_id)[tile_info_id])
|
||||
.c_str());
|
||||
write_xml_attribute(
|
||||
fp, "x",
|
||||
tile_annotation.global_port_tile_coordinates(global_port_id)[tile_info_id]
|
||||
.x());
|
||||
write_xml_attribute(
|
||||
fp, "y",
|
||||
tile_annotation.global_port_tile_coordinates(global_port_id)[tile_info_id]
|
||||
.y());
|
||||
fp << "/>";
|
||||
}
|
||||
|
||||
fp << "\t\t" << "</global_port>";
|
||||
fp << "\t\t"
|
||||
<< "</global_port>";
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* A writer to output tile annotations to XML format
|
||||
*******************************************************************/
|
||||
void write_xml_tile_annotations(std::fstream& fp,
|
||||
const char* fname,
|
||||
void write_xml_tile_annotations(std::fstream& fp, const char* fname,
|
||||
const TileAnnotation& tile_annotation) {
|
||||
/* 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
|
||||
|
||||
/* 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" << "<tile_annotations>" << "\n";
|
||||
fp << "\t"
|
||||
<< "<tile_annotations>"
|
||||
<< "\n";
|
||||
|
||||
/* Write device model one by one */
|
||||
for (const TileGlobalPortId& global_port_id : tile_annotation.global_ports()) {
|
||||
write_xml_tile_annotation_global_port(fp, fname, tile_annotation, global_port_id);
|
||||
/* Write device model one by one */
|
||||
for (const TileGlobalPortId& global_port_id :
|
||||
tile_annotation.global_ports()) {
|
||||
write_xml_tile_annotation_global_port(fp, fname, tile_annotation,
|
||||
global_port_id);
|
||||
}
|
||||
|
||||
/* Write the root node for pb_type annotations */
|
||||
fp << "\t" << "</tile_annotations>" << "\n";
|
||||
fp << "\t"
|
||||
<< "</tile_annotations>"
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
} /* namespace openfpga ends */
|
||||
} // namespace openfpga
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* Include header files that are required by function declaration
|
||||
*******************************************************************/
|
||||
#include <fstream>
|
||||
|
||||
#include "tile_annotation.h"
|
||||
|
||||
/********************************************************************
|
||||
|
@ -13,10 +14,9 @@
|
|||
/* namespace openfpga begins */
|
||||
namespace openfpga {
|
||||
|
||||
void write_xml_tile_annotations(std::fstream& fp,
|
||||
const char* fname,
|
||||
void write_xml_tile_annotations(std::fstream& fp, const char* fname,
|
||||
const TileAnnotation& tile_annotation);
|
||||
|
||||
} /* namespace openfpga ends */
|
||||
} // namespace openfpga
|
||||
|
||||
#endif
|
||||
|
|
|
@ -2,93 +2,87 @@
|
|||
* This file includes most utilized function to write an XML file
|
||||
*******************************************************************/
|
||||
/* Headers from system goes first */
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
/* Headers from vtrutil library */
|
||||
#include "vtr_assert.h"
|
||||
#include "vtr_assert.h"
|
||||
|
||||
/* Headers from openfpgautil library */
|
||||
#include "openfpga_digest.h"
|
||||
#include "openfpga_digest.h"
|
||||
|
||||
/* Headers from readarchopenfpga library */
|
||||
#include "write_xml_utils.h"
|
||||
#include "write_xml_utils.h"
|
||||
|
||||
/********************************************************************
|
||||
* A most utilized function to write an XML attribute to file
|
||||
*******************************************************************/
|
||||
void write_xml_attribute(std::fstream& fp,
|
||||
const char* attr,
|
||||
void write_xml_attribute(std::fstream& fp, const char* attr,
|
||||
const char* value) {
|
||||
/* Validate the file stream */
|
||||
openfpga::valid_file_stream(fp);
|
||||
|
||||
fp << " " << attr << "=\"" << value << "\"";
|
||||
fp << " " << attr << "=\"" << value << "\"";
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* A most utilized function to write an XML attribute to file
|
||||
* This accepts the value as a boolean
|
||||
* This accepts the value as a boolean
|
||||
*******************************************************************/
|
||||
void write_xml_attribute(std::fstream& fp,
|
||||
const char* attr,
|
||||
void write_xml_attribute(std::fstream& fp, const char* attr,
|
||||
const bool& value) {
|
||||
/* Validate the file stream */
|
||||
openfpga::valid_file_stream(fp);
|
||||
|
||||
fp << " " << attr << "=\"";
|
||||
if (true == value) {
|
||||
fp << "true";
|
||||
fp << "true";
|
||||
} else {
|
||||
VTR_ASSERT_SAFE(false == value);
|
||||
fp << "false";
|
||||
fp << "false";
|
||||
}
|
||||
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) {
|
||||
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 << "\"";
|
||||
fp << "\"";
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* A most utilized function to write an XML attribute to file
|
||||
* This accepts the value as a size_t
|
||||
*******************************************************************/
|
||||
void write_xml_attribute(std::fstream& fp,
|
||||
const char* attr,
|
||||
void write_xml_attribute(std::fstream& fp, const char* attr,
|
||||
const size_t& value) {
|
||||
/* Validate the file stream */
|
||||
openfpga::valid_file_stream(fp);
|
||||
|
||||
fp << " " << attr << "=\"";
|
||||
fp << value;
|
||||
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,
|
||||
void write_xml_attribute(std::fstream& fp, const char* attr,
|
||||
const float& value) {
|
||||
/* Validate the file stream */
|
||||
openfpga::valid_file_stream(fp);
|
||||
|
||||
fp << " " << attr << "=\"";
|
||||
fp << std::scientific << value;
|
||||
fp << "\"";
|
||||
fp << "\"";
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
|
|
|
@ -5,30 +5,23 @@
|
|||
* Include header files that are required by function declaration
|
||||
*******************************************************************/
|
||||
#include <fstream>
|
||||
|
||||
#include "circuit_library.h"
|
||||
#include "openfpga_port.h"
|
||||
#include "openfpga_port.h"
|
||||
|
||||
/********************************************************************
|
||||
* Function declaration
|
||||
*******************************************************************/
|
||||
void write_xml_attribute(std::fstream& fp,
|
||||
const char* attr,
|
||||
const char* value);
|
||||
void write_xml_attribute(std::fstream& fp, const char* attr, const char* value);
|
||||
|
||||
void write_xml_attribute(std::fstream& fp,
|
||||
const char* attr,
|
||||
const bool& value);
|
||||
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 int& value);
|
||||
|
||||
void write_xml_attribute(std::fstream& fp,
|
||||
const char* attr,
|
||||
void write_xml_attribute(std::fstream& fp, const char* attr,
|
||||
const float& value);
|
||||
|
||||
void write_xml_attribute(std::fstream& fp,
|
||||
const char* attr,
|
||||
void write_xml_attribute(std::fstream& fp, const char* attr,
|
||||
const size_t& value);
|
||||
|
||||
std::string generate_xml_port_name(const openfpga::BasicPort& pb_port);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/********************************************************************
|
||||
* Unit test functions to validate the correctness of
|
||||
* Unit test functions to validate the correctness of
|
||||
* 1. parser of data structures
|
||||
* 2. writer of data structures
|
||||
*******************************************************************/
|
||||
|
@ -17,21 +17,18 @@ int main(int argc, const char** argv) {
|
|||
VTR_ASSERT((2 == argc) || (3 == argc));
|
||||
|
||||
/* Parse the circuit library from an XML file */
|
||||
const openfpga::Arch& openfpga_arch = read_xml_openfpga_arch(argv[1]);
|
||||
const openfpga::Arch& openfpga_arch = read_xml_openfpga_arch(argv[1]);
|
||||
VTR_LOG("Parsed %lu circuit models from XML into circuit library.\n",
|
||||
openfpga_arch.circuit_lib.num_models());
|
||||
|
||||
/* Check the circuit library */
|
||||
check_circuit_library(openfpga_arch.circuit_lib);
|
||||
|
||||
|
||||
/* Output the circuit library to an XML file
|
||||
* This is optional only used when there is a second argument
|
||||
*/
|
||||
if (3 <= argc) {
|
||||
if (3 <= argc) {
|
||||
write_xml_openfpga_arch(argv[2], openfpga_arch);
|
||||
VTR_LOG("Echo the OpenFPGA architecture to an XML file: %s.\n",
|
||||
argv[2]);
|
||||
VTR_LOG("Echo the OpenFPGA architecture to an XML file: %s.\n", argv[2]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/********************************************************************
|
||||
* Unit test functions to validate the correctness of
|
||||
* Unit test functions to validate the correctness of
|
||||
* 1. parser of data structures
|
||||
* 2. writer of data structures
|
||||
*******************************************************************/
|
||||
|
@ -16,14 +16,14 @@ int main(int argc, const char** argv) {
|
|||
VTR_ASSERT((2 == argc) || (3 == argc));
|
||||
|
||||
/* Parse the simulation settings from an XML file */
|
||||
const openfpga::BitstreamSetting& openfpga_bitstream_setting = read_xml_openfpga_bitstream_settings(argv[1]);
|
||||
VTR_LOG("Parsed bitstream settings from XML %s.\n",
|
||||
argv[1]);
|
||||
const openfpga::BitstreamSetting& openfpga_bitstream_setting =
|
||||
read_xml_openfpga_bitstream_settings(argv[1]);
|
||||
VTR_LOG("Parsed bitstream settings from XML %s.\n", argv[1]);
|
||||
|
||||
/* Output the simulation settings to an XML file
|
||||
* This is optional only used when there is a second argument
|
||||
*/
|
||||
if (3 <= argc) {
|
||||
if (3 <= argc) {
|
||||
write_xml_openfpga_bitstream_settings(argv[2], openfpga_bitstream_setting);
|
||||
VTR_LOG("Echo the OpenFPGA bitstream settings to an XML file: %s.\n",
|
||||
argv[2]);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/********************************************************************
|
||||
* Unit test functions to validate the correctness of
|
||||
* Unit test functions to validate the correctness of
|
||||
* 1. parser of data structures
|
||||
* 2. writer of data structures
|
||||
*******************************************************************/
|
||||
|
@ -16,14 +16,14 @@ int main(int argc, const char** argv) {
|
|||
VTR_ASSERT((2 == argc) || (3 == argc));
|
||||
|
||||
/* Parse the simulation settings from an XML file */
|
||||
const openfpga::SimulationSetting& openfpga_sim_setting = read_xml_openfpga_simulation_settings(argv[1]);
|
||||
VTR_LOG("Parsed simulation settings from XML %s.\n",
|
||||
argv[1]);
|
||||
const openfpga::SimulationSetting& openfpga_sim_setting =
|
||||
read_xml_openfpga_simulation_settings(argv[1]);
|
||||
VTR_LOG("Parsed simulation settings from XML %s.\n", argv[1]);
|
||||
|
||||
/* Output the simulation settings to an XML file
|
||||
* This is optional only used when there is a second argument
|
||||
*/
|
||||
if (3 <= argc) {
|
||||
if (3 <= argc) {
|
||||
write_xml_openfpga_simulation_settings(argv[2], openfpga_sim_setting);
|
||||
VTR_LOG("Echo the OpenFPGA simulation settings to an XML file: %s.\n",
|
||||
argv[2]);
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
#include "bus_group.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "vtr_assert.h"
|
||||
#include "vtr_log.h"
|
||||
|
||||
#include "bus_group.h"
|
||||
|
||||
namespace openfpga { // Begin namespace openfpga
|
||||
namespace openfpga { // Begin namespace openfpga
|
||||
|
||||
/************************************************************************
|
||||
* Member functions for class BusGroup
|
||||
|
@ -14,9 +14,7 @@ namespace openfpga { // Begin namespace openfpga
|
|||
/************************************************************************
|
||||
* Constructors
|
||||
***********************************************************************/
|
||||
BusGroup::BusGroup() {
|
||||
return;
|
||||
}
|
||||
BusGroup::BusGroup() { return; }
|
||||
|
||||
/************************************************************************
|
||||
* Public Accessors : aggregates
|
||||
|
@ -26,67 +24,68 @@ BusGroup::bus_group_range BusGroup::buses() const {
|
|||
}
|
||||
|
||||
/************************************************************************
|
||||
* Public Accessors : Basic data query
|
||||
* Public Accessors : Basic data query
|
||||
***********************************************************************/
|
||||
openfpga::BasicPort BusGroup::bus_port(const BusGroupId& bus_id) const {
|
||||
VTR_ASSERT(valid_bus_id(bus_id));
|
||||
return bus_ports_[bus_id];
|
||||
return bus_ports_[bus_id];
|
||||
}
|
||||
|
||||
bool BusGroup::is_big_endian(const BusGroupId& bus_id) const {
|
||||
VTR_ASSERT(valid_bus_id(bus_id));
|
||||
return bus_big_endians_[bus_id];
|
||||
return bus_big_endians_[bus_id];
|
||||
}
|
||||
|
||||
std::vector<BusPinId> BusGroup::bus_pins(const BusGroupId& bus_id) const {
|
||||
VTR_ASSERT(valid_bus_id(bus_id));
|
||||
return bus_pin_ids_[bus_id];
|
||||
return bus_pin_ids_[bus_id];
|
||||
}
|
||||
|
||||
int BusGroup::pin_index(const BusPinId& pin_id) const {
|
||||
VTR_ASSERT(valid_pin_id(pin_id));
|
||||
return pin_indices_[pin_id];
|
||||
return pin_indices_[pin_id];
|
||||
}
|
||||
|
||||
std::string BusGroup::pin_name(const BusPinId& pin_id) const {
|
||||
VTR_ASSERT(valid_pin_id(pin_id));
|
||||
return pin_names_[pin_id];
|
||||
return pin_names_[pin_id];
|
||||
}
|
||||
|
||||
BusGroupId BusGroup::find_pin_bus(const std::string& pin_name) const {
|
||||
std::map<std::string, BusPinId>::const_iterator result = pin_name2id_map_.find(pin_name);
|
||||
std::map<std::string, BusPinId>::const_iterator result =
|
||||
pin_name2id_map_.find(pin_name);
|
||||
if (result == pin_name2id_map_.end()) {
|
||||
/* Not found, return an invalid id */
|
||||
return BusGroupId::INVALID();
|
||||
}
|
||||
/* Found, we should get the parent bus */
|
||||
BusPinId pin_id = result->second;
|
||||
BusPinId pin_id = result->second;
|
||||
return pin_parent_bus_ids_[pin_id];
|
||||
}
|
||||
|
||||
BusGroupId BusGroup::find_bus(const std::string& bus_name) const {
|
||||
std::map<std::string, BusGroupId>::const_iterator result = bus_name2id_map_.find(bus_name);
|
||||
std::map<std::string, BusGroupId>::const_iterator result =
|
||||
bus_name2id_map_.find(bus_name);
|
||||
if (result == bus_name2id_map_.end()) {
|
||||
/* Not found, return an invalid id */
|
||||
return BusGroupId::INVALID();
|
||||
}
|
||||
/* Found, we should get the parent bus */
|
||||
return result->second;
|
||||
return result->second;
|
||||
}
|
||||
|
||||
BusPinId BusGroup::find_pin(const std::string& pin_name) const {
|
||||
std::map<std::string, BusPinId>::const_iterator result = pin_name2id_map_.find(pin_name);
|
||||
std::map<std::string, BusPinId>::const_iterator result =
|
||||
pin_name2id_map_.find(pin_name);
|
||||
if (result == pin_name2id_map_.end()) {
|
||||
/* Not found, return an invalid id */
|
||||
return BusPinId::INVALID();
|
||||
}
|
||||
/* Found, we should get the parent bus */
|
||||
return result->second;
|
||||
return result->second;
|
||||
}
|
||||
|
||||
bool BusGroup::empty() const {
|
||||
return 0 == bus_ids_.size();
|
||||
}
|
||||
bool BusGroup::empty() const { return 0 == bus_ids_.size(); }
|
||||
|
||||
/************************************************************************
|
||||
* Public Mutators
|
||||
|
@ -108,7 +107,7 @@ void BusGroup::reserve_pins(const size_t& num_pins) {
|
|||
BusGroupId BusGroup::create_bus(const openfpga::BasicPort& bus_port) {
|
||||
/* Create a new id */
|
||||
BusGroupId bus_id = BusGroupId(bus_ids_.size());
|
||||
|
||||
|
||||
bus_ids_.push_back(bus_id);
|
||||
bus_ports_.push_back(bus_port);
|
||||
bus_big_endians_.push_back(true);
|
||||
|
@ -119,14 +118,16 @@ BusGroupId BusGroup::create_bus(const openfpga::BasicPort& bus_port) {
|
|||
if (result == bus_name2id_map_.end()) {
|
||||
bus_name2id_map_[bus_port.get_name()] = bus_id;
|
||||
} else {
|
||||
VTR_LOG_ERROR("Duplicated bus name '%s' in bus group", bus_port.get_name().c_str());
|
||||
VTR_LOG_ERROR("Duplicated bus name '%s' in bus group",
|
||||
bus_port.get_name().c_str());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
return bus_id;
|
||||
}
|
||||
|
||||
void BusGroup::set_bus_big_endian(const BusGroupId& bus_id, const bool& big_endian) {
|
||||
void BusGroup::set_bus_big_endian(const BusGroupId& bus_id,
|
||||
const bool& big_endian) {
|
||||
VTR_ASSERT(valid_bus_id(bus_id));
|
||||
bus_big_endians_[bus_id] = big_endian;
|
||||
}
|
||||
|
@ -134,7 +135,7 @@ void BusGroup::set_bus_big_endian(const BusGroupId& bus_id, const bool& big_endi
|
|||
BusPinId BusGroup::create_pin(const BusGroupId& bus_id, const int& index) {
|
||||
/* Create a new id */
|
||||
BusPinId pin_id = BusPinId(pin_ids_.size());
|
||||
|
||||
|
||||
pin_ids_.push_back(pin_id);
|
||||
|
||||
pin_indices_.push_back(index);
|
||||
|
@ -143,7 +144,7 @@ BusPinId BusGroup::create_pin(const BusGroupId& bus_id, const int& index) {
|
|||
/* Register the pin to the bus */
|
||||
VTR_ASSERT(valid_bus_id(bus_id));
|
||||
pin_parent_bus_ids_.push_back(bus_id);
|
||||
|
||||
|
||||
/* If the pin index is beyond the range of the bus_pin_ids, resize it */
|
||||
if (size_t(index) >= bus_pin_ids_[bus_id].size()) {
|
||||
bus_pin_ids_[bus_id].resize(index + 1);
|
||||
|
@ -153,7 +154,6 @@ BusPinId BusGroup::create_pin(const BusGroupId& bus_id, const int& index) {
|
|||
return pin_id;
|
||||
}
|
||||
|
||||
|
||||
void BusGroup::set_pin_name(const BusPinId& pin_id, const std::string& name) {
|
||||
VTR_ASSERT(valid_pin_id(pin_id));
|
||||
pin_names_[pin_id] = name;
|
||||
|
@ -169,14 +169,14 @@ void BusGroup::set_pin_name(const BusPinId& pin_id, const std::string& name) {
|
|||
}
|
||||
|
||||
/************************************************************************
|
||||
* Internal invalidators/validators
|
||||
* Internal invalidators/validators
|
||||
***********************************************************************/
|
||||
bool BusGroup::valid_bus_id(const BusGroupId& bus_id) const {
|
||||
return ( size_t(bus_id) < bus_ids_.size() ) && ( bus_id == bus_ids_[bus_id] );
|
||||
return (size_t(bus_id) < bus_ids_.size()) && (bus_id == bus_ids_[bus_id]);
|
||||
}
|
||||
|
||||
bool BusGroup::valid_pin_id(const BusPinId& pin_id) const {
|
||||
return ( size_t(pin_id) < pin_ids_.size() ) && ( pin_id == pin_ids_[pin_id] );
|
||||
return (size_t(pin_id) < pin_ids_.size()) && (pin_id == pin_ids_[pin_id]);
|
||||
}
|
||||
|
||||
} // End of namespace openfpga
|
||||
} // End of namespace openfpga
|
||||
|
|
|
@ -4,19 +4,18 @@
|
|||
/********************************************************************
|
||||
* This file include the declaration of pin constraints
|
||||
*******************************************************************/
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <array>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
/* Headers from vtrutil library */
|
||||
#include "vtr_vector.h"
|
||||
|
||||
/* Headers from openfpgautil library */
|
||||
#include "bus_group_fwd.h"
|
||||
#include "openfpga_port.h"
|
||||
|
||||
#include "bus_group_fwd.h"
|
||||
|
||||
namespace openfpga { // Begin namespace openfpga
|
||||
namespace openfpga { // Begin namespace openfpga
|
||||
|
||||
/********************************************************************
|
||||
* A data structure to describe the bus-to-pin mapping
|
||||
|
@ -36,99 +35,103 @@ namespace openfpga { // Begin namespace openfpga
|
|||
*
|
||||
*******************************************************************/
|
||||
class BusGroup {
|
||||
public: /* Types */
|
||||
typedef vtr::vector<BusGroupId, BusGroupId>::const_iterator bus_group_iterator;
|
||||
typedef vtr::vector<BusPinId, BusPinId>::const_iterator bus_pin_iterator;
|
||||
/* Create range */
|
||||
typedef vtr::Range<bus_group_iterator> bus_group_range;
|
||||
typedef vtr::Range<bus_pin_iterator> bus_pin_range;
|
||||
public: /* Constructors */
|
||||
BusGroup();
|
||||
public: /* Accessors: aggregates */
|
||||
bus_group_range buses() const;
|
||||
public: /* Public Accessors: Basic data query */
|
||||
/** Get port information of a bus with a given id */
|
||||
BasicPort bus_port(const BusGroupId& bus_id) const;
|
||||
public: /* Types */
|
||||
typedef vtr::vector<BusGroupId, BusGroupId>::const_iterator
|
||||
bus_group_iterator;
|
||||
typedef vtr::vector<BusPinId, BusPinId>::const_iterator bus_pin_iterator;
|
||||
/* Create range */
|
||||
typedef vtr::Range<bus_group_iterator> bus_group_range;
|
||||
typedef vtr::Range<bus_pin_iterator> bus_pin_range;
|
||||
|
||||
/* Check if a bus follows big endian */
|
||||
bool is_big_endian(const BusGroupId& bus_id) const;
|
||||
public: /* Constructors */
|
||||
BusGroup();
|
||||
|
||||
/* Get the pins under a specific bus */
|
||||
std::vector<BusPinId> bus_pins(const BusGroupId& bus_id) const;
|
||||
public: /* Accessors: aggregates */
|
||||
bus_group_range buses() const;
|
||||
|
||||
/* Get the index of a pin */
|
||||
int pin_index(const BusPinId& pin_id) const;
|
||||
public: /* Public Accessors: Basic data query */
|
||||
/** Get port information of a bus with a given id */
|
||||
BasicPort bus_port(const BusGroupId& bus_id) const;
|
||||
|
||||
/* Get the name of a pin */
|
||||
std::string pin_name(const BusPinId& pin_id) const;
|
||||
/* Check if a bus follows big endian */
|
||||
bool is_big_endian(const BusGroupId& bus_id) const;
|
||||
|
||||
/* Find the bus that a pin belongs to */
|
||||
BusGroupId find_pin_bus(const std::string& pin_name) const;
|
||||
/* Get the pins under a specific bus */
|
||||
std::vector<BusPinId> bus_pins(const BusGroupId& bus_id) const;
|
||||
|
||||
/* Find the bus id with a given name */
|
||||
BusGroupId find_bus(const std::string& bus_name) const;
|
||||
/* Get the index of a pin */
|
||||
int pin_index(const BusPinId& pin_id) const;
|
||||
|
||||
/* Find the pin id with a given name */
|
||||
BusPinId find_pin(const std::string& pin_name) const;
|
||||
/* Get the name of a pin */
|
||||
std::string pin_name(const BusPinId& pin_id) const;
|
||||
|
||||
/* Check if there are any buses */
|
||||
bool empty() const;
|
||||
/* Find the bus that a pin belongs to */
|
||||
BusGroupId find_pin_bus(const std::string& pin_name) const;
|
||||
|
||||
public: /* Public Mutators */
|
||||
/* Reserve a number of buses to be memory efficent */
|
||||
void reserve_buses(const size_t& num_buses);
|
||||
/* Find the bus id with a given name */
|
||||
BusGroupId find_bus(const std::string& bus_name) const;
|
||||
|
||||
/* Reserve a number of pins to be memory efficent */
|
||||
void reserve_pins(const size_t& num_pins);
|
||||
/* Find the pin id with a given name */
|
||||
BusPinId find_pin(const std::string& pin_name) const;
|
||||
|
||||
/* Add a bus to storage */
|
||||
BusGroupId create_bus(const openfpga::BasicPort& bus_port);
|
||||
/* Check if there are any buses */
|
||||
bool empty() const;
|
||||
|
||||
/* Set endianness for a bus; If not set, by default it assumes big-endian */
|
||||
void set_bus_big_endian(const BusGroupId& bus_id, const bool& big_endian);
|
||||
public: /* Public Mutators */
|
||||
/* Reserve a number of buses to be memory efficent */
|
||||
void reserve_buses(const size_t& num_buses);
|
||||
|
||||
/* Add a pin to a bus, with a given index in the bus, e.g., A[1] in A[0:2] */
|
||||
BusPinId create_pin(const BusGroupId& bus_id, const int& index);
|
||||
/* Reserve a number of pins to be memory efficent */
|
||||
void reserve_pins(const size_t& num_pins);
|
||||
|
||||
/* Set the name for a pin */
|
||||
void set_pin_name(const BusPinId& pin_id, const std::string& name);
|
||||
/* Add a bus to storage */
|
||||
BusGroupId create_bus(const openfpga::BasicPort& bus_port);
|
||||
|
||||
public: /* Public invalidators/validators */
|
||||
/* Show if the bus id is a valid for data queries */
|
||||
bool valid_bus_id(const BusGroupId& bus_id) const;
|
||||
/* Set endianness for a bus; If not set, by default it assumes big-endian */
|
||||
void set_bus_big_endian(const BusGroupId& bus_id, const bool& big_endian);
|
||||
|
||||
/* Show if the pin id is a valid for data queries */
|
||||
bool valid_pin_id(const BusPinId& pin_id) const;
|
||||
/* Add a pin to a bus, with a given index in the bus, e.g., A[1] in A[0:2] */
|
||||
BusPinId create_pin(const BusGroupId& bus_id, const int& index);
|
||||
|
||||
private: /* Internal data */
|
||||
/* Unique ids for each bus */
|
||||
vtr::vector<BusGroupId, BusGroupId> bus_ids_;
|
||||
/* Set the name for a pin */
|
||||
void set_pin_name(const BusPinId& pin_id, const std::string& name);
|
||||
|
||||
/* Port information of each bus */
|
||||
vtr::vector<BusGroupId, BasicPort> bus_ports_;
|
||||
public: /* Public invalidators/validators */
|
||||
/* Show if the bus id is a valid for data queries */
|
||||
bool valid_bus_id(const BusGroupId& bus_id) const;
|
||||
|
||||
/* Endianness of each bus: big endian by default */
|
||||
vtr::vector<BusGroupId, bool> bus_big_endians_;
|
||||
/* Show if the pin id is a valid for data queries */
|
||||
bool valid_pin_id(const BusPinId& pin_id) const;
|
||||
|
||||
/* Indices of each pin under each bus */
|
||||
vtr::vector<BusGroupId, std::vector<BusPinId>> bus_pin_ids_;
|
||||
private: /* Internal data */
|
||||
/* Unique ids for each bus */
|
||||
vtr::vector<BusGroupId, BusGroupId> bus_ids_;
|
||||
|
||||
/* Unique ids for each pin */
|
||||
vtr::vector<BusPinId, BusPinId> pin_ids_;
|
||||
/* Port information of each bus */
|
||||
vtr::vector<BusGroupId, BasicPort> bus_ports_;
|
||||
|
||||
/* Index for each pin */
|
||||
vtr::vector<BusPinId, int> pin_indices_;
|
||||
/* Endianness of each bus: big endian by default */
|
||||
vtr::vector<BusGroupId, bool> bus_big_endians_;
|
||||
|
||||
/* Name of each pin under each bus */
|
||||
vtr::vector<BusPinId, std::string> pin_names_;
|
||||
/* Indices of each pin under each bus */
|
||||
vtr::vector<BusGroupId, std::vector<BusPinId>> bus_pin_ids_;
|
||||
|
||||
/* Parent bus of each pin */
|
||||
vtr::vector<BusPinId, BusGroupId> pin_parent_bus_ids_;
|
||||
/* Unique ids for each pin */
|
||||
vtr::vector<BusPinId, BusPinId> pin_ids_;
|
||||
|
||||
/* Fast look-up */
|
||||
std::map<std::string, BusGroupId> bus_name2id_map_;
|
||||
std::map<std::string, BusPinId> pin_name2id_map_;
|
||||
/* Index for each pin */
|
||||
vtr::vector<BusPinId, int> pin_indices_;
|
||||
|
||||
/* Name of each pin under each bus */
|
||||
vtr::vector<BusPinId, std::string> pin_names_;
|
||||
|
||||
/* Parent bus of each pin */
|
||||
vtr::vector<BusPinId, BusGroupId> pin_parent_bus_ids_;
|
||||
|
||||
/* Fast look-up */
|
||||
std::map<std::string, BusGroupId> bus_name2id_map_;
|
||||
std::map<std::string, BusPinId> pin_name2id_map_;
|
||||
};
|
||||
|
||||
} // End of namespace openfpga
|
||||
} // End of namespace openfpga
|
||||
#endif
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
/************************************************************************
|
||||
* A header file for BusGroup class, including critical data declaration
|
||||
* Please include this file only for using any PinConstraints data structure
|
||||
* Refer to bus_group.h for more details
|
||||
* Refer to bus_group.h for more details
|
||||
***********************************************************************/
|
||||
|
||||
/************************************************************************
|
||||
* Create strong id for BusGroup to avoid illegal type casting
|
||||
* Create strong id for BusGroup to avoid illegal type casting
|
||||
***********************************************************************/
|
||||
#ifndef BUS_GROUP_FWD_H
|
||||
#define BUS_GROUP_FWD_H
|
||||
|
||||
#include "vtr_strong_id.h"
|
||||
|
||||
namespace openfpga { // Begin namespace openfpga
|
||||
namespace openfpga { // Begin namespace openfpga
|
||||
|
||||
struct bus_group_id_tag;
|
||||
struct bus_pin_id_tag;
|
||||
|
@ -23,6 +23,6 @@ typedef vtr::StrongId<bus_pin_id_tag> BusPinId;
|
|||
/* Short declaration of class */
|
||||
class BusGroup;
|
||||
|
||||
} // End of namespace openfpga
|
||||
} // End of namespace openfpga
|
||||
|
||||
#endif
|
||||
|
|
|
@ -18,31 +18,31 @@
|
|||
|
||||
/* Headers from libarchfpga */
|
||||
#include "arch_error.h"
|
||||
#include "read_xml_util.h"
|
||||
|
||||
#include "bus_group_xml_constants.h"
|
||||
#include "read_xml_bus_group.h"
|
||||
#include "read_xml_util.h"
|
||||
|
||||
namespace openfpga { // Begin namespace openfpga
|
||||
namespace openfpga { // Begin namespace openfpga
|
||||
|
||||
/********************************************************************
|
||||
* Parse XML codes of a <pin> to an object of BusGroup
|
||||
*******************************************************************/
|
||||
static
|
||||
void read_xml_pin(pugi::xml_node& xml_pin,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
BusGroup& bus_group,
|
||||
const BusGroupId& bus_id) {
|
||||
static void read_xml_pin(pugi::xml_node& xml_pin,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
BusGroup& bus_group, const BusGroupId& bus_id) {
|
||||
if (false == bus_group.valid_bus_id(bus_id)) {
|
||||
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_pin),
|
||||
"Invalid id of a bus group!\n");
|
||||
}
|
||||
|
||||
int pin_index = get_attribute(xml_pin, XML_PIN_INDEX_ATTRIBUTE_NAME, loc_data).as_int();
|
||||
std::string pin_name = get_attribute(xml_pin, XML_PIN_NAME_ATTRIBUTE_NAME, loc_data).as_string();
|
||||
int pin_index =
|
||||
get_attribute(xml_pin, XML_PIN_INDEX_ATTRIBUTE_NAME, loc_data).as_int();
|
||||
std::string pin_name =
|
||||
get_attribute(xml_pin, XML_PIN_NAME_ATTRIBUTE_NAME, loc_data).as_string();
|
||||
|
||||
/* Before update storage, check if the pin index is in the range */
|
||||
BasicPort pin_port(bus_group.bus_port(bus_id).get_name(), pin_index, pin_index);
|
||||
BasicPort pin_port(bus_group.bus_port(bus_id).get_name(), pin_index,
|
||||
pin_index);
|
||||
if (!bus_group.bus_port(bus_id).contained(pin_port)) {
|
||||
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_pin),
|
||||
"Pin index is out of range of the bus port width!\n");
|
||||
|
@ -55,12 +55,11 @@ void read_xml_pin(pugi::xml_node& xml_pin,
|
|||
/********************************************************************
|
||||
* Parse XML codes of a <bus> to an object of BusGroup
|
||||
*******************************************************************/
|
||||
static
|
||||
void read_xml_bus(pugi::xml_node& xml_bus,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
BusGroup& bus_group) {
|
||||
|
||||
openfpga::PortParser port_parser(get_attribute(xml_bus, XML_BUS_PORT_ATTRIBUTE_NAME, loc_data).as_string());
|
||||
static void read_xml_bus(pugi::xml_node& xml_bus,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
BusGroup& bus_group) {
|
||||
openfpga::PortParser port_parser(
|
||||
get_attribute(xml_bus, XML_BUS_PORT_ATTRIBUTE_NAME, loc_data).as_string());
|
||||
|
||||
/* Create a new bus in the storage */
|
||||
BusGroupId bus_id = bus_group.create_bus(port_parser.port());
|
||||
|
@ -77,7 +76,10 @@ void read_xml_bus(pugi::xml_node& xml_bus,
|
|||
}
|
||||
|
||||
/* Find big endian */
|
||||
bus_group.set_bus_big_endian(bus_id, get_attribute(xml_bus, XML_BUS_BIG_ENDIAN_ATTRIBUTE_NAME, loc_data, pugiutil::OPTIONAL).as_bool(true));
|
||||
bus_group.set_bus_big_endian(
|
||||
bus_id, get_attribute(xml_bus, XML_BUS_BIG_ENDIAN_ATTRIBUTE_NAME, loc_data,
|
||||
pugiutil::OPTIONAL)
|
||||
.as_bool(true));
|
||||
|
||||
for (pugi::xml_node xml_pin : xml_bus.children()) {
|
||||
/* Error out if the XML child has an invalid name! */
|
||||
|
@ -85,14 +87,13 @@ void read_xml_bus(pugi::xml_node& xml_bus,
|
|||
bad_tag(xml_pin, loc_data, xml_bus, {XML_PIN_NODE_NAME});
|
||||
}
|
||||
read_xml_pin(xml_pin, loc_data, bus_group, bus_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Parse XML codes about <bus_group> to an object of BusGroup
|
||||
*******************************************************************/
|
||||
BusGroup read_xml_bus_group(const char* fname) {
|
||||
|
||||
vtr::ScopedStartFinishTimer timer("Read Bus Group");
|
||||
|
||||
BusGroup bus_group;
|
||||
|
@ -104,16 +105,19 @@ BusGroup read_xml_bus_group(const char* fname) {
|
|||
try {
|
||||
loc_data = pugiutil::load_xml(doc, fname);
|
||||
|
||||
pugi::xml_node xml_root = get_single_child(doc, XML_BUS_GROUP_NODE_NAME, loc_data);
|
||||
pugi::xml_node xml_root =
|
||||
get_single_child(doc, XML_BUS_GROUP_NODE_NAME, loc_data);
|
||||
|
||||
size_t num_buses = std::distance(xml_root.children().begin(), xml_root.children().end());
|
||||
size_t num_buses =
|
||||
std::distance(xml_root.children().begin(), xml_root.children().end());
|
||||
|
||||
/* Count the total number of pins */
|
||||
size_t num_pins = 0;
|
||||
for (pugi::xml_node xml_bus : xml_root.children()) {
|
||||
num_pins += std::distance(xml_bus.children().begin(), xml_bus.children().end());
|
||||
num_pins +=
|
||||
std::distance(xml_bus.children().begin(), xml_bus.children().end());
|
||||
}
|
||||
|
||||
|
||||
/* Reserve memory space for the buses */
|
||||
bus_group.reserve_buses(num_buses);
|
||||
/* Reserve memory space for the pins */
|
||||
|
@ -125,13 +129,12 @@ BusGroup read_xml_bus_group(const char* fname) {
|
|||
bad_tag(xml_bus, loc_data, xml_root, {XML_BUS_NODE_NAME});
|
||||
}
|
||||
read_xml_bus(xml_bus, loc_data, bus_group);
|
||||
}
|
||||
}
|
||||
} catch (pugiutil::XmlError& e) {
|
||||
archfpga_throw(fname, e.line(),
|
||||
"%s", e.what());
|
||||
archfpga_throw(fname, e.line(), "%s", e.what());
|
||||
}
|
||||
|
||||
return bus_group;
|
||||
return bus_group;
|
||||
}
|
||||
|
||||
} // End of namespace openfpga
|
||||
} // End of namespace openfpga
|
||||
|
|
|
@ -4,18 +4,18 @@
|
|||
/********************************************************************
|
||||
* Include header files that are required by function declaration
|
||||
*******************************************************************/
|
||||
#include "pugixml_util.hpp"
|
||||
#include "pugixml.hpp"
|
||||
#include "bus_group.h"
|
||||
#include "pugixml.hpp"
|
||||
#include "pugixml_util.hpp"
|
||||
|
||||
/********************************************************************
|
||||
* Function declaration
|
||||
*******************************************************************/
|
||||
|
||||
namespace openfpga { // Begin namespace openfpga
|
||||
namespace openfpga { // Begin namespace openfpga
|
||||
|
||||
BusGroup read_xml_bus_group(const char* fname);
|
||||
|
||||
} // End of namespace openfpga
|
||||
} // End of namespace openfpga
|
||||
|
||||
#endif
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
* This file includes functions that outputs a bus group object to XML format
|
||||
*******************************************************************/
|
||||
/* Headers from system goes first */
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
/* Headers from vtr util library */
|
||||
#include "vtr_assert.h"
|
||||
|
@ -14,25 +14,23 @@
|
|||
#include "openfpga_digest.h"
|
||||
|
||||
/* Headers from arch openfpga library */
|
||||
#include "write_xml_utils.h"
|
||||
#include "write_xml_utils.h"
|
||||
|
||||
/* Headers from pin constraint library */
|
||||
#include "bus_group_xml_constants.h"
|
||||
#include "write_xml_bus_group.h"
|
||||
|
||||
namespace openfpga { // Begin namespace openfpga
|
||||
namespace openfpga { // Begin namespace openfpga
|
||||
|
||||
/********************************************************************
|
||||
* A writer to output a bus to XML format
|
||||
*
|
||||
* Return 0 if successful
|
||||
* Return 1 if there are more serious bugs in the architecture
|
||||
* Return 1 if there are more serious bugs in the architecture
|
||||
* Return 2 if fail when creating files
|
||||
*******************************************************************/
|
||||
static
|
||||
int write_xml_bus(std::fstream& fp,
|
||||
const BusGroup& bus_group,
|
||||
const BusGroupId& bus_id) {
|
||||
static int write_xml_bus(std::fstream& fp, const BusGroup& bus_group,
|
||||
const BusGroupId& bus_id) {
|
||||
/* Validate the file stream */
|
||||
if (false == openfpga::valid_file_stream(fp)) {
|
||||
return 2;
|
||||
|
@ -45,24 +43,32 @@ int write_xml_bus(std::fstream& fp,
|
|||
return 1;
|
||||
}
|
||||
|
||||
write_xml_attribute(fp, XML_BUS_PORT_ATTRIBUTE_NAME, generate_xml_port_name(bus_group.bus_port(bus_id)).c_str());
|
||||
write_xml_attribute(fp, XML_BUS_BIG_ENDIAN_ATTRIBUTE_NAME, bus_group.is_big_endian(bus_id));
|
||||
fp << ">" << "\n";
|
||||
write_xml_attribute(
|
||||
fp, XML_BUS_PORT_ATTRIBUTE_NAME,
|
||||
generate_xml_port_name(bus_group.bus_port(bus_id)).c_str());
|
||||
write_xml_attribute(fp, XML_BUS_BIG_ENDIAN_ATTRIBUTE_NAME,
|
||||
bus_group.is_big_endian(bus_id));
|
||||
fp << ">"
|
||||
<< "\n";
|
||||
|
||||
/* Output all the pins under this bus */
|
||||
for (const BusPinId& pin_id : bus_group.bus_pins(bus_id)) {
|
||||
openfpga::write_tab_to_file(fp, 2);
|
||||
fp << "<" << XML_PIN_NODE_NAME << "";
|
||||
|
||||
write_xml_attribute(fp, XML_PIN_INDEX_ATTRIBUTE_NAME, bus_group.pin_index(pin_id));
|
||||
write_xml_attribute(fp, XML_PIN_NAME_ATTRIBUTE_NAME, bus_group.pin_name(pin_id).c_str());
|
||||
write_xml_attribute(fp, XML_PIN_INDEX_ATTRIBUTE_NAME,
|
||||
bus_group.pin_index(pin_id));
|
||||
write_xml_attribute(fp, XML_PIN_NAME_ATTRIBUTE_NAME,
|
||||
bus_group.pin_name(pin_id).c_str());
|
||||
|
||||
fp << "/>" << "\n";
|
||||
fp << "/>"
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
openfpga::write_tab_to_file(fp, 1);
|
||||
fp << "</" << XML_BUS_NODE_NAME << "";
|
||||
fp << ">" << "\n";
|
||||
fp << ">"
|
||||
<< "\n";
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -71,12 +77,10 @@ int write_xml_bus(std::fstream& fp,
|
|||
* A writer to output a bus group object to XML format
|
||||
*
|
||||
* Return 0 if successful
|
||||
* Return 1 if there are more serious bugs in the architecture
|
||||
* Return 1 if there are more serious bugs in the architecture
|
||||
* Return 2 if fail when creating files
|
||||
*******************************************************************/
|
||||
int write_xml_bus_group(const char* fname,
|
||||
const BusGroup& bus_group) {
|
||||
|
||||
int write_xml_bus_group(const char* fname, const BusGroup& bus_group) {
|
||||
vtr::ScopedStartFinishTimer timer("Write Bus Group");
|
||||
|
||||
/* Create a file handler */
|
||||
|
@ -86,15 +90,16 @@ int write_xml_bus_group(const char* fname,
|
|||
|
||||
/* Validate the file stream */
|
||||
openfpga::check_file_stream(fname, fp);
|
||||
|
||||
|
||||
/* Write the root node */
|
||||
fp << "<" << XML_BUS_GROUP_NODE_NAME << ">" << "\n";
|
||||
fp << "<" << XML_BUS_GROUP_NODE_NAME << ">"
|
||||
<< "\n";
|
||||
|
||||
int err_code = 0;
|
||||
|
||||
/* Write each bus */
|
||||
/* Write each bus */
|
||||
for (const BusGroupId& bus : bus_group.buses()) {
|
||||
/* Write bus */
|
||||
/* Write bus */
|
||||
err_code = write_xml_bus(fp, bus_group, bus);
|
||||
if (0 != err_code) {
|
||||
return err_code;
|
||||
|
@ -102,7 +107,8 @@ int write_xml_bus_group(const char* fname,
|
|||
}
|
||||
|
||||
/* Finish writing the root node */
|
||||
fp << "</" << XML_BUS_GROUP_NODE_NAME << ">" << "\n";
|
||||
fp << "</" << XML_BUS_GROUP_NODE_NAME << ">"
|
||||
<< "\n";
|
||||
|
||||
/* Close the file stream */
|
||||
fp.close();
|
||||
|
@ -110,4 +116,4 @@ int write_xml_bus_group(const char* fname,
|
|||
return err_code;
|
||||
}
|
||||
|
||||
} // End of namespace openfpga
|
||||
} // End of namespace openfpga
|
||||
|
|
|
@ -5,16 +5,16 @@
|
|||
* Include header files that are required by function declaration
|
||||
*******************************************************************/
|
||||
#include <fstream>
|
||||
|
||||
#include "bus_group.h"
|
||||
|
||||
/********************************************************************
|
||||
* Function declaration
|
||||
*******************************************************************/
|
||||
namespace openfpga { // Begin namespace openfpga
|
||||
namespace openfpga { // Begin namespace openfpga
|
||||
|
||||
int write_xml_bus_group(const char* fname,
|
||||
const BusGroup& bus_group);
|
||||
int write_xml_bus_group(const char* fname, const BusGroup& bus_group);
|
||||
|
||||
} // End of namespace openfpga
|
||||
} // End of namespace openfpga
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/********************************************************************
|
||||
* Unit test functions to validate the correctness of
|
||||
* Unit test functions to validate the correctness of
|
||||
* 1. parser of data structures
|
||||
* 2. writer of data structures
|
||||
*******************************************************************/
|
||||
|
@ -16,18 +16,15 @@ int main(int argc, const char** argv) {
|
|||
VTR_ASSERT((2 == argc) || (3 == argc));
|
||||
|
||||
/* Parse the circuit library from an XML file */
|
||||
const openfpga::BusGroup& bus_group = openfpga::read_xml_bus_group(argv[1]);
|
||||
const openfpga::BusGroup& bus_group = openfpga::read_xml_bus_group(argv[1]);
|
||||
VTR_LOG("Parsed %lu bus(es) from XML into bus group.\n",
|
||||
bus_group.buses().size());
|
||||
|
||||
/* Output the bus group to an XML file
|
||||
* This is optional only used when there is a second argument
|
||||
*/
|
||||
if (3 <= argc) {
|
||||
if (3 <= argc) {
|
||||
openfpga::write_xml_bus_group(argv[2], bus_group);
|
||||
VTR_LOG("Write the bus group to an XML file: %s.\n",
|
||||
argv[2]);
|
||||
VTR_LOG("Write the bus group to an XML file: %s.\n", argv[2]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
#include "fabric_key.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "vtr_assert.h"
|
||||
#include "vtr_log.h"
|
||||
|
||||
#include "fabric_key.h"
|
||||
|
||||
/************************************************************************
|
||||
* Member functions for class FabricKey
|
||||
***********************************************************************/
|
||||
|
@ -12,9 +12,7 @@
|
|||
/************************************************************************
|
||||
* Constructors
|
||||
***********************************************************************/
|
||||
FabricKey::FabricKey() {
|
||||
return;
|
||||
}
|
||||
FabricKey::FabricKey() { return; }
|
||||
|
||||
/************************************************************************
|
||||
* Public Accessors : aggregates
|
||||
|
@ -27,59 +25,64 @@ FabricKey::fabric_region_range FabricKey::regions() const {
|
|||
return vtr::make_range(region_ids_.begin(), region_ids_.end());
|
||||
}
|
||||
|
||||
FabricKey::fabric_bit_line_bank_range FabricKey::bl_banks(const FabricRegionId& region_id) const {
|
||||
FabricKey::fabric_bit_line_bank_range FabricKey::bl_banks(
|
||||
const FabricRegionId& region_id) const {
|
||||
VTR_ASSERT(valid_region_id(region_id));
|
||||
return vtr::make_range(bl_bank_ids_[region_id].begin(), bl_bank_ids_[region_id].end());
|
||||
return vtr::make_range(bl_bank_ids_[region_id].begin(),
|
||||
bl_bank_ids_[region_id].end());
|
||||
}
|
||||
|
||||
FabricKey::fabric_word_line_bank_range FabricKey::wl_banks(const FabricRegionId& region_id) const {
|
||||
FabricKey::fabric_word_line_bank_range FabricKey::wl_banks(
|
||||
const FabricRegionId& region_id) const {
|
||||
VTR_ASSERT(valid_region_id(region_id));
|
||||
return vtr::make_range(wl_bank_ids_[region_id].begin(), wl_bank_ids_[region_id].end());
|
||||
return vtr::make_range(wl_bank_ids_[region_id].begin(),
|
||||
wl_bank_ids_[region_id].end());
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Public Accessors : Basic data query
|
||||
* Public Accessors : Basic data query
|
||||
***********************************************************************/
|
||||
std::vector<FabricKeyId> FabricKey::region_keys(const FabricRegionId& region_id) const {
|
||||
std::vector<FabricKeyId> FabricKey::region_keys(
|
||||
const FabricRegionId& region_id) const {
|
||||
/* validate the region_id */
|
||||
VTR_ASSERT(valid_region_id(region_id));
|
||||
return region_key_ids_[region_id];
|
||||
return region_key_ids_[region_id];
|
||||
}
|
||||
|
||||
std::string FabricKey::key_name(const FabricKeyId& key_id) const {
|
||||
/* validate the key_id */
|
||||
VTR_ASSERT(valid_key_id(key_id));
|
||||
return key_names_[key_id];
|
||||
return key_names_[key_id];
|
||||
}
|
||||
|
||||
size_t FabricKey::key_value(const FabricKeyId& key_id) const {
|
||||
/* validate the key_id */
|
||||
VTR_ASSERT(valid_key_id(key_id));
|
||||
return key_values_[key_id];
|
||||
return key_values_[key_id];
|
||||
}
|
||||
|
||||
std::string FabricKey::key_alias(const FabricKeyId& key_id) const {
|
||||
/* validate the key_id */
|
||||
VTR_ASSERT(valid_key_id(key_id));
|
||||
return key_alias_[key_id];
|
||||
return key_alias_[key_id];
|
||||
}
|
||||
|
||||
vtr::Point<int> FabricKey::key_coordinate(const FabricKeyId& key_id) const {
|
||||
/* validate the key_id */
|
||||
VTR_ASSERT(valid_key_id(key_id));
|
||||
return key_coordinates_[key_id];
|
||||
return key_coordinates_[key_id];
|
||||
}
|
||||
|
||||
bool FabricKey::empty() const {
|
||||
return 0 == key_ids_.size();
|
||||
}
|
||||
bool FabricKey::empty() const { return 0 == key_ids_.size(); }
|
||||
|
||||
std::vector<openfpga::BasicPort> FabricKey::bl_bank_data_ports(const FabricRegionId& region_id, const FabricBitLineBankId& bank_id) const {
|
||||
std::vector<openfpga::BasicPort> FabricKey::bl_bank_data_ports(
|
||||
const FabricRegionId& region_id, const FabricBitLineBankId& bank_id) const {
|
||||
VTR_ASSERT(valid_bl_bank_id(region_id, bank_id));
|
||||
return bl_bank_data_ports_[region_id][bank_id];
|
||||
}
|
||||
|
||||
std::vector<openfpga::BasicPort> FabricKey::wl_bank_data_ports(const FabricRegionId& region_id, const FabricWordLineBankId& bank_id) const {
|
||||
std::vector<openfpga::BasicPort> FabricKey::wl_bank_data_ports(
|
||||
const FabricRegionId& region_id, const FabricWordLineBankId& bank_id) const {
|
||||
VTR_ASSERT(valid_wl_bank_id(region_id, bank_id));
|
||||
return wl_bank_data_ports_[region_id][bank_id];
|
||||
}
|
||||
|
@ -106,7 +109,7 @@ FabricRegionId FabricKey::create_region() {
|
|||
bl_bank_data_ports_.emplace_back();
|
||||
wl_bank_ids_.emplace_back();
|
||||
wl_bank_data_ports_.emplace_back();
|
||||
|
||||
|
||||
return region;
|
||||
}
|
||||
|
||||
|
@ -126,12 +129,12 @@ void FabricKey::add_key_to_region(const FabricRegionId& region_id,
|
|||
VTR_ASSERT(valid_region_id(region_id));
|
||||
|
||||
/* Check if the key is already in the region */
|
||||
if (region_key_ids_[region_id].end() != std::find(region_key_ids_[region_id].begin(),
|
||||
region_key_ids_[region_id].end(),
|
||||
key_id)) {
|
||||
VTR_LOG_WARN("Try to add a key '%s' which is already in the region '%lu'!\n",
|
||||
key_name(key_id).c_str(),
|
||||
size_t(region_id));
|
||||
if (region_key_ids_[region_id].end() !=
|
||||
std::find(region_key_ids_[region_id].begin(),
|
||||
region_key_ids_[region_id].end(), key_id)) {
|
||||
VTR_LOG_WARN(
|
||||
"Try to add a key '%s' which is already in the region '%lu'!\n",
|
||||
key_name(key_id).c_str(), size_t(region_id));
|
||||
VTR_ASSERT(region_id == key_regions_[key_id]);
|
||||
return; /* Nothing to do but leave a warning! */
|
||||
}
|
||||
|
@ -140,12 +143,13 @@ void FabricKey::add_key_to_region(const FabricRegionId& region_id,
|
|||
region_key_ids_[region_id].push_back(key_id);
|
||||
|
||||
/* If the key is already in another region, we will error out */
|
||||
if ( (true == valid_region_id(key_regions_[key_id]))
|
||||
&& (region_id != key_regions_[key_id])) {
|
||||
VTR_LOG_ERROR("Try to add a key '%s' to region '%lu' but it is already in another region '%lu'!\n",
|
||||
key_name(key_id).c_str(),
|
||||
size_t(key_regions_[key_id]),
|
||||
size_t(region_id));
|
||||
if ((true == valid_region_id(key_regions_[key_id])) &&
|
||||
(region_id != key_regions_[key_id])) {
|
||||
VTR_LOG_ERROR(
|
||||
"Try to add a key '%s' to region '%lu' but it is already in another "
|
||||
"region '%lu'!\n",
|
||||
key_name(key_id).c_str(), size_t(key_regions_[key_id]),
|
||||
size_t(region_id));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
@ -170,7 +174,7 @@ FabricKeyId FabricKey::create_key() {
|
|||
key_regions_.emplace_back(FabricRegionId::INVALID());
|
||||
key_alias_.emplace_back();
|
||||
key_coordinates_.emplace_back(vtr::Point<int>(-1, -1));
|
||||
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
|
@ -182,8 +186,7 @@ void FabricKey::set_key_name(const FabricKeyId& key_id,
|
|||
key_names_[key_id] = name;
|
||||
}
|
||||
|
||||
void FabricKey::set_key_value(const FabricKeyId& key_id,
|
||||
const size_t& value) {
|
||||
void FabricKey::set_key_value(const FabricKeyId& key_id, const size_t& value) {
|
||||
/* validate the key_id */
|
||||
VTR_ASSERT(valid_key_id(key_id));
|
||||
|
||||
|
@ -206,80 +209,91 @@ void FabricKey::set_key_coordinate(const FabricKeyId& key_id,
|
|||
key_coordinates_[key_id] = coord;
|
||||
}
|
||||
|
||||
void FabricKey::reserve_bl_shift_register_banks(const FabricRegionId& region_id, const size_t& num_banks) {
|
||||
void FabricKey::reserve_bl_shift_register_banks(const FabricRegionId& region_id,
|
||||
const size_t& num_banks) {
|
||||
VTR_ASSERT(valid_region_id(region_id));
|
||||
bl_bank_ids_[region_id].reserve(num_banks);
|
||||
bl_bank_data_ports_[region_id].reserve(num_banks);
|
||||
}
|
||||
|
||||
void FabricKey::reserve_wl_shift_register_banks(const FabricRegionId& region_id, const size_t& num_banks) {
|
||||
void FabricKey::reserve_wl_shift_register_banks(const FabricRegionId& region_id,
|
||||
const size_t& num_banks) {
|
||||
VTR_ASSERT(valid_region_id(region_id));
|
||||
wl_bank_ids_[region_id].reserve(num_banks);
|
||||
wl_bank_data_ports_[region_id].reserve(num_banks);
|
||||
}
|
||||
|
||||
FabricBitLineBankId FabricKey::create_bl_shift_register_bank(const FabricRegionId& region_id) {
|
||||
FabricBitLineBankId FabricKey::create_bl_shift_register_bank(
|
||||
const FabricRegionId& region_id) {
|
||||
VTR_ASSERT(valid_region_id(region_id));
|
||||
|
||||
|
||||
/* Create a new id */
|
||||
FabricBitLineBankId bank = FabricBitLineBankId(bl_bank_ids_[region_id].size());
|
||||
FabricBitLineBankId bank =
|
||||
FabricBitLineBankId(bl_bank_ids_[region_id].size());
|
||||
bl_bank_ids_[region_id].push_back(bank);
|
||||
bl_bank_data_ports_[region_id].emplace_back();
|
||||
|
||||
return bank;
|
||||
}
|
||||
|
||||
void FabricKey::add_data_port_to_bl_shift_register_bank(const FabricRegionId& region_id,
|
||||
const FabricBitLineBankId& bank_id,
|
||||
const openfpga::BasicPort& data_port) {
|
||||
void FabricKey::add_data_port_to_bl_shift_register_bank(
|
||||
const FabricRegionId& region_id, const FabricBitLineBankId& bank_id,
|
||||
const openfpga::BasicPort& data_port) {
|
||||
VTR_ASSERT(valid_bl_bank_id(region_id, bank_id));
|
||||
bl_bank_data_ports_[region_id][bank_id].push_back(data_port);
|
||||
}
|
||||
|
||||
FabricWordLineBankId FabricKey::create_wl_shift_register_bank(const FabricRegionId& region_id) {
|
||||
FabricWordLineBankId FabricKey::create_wl_shift_register_bank(
|
||||
const FabricRegionId& region_id) {
|
||||
VTR_ASSERT(valid_region_id(region_id));
|
||||
|
||||
|
||||
/* Create a new id */
|
||||
FabricWordLineBankId bank = FabricWordLineBankId(wl_bank_ids_[region_id].size());
|
||||
FabricWordLineBankId bank =
|
||||
FabricWordLineBankId(wl_bank_ids_[region_id].size());
|
||||
wl_bank_ids_[region_id].push_back(bank);
|
||||
wl_bank_data_ports_[region_id].emplace_back();
|
||||
|
||||
return bank;
|
||||
}
|
||||
|
||||
void FabricKey::add_data_port_to_wl_shift_register_bank(const FabricRegionId& region_id,
|
||||
const FabricWordLineBankId& bank_id,
|
||||
const openfpga::BasicPort& data_port) {
|
||||
void FabricKey::add_data_port_to_wl_shift_register_bank(
|
||||
const FabricRegionId& region_id, const FabricWordLineBankId& bank_id,
|
||||
const openfpga::BasicPort& data_port) {
|
||||
VTR_ASSERT(valid_wl_bank_id(region_id, bank_id));
|
||||
wl_bank_data_ports_[region_id][bank_id].push_back(data_port);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Internal invalidators/validators
|
||||
* Internal invalidators/validators
|
||||
***********************************************************************/
|
||||
/* Validators */
|
||||
bool FabricKey::valid_region_id(const FabricRegionId& region_id) const {
|
||||
return ( size_t(region_id) < region_ids_.size() ) && ( region_id == region_ids_[region_id] );
|
||||
return (size_t(region_id) < region_ids_.size()) &&
|
||||
(region_id == region_ids_[region_id]);
|
||||
}
|
||||
|
||||
bool FabricKey::valid_key_id(const FabricKeyId& key_id) const {
|
||||
return ( size_t(key_id) < key_ids_.size() ) && ( key_id == key_ids_[key_id] );
|
||||
return (size_t(key_id) < key_ids_.size()) && (key_id == key_ids_[key_id]);
|
||||
}
|
||||
|
||||
bool FabricKey::valid_key_coordinate(const vtr::Point<int>& coord) const {
|
||||
return coord.x() > -1 && coord.y() > -1;
|
||||
}
|
||||
|
||||
bool FabricKey::valid_bl_bank_id(const FabricRegionId& region_id, const FabricBitLineBankId& bank_id) const {
|
||||
bool FabricKey::valid_bl_bank_id(const FabricRegionId& region_id,
|
||||
const FabricBitLineBankId& bank_id) const {
|
||||
if (!valid_region_id(region_id)) {
|
||||
return false;
|
||||
}
|
||||
return ( size_t(bank_id) < bl_bank_ids_[region_id].size() ) && ( bank_id == bl_bank_ids_[region_id][bank_id] );
|
||||
return (size_t(bank_id) < bl_bank_ids_[region_id].size()) &&
|
||||
(bank_id == bl_bank_ids_[region_id][bank_id]);
|
||||
}
|
||||
|
||||
bool FabricKey::valid_wl_bank_id(const FabricRegionId& region_id, const FabricWordLineBankId& bank_id) const {
|
||||
bool FabricKey::valid_wl_bank_id(const FabricRegionId& region_id,
|
||||
const FabricWordLineBankId& bank_id) const {
|
||||
if (!valid_region_id(region_id)) {
|
||||
return false;
|
||||
}
|
||||
return ( size_t(bank_id) < wl_bank_ids_[region_id].size() ) && ( bank_id == wl_bank_ids_[region_id][bank_id] );
|
||||
return (size_t(bank_id) < wl_bank_ids_[region_id].size()) &&
|
||||
(bank_id == wl_bank_ids_[region_id][bank_id]);
|
||||
}
|
||||
|
|
|
@ -4,26 +4,25 @@
|
|||
/********************************************************************
|
||||
* This file include the declaration of fabric key
|
||||
*******************************************************************/
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <array>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
/* Headers from vtrutil library */
|
||||
#include "vtr_vector.h"
|
||||
#include "vtr_geometry.h"
|
||||
#include "vtr_vector.h"
|
||||
|
||||
/* Headers from openfpgautil library */
|
||||
#include "openfpga_port.h"
|
||||
|
||||
#include "fabric_key_fwd.h"
|
||||
#include "openfpga_port.h"
|
||||
|
||||
/********************************************************************
|
||||
* A data structure to describe a secure key for fabric organization
|
||||
* A fabric may consist of multiple regions
|
||||
* Each region contains a number of keys
|
||||
*
|
||||
*
|
||||
* Note that:
|
||||
* - each key can only be defined in one unique region
|
||||
* - each key can only be defined in one unique region
|
||||
*
|
||||
* Typical usage:
|
||||
* --------------
|
||||
|
@ -38,144 +37,168 @@
|
|||
*
|
||||
*******************************************************************/
|
||||
class FabricKey {
|
||||
public: /* Types */
|
||||
typedef vtr::vector<FabricKeyId, FabricKeyId>::const_iterator fabric_key_iterator;
|
||||
typedef vtr::vector<FabricRegionId, FabricRegionId>::const_iterator fabric_region_iterator;
|
||||
typedef vtr::vector<FabricBitLineBankId, FabricBitLineBankId>::const_iterator fabric_bit_line_bank_iterator;
|
||||
typedef vtr::vector<FabricWordLineBankId, FabricWordLineBankId>::const_iterator fabric_word_line_bank_iterator;
|
||||
/* Create range */
|
||||
typedef vtr::Range<fabric_region_iterator> fabric_region_range;
|
||||
typedef vtr::Range<fabric_key_iterator> fabric_key_range;
|
||||
typedef vtr::Range<fabric_bit_line_bank_iterator> fabric_bit_line_bank_range;
|
||||
typedef vtr::Range<fabric_word_line_bank_iterator> fabric_word_line_bank_range;
|
||||
public: /* Constructors */
|
||||
FabricKey();
|
||||
public: /* Accessors: aggregates */
|
||||
fabric_key_range keys() const;
|
||||
fabric_region_range regions() const;
|
||||
fabric_bit_line_bank_range bl_banks(const FabricRegionId& region_id) const;
|
||||
fabric_word_line_bank_range wl_banks(const FabricRegionId& region_id) const;
|
||||
public: /* Public Accessors: Basic data query */
|
||||
/* Access all the keys of a region */
|
||||
std::vector<FabricKeyId> region_keys(const FabricRegionId& region_id) const;
|
||||
public: /* Types */
|
||||
typedef vtr::vector<FabricKeyId, FabricKeyId>::const_iterator
|
||||
fabric_key_iterator;
|
||||
typedef vtr::vector<FabricRegionId, FabricRegionId>::const_iterator
|
||||
fabric_region_iterator;
|
||||
typedef vtr::vector<FabricBitLineBankId, FabricBitLineBankId>::const_iterator
|
||||
fabric_bit_line_bank_iterator;
|
||||
typedef vtr::vector<FabricWordLineBankId,
|
||||
FabricWordLineBankId>::const_iterator
|
||||
fabric_word_line_bank_iterator;
|
||||
/* Create range */
|
||||
typedef vtr::Range<fabric_region_iterator> fabric_region_range;
|
||||
typedef vtr::Range<fabric_key_iterator> fabric_key_range;
|
||||
typedef vtr::Range<fabric_bit_line_bank_iterator> fabric_bit_line_bank_range;
|
||||
typedef vtr::Range<fabric_word_line_bank_iterator>
|
||||
fabric_word_line_bank_range;
|
||||
|
||||
/* Access the name of a key */
|
||||
std::string key_name(const FabricKeyId& key_id) const;
|
||||
public: /* Constructors */
|
||||
FabricKey();
|
||||
|
||||
/* Access the value of a key */
|
||||
size_t key_value(const FabricKeyId& key_id) const;
|
||||
public: /* Accessors: aggregates */
|
||||
fabric_key_range keys() const;
|
||||
fabric_region_range regions() const;
|
||||
fabric_bit_line_bank_range bl_banks(const FabricRegionId& region_id) const;
|
||||
fabric_word_line_bank_range wl_banks(const FabricRegionId& region_id) const;
|
||||
|
||||
/* Access the alias of a key */
|
||||
std::string key_alias(const FabricKeyId& key_id) const;
|
||||
public: /* Public Accessors: Basic data query */
|
||||
/* Access all the keys of a region */
|
||||
std::vector<FabricKeyId> region_keys(const FabricRegionId& region_id) const;
|
||||
|
||||
/* Access the coordinate of a key */
|
||||
vtr::Point<int> key_coordinate(const FabricKeyId& key_id) const;
|
||||
/* Access the name of a key */
|
||||
std::string key_name(const FabricKeyId& key_id) const;
|
||||
|
||||
/* Check if there are any keys */
|
||||
bool empty() const;
|
||||
/* Access the value of a key */
|
||||
size_t key_value(const FabricKeyId& key_id) const;
|
||||
|
||||
/* Return a list of data ports which will be driven by a BL shift register bank */
|
||||
std::vector<openfpga::BasicPort> bl_bank_data_ports(const FabricRegionId& region_id, const FabricBitLineBankId& bank_id) const;
|
||||
/* Access the alias of a key */
|
||||
std::string key_alias(const FabricKeyId& key_id) const;
|
||||
|
||||
/* Return a list of data ports which will be driven by a WL shift register bank */
|
||||
std::vector<openfpga::BasicPort> wl_bank_data_ports(const FabricRegionId& region_id, const FabricWordLineBankId& bank_id) const;
|
||||
/* Access the coordinate of a key */
|
||||
vtr::Point<int> key_coordinate(const FabricKeyId& key_id) const;
|
||||
|
||||
public: /* Public Mutators: model-related */
|
||||
/* Check if there are any keys */
|
||||
bool empty() const;
|
||||
|
||||
/* Reserve a number of regions to be memory efficent */
|
||||
void reserve_regions(const size_t& num_regions);
|
||||
/* Return a list of data ports which will be driven by a BL shift register
|
||||
* bank */
|
||||
std::vector<openfpga::BasicPort> bl_bank_data_ports(
|
||||
const FabricRegionId& region_id, const FabricBitLineBankId& bank_id) const;
|
||||
|
||||
/* Create a new region and add it to the library, return an id */
|
||||
FabricRegionId create_region();
|
||||
/* Return a list of data ports which will be driven by a WL shift register
|
||||
* bank */
|
||||
std::vector<openfpga::BasicPort> wl_bank_data_ports(
|
||||
const FabricRegionId& region_id, const FabricWordLineBankId& bank_id) const;
|
||||
|
||||
/* Reserve the memory space for keys under a region, to be memory efficient */
|
||||
void reserve_region_keys(const FabricRegionId& region_id,
|
||||
const size_t& num_keys);
|
||||
public: /* Public Mutators: model-related */
|
||||
/* Reserve a number of regions to be memory efficent */
|
||||
void reserve_regions(const size_t& num_regions);
|
||||
|
||||
/* Add a key to a region */
|
||||
void add_key_to_region(const FabricRegionId& region_id,
|
||||
const FabricKeyId& key_id);
|
||||
/* Create a new region and add it to the library, return an id */
|
||||
FabricRegionId create_region();
|
||||
|
||||
/* Reserve a number of keys to be memory efficent */
|
||||
void reserve_keys(const size_t& num_keys);
|
||||
/* Reserve the memory space for keys under a region, to be memory efficient */
|
||||
void reserve_region_keys(const FabricRegionId& region_id,
|
||||
const size_t& num_keys);
|
||||
|
||||
/* Create a new key and add it to the library, return an id */
|
||||
FabricKeyId create_key();
|
||||
/* Add a key to a region */
|
||||
void add_key_to_region(const FabricRegionId& region_id,
|
||||
const FabricKeyId& key_id);
|
||||
|
||||
/* Configure attributes of a key */
|
||||
void set_key_name(const FabricKeyId& key_id,
|
||||
const std::string& name);
|
||||
/* Reserve a number of keys to be memory efficent */
|
||||
void reserve_keys(const size_t& num_keys);
|
||||
|
||||
void set_key_value(const FabricKeyId& key_id,
|
||||
const size_t& value);
|
||||
/* Create a new key and add it to the library, return an id */
|
||||
FabricKeyId create_key();
|
||||
|
||||
void set_key_alias(const FabricKeyId& key_id,
|
||||
const std::string& alias);
|
||||
/* Configure attributes of a key */
|
||||
void set_key_name(const FabricKeyId& key_id, const std::string& name);
|
||||
|
||||
void set_key_coordinate(const FabricKeyId& key_id,
|
||||
const vtr::Point<int>& coord);
|
||||
void set_key_value(const FabricKeyId& key_id, const size_t& value);
|
||||
|
||||
/* Reserve a number of banks to be memory efficent */
|
||||
void reserve_bl_shift_register_banks(const FabricRegionId& region_id, const size_t& num_banks);
|
||||
void reserve_wl_shift_register_banks(const FabricRegionId& region_id, const size_t& num_banks);
|
||||
void set_key_alias(const FabricKeyId& key_id, const std::string& alias);
|
||||
|
||||
/* Create a new shift register bank for BLs and return an id */
|
||||
FabricBitLineBankId create_bl_shift_register_bank(const FabricRegionId& region_id);
|
||||
void set_key_coordinate(const FabricKeyId& key_id,
|
||||
const vtr::Point<int>& coord);
|
||||
|
||||
/* Add a data port to a given BL shift register bank */
|
||||
void add_data_port_to_bl_shift_register_bank(const FabricRegionId& region_id,
|
||||
const FabricBitLineBankId& bank_id,
|
||||
const openfpga::BasicPort& data_port);
|
||||
/* Reserve a number of banks to be memory efficent */
|
||||
void reserve_bl_shift_register_banks(const FabricRegionId& region_id,
|
||||
const size_t& num_banks);
|
||||
void reserve_wl_shift_register_banks(const FabricRegionId& region_id,
|
||||
const size_t& num_banks);
|
||||
|
||||
/* Create a new shift register bank for WLs and return an id */
|
||||
FabricWordLineBankId create_wl_shift_register_bank(const FabricRegionId& region_id);
|
||||
/* Create a new shift register bank for BLs and return an id */
|
||||
FabricBitLineBankId create_bl_shift_register_bank(
|
||||
const FabricRegionId& region_id);
|
||||
|
||||
/* Add a data port to a given WL shift register bank */
|
||||
void add_data_port_to_wl_shift_register_bank(const FabricRegionId& region_id,
|
||||
const FabricWordLineBankId& bank_id,
|
||||
const openfpga::BasicPort& data_port);
|
||||
/* Add a data port to a given BL shift register bank */
|
||||
void add_data_port_to_bl_shift_register_bank(
|
||||
const FabricRegionId& region_id, const FabricBitLineBankId& bank_id,
|
||||
const openfpga::BasicPort& data_port);
|
||||
|
||||
public: /* Public invalidators/validators */
|
||||
bool valid_region_id(const FabricRegionId& region_id) const;
|
||||
bool valid_key_id(const FabricKeyId& key_id) const;
|
||||
/* Identify if key coordinate is acceptable to fabric key convention */
|
||||
bool valid_key_coordinate(const vtr::Point<int>& coord) const;
|
||||
bool valid_bl_bank_id(const FabricRegionId& region_id, const FabricBitLineBankId& bank_id) const;
|
||||
bool valid_wl_bank_id(const FabricRegionId& region_id, const FabricWordLineBankId& bank_id) const;
|
||||
private: /* Internal data */
|
||||
/* Unique ids for each region */
|
||||
vtr::vector<FabricRegionId, FabricRegionId> region_ids_;
|
||||
/* Create a new shift register bank for WLs and return an id */
|
||||
FabricWordLineBankId create_wl_shift_register_bank(
|
||||
const FabricRegionId& region_id);
|
||||
|
||||
/* Key ids for each region */
|
||||
vtr::vector<FabricRegionId, std::vector<FabricKeyId>> region_key_ids_;
|
||||
/* Add a data port to a given WL shift register bank */
|
||||
void add_data_port_to_wl_shift_register_bank(
|
||||
const FabricRegionId& region_id, const FabricWordLineBankId& bank_id,
|
||||
const openfpga::BasicPort& data_port);
|
||||
|
||||
/* Unique ids for each key */
|
||||
vtr::vector<FabricKeyId, FabricKeyId> key_ids_;
|
||||
public: /* Public invalidators/validators */
|
||||
bool valid_region_id(const FabricRegionId& region_id) const;
|
||||
bool valid_key_id(const FabricKeyId& key_id) const;
|
||||
/* Identify if key coordinate is acceptable to fabric key convention */
|
||||
bool valid_key_coordinate(const vtr::Point<int>& coord) const;
|
||||
bool valid_bl_bank_id(const FabricRegionId& region_id,
|
||||
const FabricBitLineBankId& bank_id) const;
|
||||
bool valid_wl_bank_id(const FabricRegionId& region_id,
|
||||
const FabricWordLineBankId& bank_id) const;
|
||||
|
||||
/* Names for each key */
|
||||
vtr::vector<FabricKeyId, std::string> key_names_;
|
||||
private: /* Internal data */
|
||||
/* Unique ids for each region */
|
||||
vtr::vector<FabricRegionId, FabricRegionId> region_ids_;
|
||||
|
||||
/* Values for each key */
|
||||
vtr::vector<FabricKeyId, size_t> key_values_;
|
||||
/* Key ids for each region */
|
||||
vtr::vector<FabricRegionId, std::vector<FabricKeyId>> region_key_ids_;
|
||||
|
||||
/* Values for each key */
|
||||
vtr::vector<FabricKeyId, vtr::Point<int>> key_coordinates_;
|
||||
/* Unique ids for each key */
|
||||
vtr::vector<FabricKeyId, FabricKeyId> key_ids_;
|
||||
|
||||
/* Region for each key */
|
||||
vtr::vector<FabricKeyId, FabricRegionId> key_regions_;
|
||||
/* Names for each key */
|
||||
vtr::vector<FabricKeyId, std::string> key_names_;
|
||||
|
||||
/* Optional alias for each key, with which a key can also be represented */
|
||||
vtr::vector<FabricKeyId, std::string> key_alias_;
|
||||
/* Values for each key */
|
||||
vtr::vector<FabricKeyId, size_t> key_values_;
|
||||
|
||||
/* Unique ids for each BL shift register bank */
|
||||
vtr::vector<FabricRegionId, vtr::vector<FabricBitLineBankId, FabricBitLineBankId>> bl_bank_ids_;
|
||||
/* Data ports to be connected to each BL shift register bank */
|
||||
vtr::vector<FabricRegionId, vtr::vector<FabricBitLineBankId, std::vector<openfpga::BasicPort>>> bl_bank_data_ports_;
|
||||
/* Values for each key */
|
||||
vtr::vector<FabricKeyId, vtr::Point<int>> key_coordinates_;
|
||||
|
||||
/* Unique ids for each WL shift register bank */
|
||||
vtr::vector<FabricRegionId, vtr::vector<FabricWordLineBankId, FabricWordLineBankId>> wl_bank_ids_;
|
||||
/* Data ports to be connected to each WL shift register bank */
|
||||
vtr::vector<FabricRegionId, vtr::vector<FabricWordLineBankId, std::vector<openfpga::BasicPort>>> wl_bank_data_ports_;
|
||||
/* Region for each key */
|
||||
vtr::vector<FabricKeyId, FabricRegionId> key_regions_;
|
||||
|
||||
/* Optional alias for each key, with which a key can also be represented */
|
||||
vtr::vector<FabricKeyId, std::string> key_alias_;
|
||||
|
||||
/* Unique ids for each BL shift register bank */
|
||||
vtr::vector<FabricRegionId,
|
||||
vtr::vector<FabricBitLineBankId, FabricBitLineBankId>>
|
||||
bl_bank_ids_;
|
||||
/* Data ports to be connected to each BL shift register bank */
|
||||
vtr::vector<FabricRegionId, vtr::vector<FabricBitLineBankId,
|
||||
std::vector<openfpga::BasicPort>>>
|
||||
bl_bank_data_ports_;
|
||||
|
||||
/* Unique ids for each WL shift register bank */
|
||||
vtr::vector<FabricRegionId,
|
||||
vtr::vector<FabricWordLineBankId, FabricWordLineBankId>>
|
||||
wl_bank_ids_;
|
||||
/* Data ports to be connected to each WL shift register bank */
|
||||
vtr::vector<FabricRegionId, vtr::vector<FabricWordLineBankId,
|
||||
std::vector<openfpga::BasicPort>>>
|
||||
wl_bank_data_ports_;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/************************************************************************
|
||||
* A header file for FabricKey class, including critical data declaration
|
||||
* Please include this file only for using any TechnologyLibrary data structure
|
||||
* Refer to fabric_key.h for more details
|
||||
* Refer to fabric_key.h for more details
|
||||
***********************************************************************/
|
||||
|
||||
/************************************************************************
|
||||
* Create strong id for FabricKey to avoid illegal type casting
|
||||
* Create strong id for FabricKey to avoid illegal type casting
|
||||
***********************************************************************/
|
||||
#ifndef FABRIC_KEY_FWD_H
|
||||
#define FABRIC_KEY_FWD_H
|
||||
|
|
|
@ -14,105 +14,111 @@
|
|||
#include "vtr_time.h"
|
||||
|
||||
/* Headers from openfpga util library */
|
||||
#include "openfpga_tokenizer.h"
|
||||
#include "openfpga_port_parser.h"
|
||||
#include "openfpga_tokenizer.h"
|
||||
|
||||
/* Headers from libarchfpga */
|
||||
#include "arch_error.h"
|
||||
#include "read_xml_util.h"
|
||||
|
||||
#include "read_xml_fabric_key.h"
|
||||
#include "read_xml_util.h"
|
||||
|
||||
/********************************************************************
|
||||
* Parse XML codes of a <key> to an object of FabricKey
|
||||
*******************************************************************/
|
||||
static
|
||||
void read_xml_region_key(pugi::xml_node& xml_component_key,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
FabricKey& fabric_key,
|
||||
const FabricRegionId& fabric_region) {
|
||||
|
||||
static void read_xml_region_key(pugi::xml_node& xml_component_key,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
FabricKey& fabric_key,
|
||||
const FabricRegionId& fabric_region) {
|
||||
/* Find the id of component key */
|
||||
const size_t& id = get_attribute(xml_component_key, "id", loc_data).as_int();
|
||||
|
||||
if (false == fabric_key.valid_key_id(FabricKeyId(id))) {
|
||||
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_component_key),
|
||||
"Invalid 'id' attribute '%d' (in total %lu keys)!\n",
|
||||
id,
|
||||
"Invalid 'id' attribute '%d' (in total %lu keys)!\n", id,
|
||||
fabric_key.keys().size());
|
||||
}
|
||||
|
||||
VTR_ASSERT_SAFE(true == fabric_key.valid_key_id(FabricKeyId(id)));
|
||||
|
||||
/* If we have an alias, set the value as well */
|
||||
const std::string& alias = get_attribute(xml_component_key, "alias", loc_data, pugiutil::ReqOpt::OPTIONAL).as_string();
|
||||
const std::string& alias = get_attribute(xml_component_key, "alias", loc_data,
|
||||
pugiutil::ReqOpt::OPTIONAL)
|
||||
.as_string();
|
||||
if (!alias.empty()) {
|
||||
fabric_key.set_key_alias(FabricKeyId(id), alias);
|
||||
}
|
||||
|
||||
/* If we have the alias set, name and valus are optional then
|
||||
* Otherwise, they are mandatory attributes
|
||||
/* If we have the alias set, name and valus are optional then
|
||||
* Otherwise, they are mandatory attributes
|
||||
*/
|
||||
pugiutil::ReqOpt required_name_value = pugiutil::ReqOpt::OPTIONAL;
|
||||
pugiutil::ReqOpt required_name_value = pugiutil::ReqOpt::OPTIONAL;
|
||||
if (true == alias.empty()) {
|
||||
required_name_value = pugiutil::ReqOpt::REQUIRED;
|
||||
}
|
||||
|
||||
const std::string& name = get_attribute(xml_component_key, "name", loc_data, required_name_value).as_string();
|
||||
const size_t& value = get_attribute(xml_component_key, "value", loc_data, required_name_value).as_int();
|
||||
|
||||
const std::string& name =
|
||||
get_attribute(xml_component_key, "name", loc_data, required_name_value)
|
||||
.as_string();
|
||||
const size_t& value =
|
||||
get_attribute(xml_component_key, "value", loc_data, required_name_value)
|
||||
.as_int();
|
||||
|
||||
fabric_key.set_key_name(FabricKeyId(id), name);
|
||||
fabric_key.set_key_value(FabricKeyId(id), value);
|
||||
fabric_key.add_key_to_region(fabric_region, FabricKeyId(id));
|
||||
|
||||
/* Parse coordinates */
|
||||
vtr::Point<int> coord;
|
||||
coord.set_x(get_attribute(xml_component_key, "column", loc_data, pugiutil::ReqOpt::OPTIONAL).as_int(-1));
|
||||
coord.set_y(get_attribute(xml_component_key, "row", loc_data, pugiutil::ReqOpt::OPTIONAL).as_int(-1));
|
||||
coord.set_x(get_attribute(xml_component_key, "column", loc_data,
|
||||
pugiutil::ReqOpt::OPTIONAL)
|
||||
.as_int(-1));
|
||||
coord.set_y(get_attribute(xml_component_key, "row", loc_data,
|
||||
pugiutil::ReqOpt::OPTIONAL)
|
||||
.as_int(-1));
|
||||
if (fabric_key.valid_key_coordinate(coord)) {
|
||||
fabric_key.set_key_coordinate(FabricKeyId(id), coord);
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Parse XML codes of a <bank> under <bl_shift_register_banks> to an object of FabricKey
|
||||
* Parse XML codes of a <bank> under <bl_shift_register_banks> to an object of
|
||||
*FabricKey
|
||||
*******************************************************************/
|
||||
static
|
||||
void read_xml_region_bl_shift_register_bank(pugi::xml_node& xml_bank,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
FabricKey& fabric_key,
|
||||
const FabricRegionId& fabric_region) {
|
||||
static void read_xml_region_bl_shift_register_bank(
|
||||
pugi::xml_node& xml_bank, const pugiutil::loc_data& loc_data,
|
||||
FabricKey& fabric_key, const FabricRegionId& fabric_region) {
|
||||
/* Find the id of the bank */
|
||||
FabricBitLineBankId bank_id = FabricBitLineBankId(get_attribute(xml_bank, "id", loc_data).as_int());
|
||||
FabricBitLineBankId bank_id =
|
||||
FabricBitLineBankId(get_attribute(xml_bank, "id", loc_data).as_int());
|
||||
|
||||
if (!fabric_key.valid_bl_bank_id(fabric_region, bank_id)) {
|
||||
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_bank),
|
||||
"Invalid 'id' attribute '%lu' (in total %lu BL banks)!\n",
|
||||
size_t(bank_id),
|
||||
fabric_key.bl_banks(fabric_region).size());
|
||||
size_t(bank_id), fabric_key.bl_banks(fabric_region).size());
|
||||
}
|
||||
|
||||
VTR_ASSERT_SAFE(true == fabric_key.valid_bl_bank_id(fabric_region, bank_id));
|
||||
|
||||
/* Parse the ports */
|
||||
std::string data_ports = get_attribute(xml_bank, "range", loc_data).as_string();
|
||||
std::string data_ports =
|
||||
get_attribute(xml_bank, "range", loc_data).as_string();
|
||||
/* Split with ',' if we have multiple ports */
|
||||
openfpga::StringToken tokenizer(data_ports);
|
||||
for (const std::string& data_port : tokenizer.split(',')) {
|
||||
openfpga::PortParser data_port_parser(data_port);
|
||||
fabric_key.add_data_port_to_bl_shift_register_bank(fabric_region, bank_id, data_port_parser.port());
|
||||
fabric_key.add_data_port_to_bl_shift_register_bank(fabric_region, bank_id,
|
||||
data_port_parser.port());
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Parse XML codes of a <bl_shift_register_banks> to an object of FabricKey
|
||||
*******************************************************************/
|
||||
static
|
||||
void read_xml_region_bl_shift_register_banks(pugi::xml_node& xml_bl_bank,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
FabricKey& fabric_key,
|
||||
const FabricRegionId& fabric_region) {
|
||||
size_t num_banks = count_children(xml_bl_bank, "bank", loc_data, pugiutil::ReqOpt::OPTIONAL);
|
||||
static void read_xml_region_bl_shift_register_banks(
|
||||
pugi::xml_node& xml_bl_bank, const pugiutil::loc_data& loc_data,
|
||||
FabricKey& fabric_key, const FabricRegionId& fabric_region) {
|
||||
size_t num_banks =
|
||||
count_children(xml_bl_bank, "bank", loc_data, pugiutil::ReqOpt::OPTIONAL);
|
||||
fabric_key.reserve_bl_shift_register_banks(fabric_region, num_banks);
|
||||
|
||||
for (size_t ibank = 0; ibank < num_banks; ++ibank) {
|
||||
|
@ -124,49 +130,50 @@ void read_xml_region_bl_shift_register_banks(pugi::xml_node& xml_bl_bank,
|
|||
if (xml_bank.name() != std::string("bank")) {
|
||||
bad_tag(xml_bank, loc_data, xml_bl_bank, {"bank"});
|
||||
}
|
||||
read_xml_region_bl_shift_register_bank(xml_bank, loc_data, fabric_key, fabric_region);
|
||||
read_xml_region_bl_shift_register_bank(xml_bank, loc_data, fabric_key,
|
||||
fabric_region);
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Parse XML codes of a <bank> under <wl_shift_register_banks> to an object of FabricKey
|
||||
* Parse XML codes of a <bank> under <wl_shift_register_banks> to an object of
|
||||
*FabricKey
|
||||
*******************************************************************/
|
||||
static
|
||||
void read_xml_region_wl_shift_register_bank(pugi::xml_node& xml_bank,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
FabricKey& fabric_key,
|
||||
const FabricRegionId& fabric_region) {
|
||||
static void read_xml_region_wl_shift_register_bank(
|
||||
pugi::xml_node& xml_bank, const pugiutil::loc_data& loc_data,
|
||||
FabricKey& fabric_key, const FabricRegionId& fabric_region) {
|
||||
/* Find the id of the bank */
|
||||
FabricWordLineBankId bank_id = FabricWordLineBankId(get_attribute(xml_bank, "id", loc_data).as_int());
|
||||
FabricWordLineBankId bank_id =
|
||||
FabricWordLineBankId(get_attribute(xml_bank, "id", loc_data).as_int());
|
||||
|
||||
if (!fabric_key.valid_wl_bank_id(fabric_region, bank_id)) {
|
||||
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_bank),
|
||||
"Invalid 'id' attribute '%lu' (in total %lu WL banks)!\n",
|
||||
size_t(bank_id),
|
||||
fabric_key.wl_banks(fabric_region).size());
|
||||
size_t(bank_id), fabric_key.wl_banks(fabric_region).size());
|
||||
}
|
||||
|
||||
VTR_ASSERT_SAFE(true == fabric_key.valid_wl_bank_id(fabric_region, bank_id));
|
||||
|
||||
/* Parse the ports */
|
||||
std::string data_ports = get_attribute(xml_bank, "range", loc_data).as_string();
|
||||
std::string data_ports =
|
||||
get_attribute(xml_bank, "range", loc_data).as_string();
|
||||
/* Split with ',' if we have multiple ports */
|
||||
openfpga::StringToken tokenizer(data_ports);
|
||||
for (const std::string& data_port : tokenizer.split(',')) {
|
||||
openfpga::PortParser data_port_parser(data_port);
|
||||
fabric_key.add_data_port_to_wl_shift_register_bank(fabric_region, bank_id, data_port_parser.port());
|
||||
fabric_key.add_data_port_to_wl_shift_register_bank(fabric_region, bank_id,
|
||||
data_port_parser.port());
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Parse XML codes of a <bl_shift_register_banks> to an object of FabricKey
|
||||
*******************************************************************/
|
||||
static
|
||||
void read_xml_region_wl_shift_register_banks(pugi::xml_node& xml_wl_bank,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
FabricKey& fabric_key,
|
||||
const FabricRegionId& fabric_region) {
|
||||
size_t num_banks = count_children(xml_wl_bank, "bank", loc_data, pugiutil::ReqOpt::OPTIONAL);
|
||||
static void read_xml_region_wl_shift_register_banks(
|
||||
pugi::xml_node& xml_wl_bank, const pugiutil::loc_data& loc_data,
|
||||
FabricKey& fabric_key, const FabricRegionId& fabric_region) {
|
||||
size_t num_banks =
|
||||
count_children(xml_wl_bank, "bank", loc_data, pugiutil::ReqOpt::OPTIONAL);
|
||||
fabric_key.reserve_wl_shift_register_banks(fabric_region, num_banks);
|
||||
|
||||
for (size_t ibank = 0; ibank < num_banks; ++ibank) {
|
||||
|
@ -178,29 +185,30 @@ void read_xml_region_wl_shift_register_banks(pugi::xml_node& xml_wl_bank,
|
|||
if (xml_bank.name() != std::string("bank")) {
|
||||
bad_tag(xml_bank, loc_data, xml_wl_bank, {"bank"});
|
||||
}
|
||||
read_xml_region_wl_shift_register_bank(xml_bank, loc_data, fabric_key, fabric_region);
|
||||
read_xml_region_wl_shift_register_bank(xml_bank, loc_data, fabric_key,
|
||||
fabric_region);
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Parse XML codes of a <key> to an object of FabricKey
|
||||
*******************************************************************/
|
||||
static
|
||||
void read_xml_fabric_region(pugi::xml_node& xml_region,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
FabricKey& fabric_key) {
|
||||
static void read_xml_fabric_region(pugi::xml_node& xml_region,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
FabricKey& fabric_key) {
|
||||
/* Find the unique id for the region */
|
||||
const FabricRegionId& region_id = FabricRegionId(get_attribute(xml_region, "id", loc_data).as_int());
|
||||
const FabricRegionId& region_id =
|
||||
FabricRegionId(get_attribute(xml_region, "id", loc_data).as_int());
|
||||
if (false == fabric_key.valid_region_id(region_id)) {
|
||||
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_region),
|
||||
"Invalid region id '%lu' (in total %lu regions)!\n",
|
||||
size_t(region_id),
|
||||
fabric_key.regions().size());
|
||||
size_t(region_id), fabric_key.regions().size());
|
||||
}
|
||||
VTR_ASSERT_SAFE(true == fabric_key.valid_region_id(region_id));
|
||||
|
||||
/* Reserve memory space for the keys in the region */
|
||||
size_t num_keys = count_children(xml_region, "key", loc_data, pugiutil::ReqOpt::OPTIONAL);
|
||||
size_t num_keys =
|
||||
count_children(xml_region, "key", loc_data, pugiutil::ReqOpt::OPTIONAL);
|
||||
fabric_key.reserve_region_keys(region_id, num_keys);
|
||||
|
||||
/* Parse the key for this region */
|
||||
|
@ -209,23 +217,28 @@ void read_xml_fabric_region(pugi::xml_node& xml_region,
|
|||
while (xml_key) {
|
||||
read_xml_region_key(xml_key, loc_data, fabric_key, region_id);
|
||||
xml_key = xml_key.next_sibling(xml_key.name());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse the BL shift register bank for this region */
|
||||
pugi::xml_node xml_bl_bank = get_single_child(xml_region, "bl_shift_register_banks", loc_data, pugiutil::ReqOpt::OPTIONAL);
|
||||
read_xml_region_bl_shift_register_banks(xml_bl_bank, loc_data, fabric_key, region_id);
|
||||
pugi::xml_node xml_bl_bank =
|
||||
get_single_child(xml_region, "bl_shift_register_banks", loc_data,
|
||||
pugiutil::ReqOpt::OPTIONAL);
|
||||
read_xml_region_bl_shift_register_banks(xml_bl_bank, loc_data, fabric_key,
|
||||
region_id);
|
||||
|
||||
/* Parse the WL shift register bank for this region */
|
||||
pugi::xml_node xml_wl_bank = get_single_child(xml_region, "wl_shift_register_banks", loc_data, pugiutil::ReqOpt::OPTIONAL);
|
||||
read_xml_region_wl_shift_register_banks(xml_wl_bank, loc_data, fabric_key, region_id);
|
||||
pugi::xml_node xml_wl_bank =
|
||||
get_single_child(xml_region, "wl_shift_register_banks", loc_data,
|
||||
pugiutil::ReqOpt::OPTIONAL);
|
||||
read_xml_region_wl_shift_register_banks(xml_wl_bank, loc_data, fabric_key,
|
||||
region_id);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Parse XML codes about <fabric> to an object of FabricKey
|
||||
*******************************************************************/
|
||||
FabricKey read_xml_fabric_key(const char* key_fname) {
|
||||
|
||||
vtr::ScopedStartFinishTimer timer("Read Fabric Key");
|
||||
|
||||
FabricKey fabric_key;
|
||||
|
@ -239,7 +252,8 @@ FabricKey read_xml_fabric_key(const char* key_fname) {
|
|||
|
||||
pugi::xml_node xml_root = get_single_child(doc, "fabric_key", loc_data);
|
||||
|
||||
size_t num_regions = std::distance(xml_root.children().begin(), xml_root.children().end());
|
||||
size_t num_regions =
|
||||
std::distance(xml_root.children().begin(), xml_root.children().end());
|
||||
/* Reserve memory space for the region */
|
||||
fabric_key.reserve_regions(num_regions);
|
||||
for (size_t iregion = 0; iregion < num_regions; ++iregion) {
|
||||
|
@ -254,7 +268,8 @@ FabricKey read_xml_fabric_key(const char* key_fname) {
|
|||
if (xml_region.name() != std::string("region")) {
|
||||
bad_tag(xml_region, loc_data, xml_root, {"region"});
|
||||
}
|
||||
num_keys += std::distance(xml_region.children().begin(), xml_region.children().end());
|
||||
num_keys += std::distance(xml_region.children().begin(),
|
||||
xml_region.children().end());
|
||||
}
|
||||
|
||||
fabric_key.reserve_keys(num_keys);
|
||||
|
@ -271,12 +286,10 @@ FabricKey read_xml_fabric_key(const char* key_fname) {
|
|||
bad_tag(xml_region, loc_data, xml_root, {"region"});
|
||||
}
|
||||
read_xml_fabric_region(xml_region, loc_data, fabric_key);
|
||||
}
|
||||
}
|
||||
} catch (pugiutil::XmlError& e) {
|
||||
archfpga_throw(key_fname, e.line(),
|
||||
"%s", e.what());
|
||||
archfpga_throw(key_fname, e.line(), "%s", e.what());
|
||||
}
|
||||
|
||||
return fabric_key;
|
||||
return fabric_key;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
/********************************************************************
|
||||
* This file includes functions that outputs a configuration protocol to XML format
|
||||
* This file includes functions that outputs a configuration protocol to XML
|
||||
*format
|
||||
*******************************************************************/
|
||||
/* Headers from system goes first */
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
/* Headers from vtr util library */
|
||||
#include "vtr_assert.h"
|
||||
|
@ -14,7 +15,7 @@
|
|||
#include "openfpga_digest.h"
|
||||
|
||||
/* Headers from arch openfpga library */
|
||||
#include "write_xml_utils.h"
|
||||
#include "write_xml_utils.h"
|
||||
|
||||
/* Headers from fabrickey library */
|
||||
#include "write_xml_fabric_key.h"
|
||||
|
@ -23,13 +24,12 @@
|
|||
* A writer to output a component key to XML format
|
||||
*
|
||||
* Return 0 if successful
|
||||
* Return 1 if there are more serious bugs in the architecture
|
||||
* Return 1 if there are more serious bugs in the architecture
|
||||
* Return 2 if fail when creating files
|
||||
*******************************************************************/
|
||||
static
|
||||
int write_xml_fabric_component_key(std::fstream& fp,
|
||||
const FabricKey& fabric_key,
|
||||
const FabricKeyId& component_key) {
|
||||
static int write_xml_fabric_component_key(std::fstream& fp,
|
||||
const FabricKey& fabric_key,
|
||||
const FabricKeyId& component_key) {
|
||||
/* Validate the file stream */
|
||||
if (false == openfpga::valid_file_stream(fp)) {
|
||||
return 2;
|
||||
|
@ -49,7 +49,8 @@ int write_xml_fabric_component_key(std::fstream& fp,
|
|||
write_xml_attribute(fp, "value", fabric_key.key_value(component_key));
|
||||
|
||||
if (!fabric_key.key_alias(component_key).empty()) {
|
||||
write_xml_attribute(fp, "alias", fabric_key.key_alias(component_key).c_str());
|
||||
write_xml_attribute(fp, "alias",
|
||||
fabric_key.key_alias(component_key).c_str());
|
||||
}
|
||||
|
||||
vtr::Point<int> coord = fabric_key.key_coordinate(component_key);
|
||||
|
@ -58,7 +59,8 @@ int write_xml_fabric_component_key(std::fstream& fp,
|
|||
write_xml_attribute(fp, "row", coord.y());
|
||||
}
|
||||
|
||||
fp << "/>" << "\n";
|
||||
fp << "/>"
|
||||
<< "\n";
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -67,13 +69,11 @@ int write_xml_fabric_component_key(std::fstream& fp,
|
|||
* A writer to output a BL shift register bank description to XML format
|
||||
*
|
||||
* Return 0 if successful
|
||||
* Return 1 if there are more serious bugs in the architecture
|
||||
* Return 1 if there are more serious bugs in the architecture
|
||||
* Return 2 if fail when creating files
|
||||
*******************************************************************/
|
||||
static
|
||||
int write_xml_fabric_bl_shift_register_banks(std::fstream& fp,
|
||||
const FabricKey& fabric_key,
|
||||
const FabricRegionId& region) {
|
||||
static int write_xml_fabric_bl_shift_register_banks(
|
||||
std::fstream& fp, const FabricKey& fabric_key, const FabricRegionId& region) {
|
||||
/* Validate the file stream */
|
||||
if (false == openfpga::valid_file_stream(fp)) {
|
||||
return 2;
|
||||
|
@ -86,14 +86,15 @@ int write_xml_fabric_bl_shift_register_banks(std::fstream& fp,
|
|||
|
||||
/* Write the root node */
|
||||
openfpga::write_tab_to_file(fp, 2);
|
||||
fp << "<bl_shift_register_banks>" << "\n";
|
||||
fp << "<bl_shift_register_banks>"
|
||||
<< "\n";
|
||||
|
||||
for (const auto& bank : fabric_key.bl_banks(region)) {
|
||||
openfpga::write_tab_to_file(fp, 3);
|
||||
fp << "<bank";
|
||||
|
||||
write_xml_attribute(fp, "id", size_t(bank));
|
||||
|
||||
|
||||
std::string port_str;
|
||||
for (const auto& port : fabric_key.bl_bank_data_ports(region, bank)) {
|
||||
port_str += generate_xml_port_name(port) + ",";
|
||||
|
@ -104,11 +105,13 @@ int write_xml_fabric_bl_shift_register_banks(std::fstream& fp,
|
|||
}
|
||||
write_xml_attribute(fp, "range", port_str.c_str());
|
||||
|
||||
fp << "/>" << "\n";
|
||||
fp << "/>"
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
openfpga::write_tab_to_file(fp, 2);
|
||||
fp << "</bl_shift_register_banks>" << "\n";
|
||||
fp << "</bl_shift_register_banks>"
|
||||
<< "\n";
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -117,13 +120,11 @@ int write_xml_fabric_bl_shift_register_banks(std::fstream& fp,
|
|||
* A writer to output a WL shift register bank description to XML format
|
||||
*
|
||||
* Return 0 if successful
|
||||
* Return 1 if there are more serious bugs in the architecture
|
||||
* Return 1 if there are more serious bugs in the architecture
|
||||
* Return 2 if fail when creating files
|
||||
*******************************************************************/
|
||||
static
|
||||
int write_xml_fabric_wl_shift_register_banks(std::fstream& fp,
|
||||
const FabricKey& fabric_key,
|
||||
const FabricRegionId& region) {
|
||||
static int write_xml_fabric_wl_shift_register_banks(
|
||||
std::fstream& fp, const FabricKey& fabric_key, const FabricRegionId& region) {
|
||||
/* Validate the file stream */
|
||||
if (false == openfpga::valid_file_stream(fp)) {
|
||||
return 2;
|
||||
|
@ -136,14 +137,15 @@ int write_xml_fabric_wl_shift_register_banks(std::fstream& fp,
|
|||
|
||||
/* Write the root node */
|
||||
openfpga::write_tab_to_file(fp, 2);
|
||||
fp << "<wl_shift_register_banks>" << "\n";
|
||||
fp << "<wl_shift_register_banks>"
|
||||
<< "\n";
|
||||
|
||||
for (const auto& bank : fabric_key.wl_banks(region)) {
|
||||
openfpga::write_tab_to_file(fp, 3);
|
||||
fp << "<bank";
|
||||
|
||||
write_xml_attribute(fp, "id", size_t(bank));
|
||||
|
||||
|
||||
std::string port_str;
|
||||
for (const auto& port : fabric_key.wl_bank_data_ports(region, bank)) {
|
||||
port_str += generate_xml_port_name(port) + ",";
|
||||
|
@ -154,11 +156,13 @@ int write_xml_fabric_wl_shift_register_banks(std::fstream& fp,
|
|||
}
|
||||
write_xml_attribute(fp, "range", port_str.c_str());
|
||||
|
||||
fp << "/>" << "\n";
|
||||
fp << "/>"
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
openfpga::write_tab_to_file(fp, 2);
|
||||
fp << "</wl_shift_register_banks>" << "\n";
|
||||
fp << "</wl_shift_register_banks>"
|
||||
<< "\n";
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -167,12 +171,10 @@ int write_xml_fabric_wl_shift_register_banks(std::fstream& fp,
|
|||
* A writer to output a fabric key to XML format
|
||||
*
|
||||
* Return 0 if successful
|
||||
* Return 1 if there are more serious bugs in the architecture
|
||||
* Return 1 if there are more serious bugs in the architecture
|
||||
* Return 2 if fail when creating files
|
||||
*******************************************************************/
|
||||
int write_xml_fabric_key(const char* fname,
|
||||
const FabricKey& fabric_key) {
|
||||
|
||||
int write_xml_fabric_key(const char* fname, const FabricKey& fabric_key) {
|
||||
vtr::ScopedStartFinishTimer timer("Write Fabric Key");
|
||||
|
||||
/* Create a file handler */
|
||||
|
@ -182,22 +184,24 @@ int write_xml_fabric_key(const char* fname,
|
|||
|
||||
/* Validate the file stream */
|
||||
openfpga::check_file_stream(fname, fp);
|
||||
|
||||
|
||||
/* Write the root node */
|
||||
fp << "<fabric_key>" << "\n";
|
||||
fp << "<fabric_key>"
|
||||
<< "\n";
|
||||
|
||||
int err_code = 0;
|
||||
|
||||
/* Write region by region */
|
||||
/* Write region by region */
|
||||
for (const FabricRegionId& region : fabric_key.regions()) {
|
||||
openfpga::write_tab_to_file(fp, 1);
|
||||
fp << "<region id=\"" << size_t(region) << "\"" << ">\n";
|
||||
fp << "<region id=\"" << size_t(region) << "\""
|
||||
<< ">\n";
|
||||
|
||||
/* Write shift register banks */
|
||||
write_xml_fabric_bl_shift_register_banks(fp, fabric_key, region);
|
||||
write_xml_fabric_wl_shift_register_banks(fp, fabric_key, region);
|
||||
|
||||
/* Write component by component */
|
||||
/* Write component by component */
|
||||
for (const FabricKeyId& key : fabric_key.region_keys(region)) {
|
||||
err_code = write_xml_fabric_component_key(fp, fabric_key, key);
|
||||
if (0 != err_code) {
|
||||
|
@ -206,11 +210,13 @@ int write_xml_fabric_key(const char* fname,
|
|||
}
|
||||
|
||||
openfpga::write_tab_to_file(fp, 1);
|
||||
fp << "</region>" << "\n";
|
||||
fp << "</region>"
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
/* Finish writing the root node */
|
||||
fp << "</fabric_key>" << "\n";
|
||||
fp << "</fabric_key>"
|
||||
<< "\n";
|
||||
|
||||
/* Close the file stream */
|
||||
fp.close();
|
||||
|
|
|
@ -5,12 +5,12 @@
|
|||
* Include header files that are required by function declaration
|
||||
*******************************************************************/
|
||||
#include <fstream>
|
||||
|
||||
#include "fabric_key.h"
|
||||
|
||||
/********************************************************************
|
||||
* Function declaration
|
||||
*******************************************************************/
|
||||
int write_xml_fabric_key(const char* fname,
|
||||
const FabricKey& fabric_key);
|
||||
int write_xml_fabric_key(const char* fname, const FabricKey& fabric_key);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/********************************************************************
|
||||
* Unit test functions to validate the correctness of
|
||||
* Unit test functions to validate the correctness of
|
||||
* 1. parser of data structures
|
||||
* 2. writer of data structures
|
||||
*******************************************************************/
|
||||
|
@ -15,20 +15,15 @@ int main(int argc, const char** argv) {
|
|||
/* Ensure we have only one or two argument */
|
||||
VTR_ASSERT((2 == argc) || (3 == argc));
|
||||
|
||||
|
||||
/* Parse the fabric key from an XML file */
|
||||
FabricKey test_key = read_xml_fabric_key(argv[1]);
|
||||
VTR_LOG("Read the fabric key from an XML file: %s.\n",
|
||||
argv[1]);
|
||||
VTR_LOG("Read the fabric key from an XML file: %s.\n", argv[1]);
|
||||
|
||||
/* Output the circuit library to an XML file
|
||||
* This is optional only used when there is a second argument
|
||||
*/
|
||||
if (3 <= argc) {
|
||||
if (3 <= argc) {
|
||||
write_xml_fabric_key(argv[2], test_key);
|
||||
VTR_LOG("Echo the fabric key to an XML file: %s.\n",
|
||||
argv[2]);
|
||||
VTR_LOG("Echo the fabric key to an XML file: %s.\n", argv[2]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
/******************************************************************************
|
||||
* This file includes member functions for data structure BitstreamManager
|
||||
* This file includes member functions for data structure BitstreamManager
|
||||
******************************************************************************/
|
||||
#include "bitstream_manager.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "vtr_assert.h"
|
||||
#include "bitstream_manager.h"
|
||||
|
||||
/* begin namespace openfpga */
|
||||
namespace openfpga {
|
||||
|
@ -23,23 +24,21 @@ BitstreamManager::BitstreamManager() {
|
|||
* Public Accessors : Aggregates
|
||||
*************************************************/
|
||||
/* Find all the configuration bits */
|
||||
size_t BitstreamManager::num_bits() const {
|
||||
return num_bits_;
|
||||
}
|
||||
size_t BitstreamManager::num_bits() const { return num_bits_; }
|
||||
|
||||
BitstreamManager::config_bit_range BitstreamManager::bits() const {
|
||||
return vtr::make_range(config_bit_iterator(ConfigBitId(0), invalid_bit_ids_),
|
||||
config_bit_iterator(ConfigBitId(num_bits_), invalid_bit_ids_));
|
||||
return vtr::make_range(
|
||||
config_bit_iterator(ConfigBitId(0), invalid_bit_ids_),
|
||||
config_bit_iterator(ConfigBitId(num_bits_), invalid_bit_ids_));
|
||||
}
|
||||
|
||||
size_t BitstreamManager::num_blocks() const {
|
||||
return num_blocks_;
|
||||
}
|
||||
size_t BitstreamManager::num_blocks() const { return num_blocks_; }
|
||||
|
||||
/* Find all the configuration blocks */
|
||||
BitstreamManager::config_block_range BitstreamManager::blocks() const {
|
||||
return vtr::make_range(config_block_iterator(ConfigBlockId(0), invalid_block_ids_),
|
||||
config_block_iterator(ConfigBlockId(num_blocks_), invalid_block_ids_));
|
||||
return vtr::make_range(
|
||||
config_block_iterator(ConfigBlockId(0), invalid_block_ids_),
|
||||
config_block_iterator(ConfigBlockId(num_blocks_), invalid_block_ids_));
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
|
@ -52,7 +51,8 @@ bool BitstreamManager::bit_value(const ConfigBitId& bit_id) const {
|
|||
return '1' == bit_values_[bit_id];
|
||||
}
|
||||
|
||||
ConfigBlockId BitstreamManager::bit_parent_block(const ConfigBitId& bit_id) const {
|
||||
ConfigBlockId BitstreamManager::bit_parent_block(
|
||||
const ConfigBitId& bit_id) const {
|
||||
/* Ensure a valid id */
|
||||
VTR_ASSERT(true == valid_bit_id(bit_id));
|
||||
|
||||
|
@ -66,26 +66,29 @@ std::string BitstreamManager::block_name(const ConfigBlockId& block_id) const {
|
|||
return block_names_[block_id];
|
||||
}
|
||||
|
||||
ConfigBlockId BitstreamManager::block_parent(const ConfigBlockId& block_id) const {
|
||||
ConfigBlockId BitstreamManager::block_parent(
|
||||
const ConfigBlockId& block_id) const {
|
||||
/* Ensure the input ids are valid */
|
||||
VTR_ASSERT(true == valid_block_id(block_id));
|
||||
|
||||
return parent_block_ids_[block_id];
|
||||
}
|
||||
|
||||
std::vector<ConfigBlockId> BitstreamManager::block_children(const ConfigBlockId& block_id) const {
|
||||
std::vector<ConfigBlockId> BitstreamManager::block_children(
|
||||
const ConfigBlockId& block_id) const {
|
||||
/* Ensure the input ids are valid */
|
||||
VTR_ASSERT(true == valid_block_id(block_id));
|
||||
|
||||
return child_block_ids_[block_id];
|
||||
}
|
||||
|
||||
std::vector<ConfigBitId> BitstreamManager::block_bits(const ConfigBlockId& block_id) const {
|
||||
std::vector<ConfigBitId> BitstreamManager::block_bits(
|
||||
const ConfigBlockId& block_id) const {
|
||||
/* Ensure the input ids are valid */
|
||||
VTR_ASSERT(true == valid_block_id(block_id));
|
||||
|
||||
size_t lsb = block_bit_id_lsbs_[block_id];
|
||||
size_t length = block_bit_lengths_[block_id];
|
||||
size_t lsb = block_bit_id_lsbs_[block_id];
|
||||
size_t length = block_bit_lengths_[block_id];
|
||||
|
||||
std::vector<ConfigBitId> bits(length, ConfigBitId::INVALID());
|
||||
|
||||
|
@ -101,8 +104,8 @@ std::vector<ConfigBitId> BitstreamManager::block_bits(const ConfigBlockId& block
|
|||
}
|
||||
|
||||
/* Find the child block in a bitstream manager with a given name */
|
||||
ConfigBlockId BitstreamManager::find_child_block(const ConfigBlockId& block_id,
|
||||
const std::string& child_block_name) const {
|
||||
ConfigBlockId BitstreamManager::find_child_block(
|
||||
const ConfigBlockId& block_id, const std::string& child_block_name) const {
|
||||
/* Ensure the input ids are valid */
|
||||
VTR_ASSERT(true == valid_block_id(block_id));
|
||||
|
||||
|
@ -130,14 +133,16 @@ int BitstreamManager::block_path_id(const ConfigBlockId& block_id) const {
|
|||
return block_path_ids_[block_id];
|
||||
}
|
||||
|
||||
std::string BitstreamManager::block_input_net_ids(const ConfigBlockId& block_id) const {
|
||||
std::string BitstreamManager::block_input_net_ids(
|
||||
const ConfigBlockId& block_id) const {
|
||||
/* Ensure the input ids are valid */
|
||||
VTR_ASSERT(true == valid_block_id(block_id));
|
||||
|
||||
return block_input_net_ids_[block_id];
|
||||
}
|
||||
|
||||
std::string BitstreamManager::block_output_net_ids(const ConfigBlockId& block_id) const {
|
||||
std::string BitstreamManager::block_output_net_ids(
|
||||
const ConfigBlockId& block_id) const {
|
||||
/* Ensure the input ids are valid */
|
||||
VTR_ASSERT(true == valid_block_id(block_id));
|
||||
|
||||
|
@ -147,7 +152,8 @@ std::string BitstreamManager::block_output_net_ids(const ConfigBlockId& block_id
|
|||
/******************************************************************************
|
||||
* Public Mutators
|
||||
******************************************************************************/
|
||||
ConfigBitId BitstreamManager::add_bit(const ConfigBlockId& parent_block, const bool& bit_value) {
|
||||
ConfigBitId BitstreamManager::add_bit(const ConfigBlockId& parent_block,
|
||||
const bool& bit_value) {
|
||||
ConfigBitId bit = ConfigBitId(num_bits_);
|
||||
/* Add a new bit, and allocate associated data structures */
|
||||
num_bits_++;
|
||||
|
@ -159,7 +165,7 @@ ConfigBitId BitstreamManager::add_bit(const ConfigBlockId& parent_block, const b
|
|||
|
||||
bit_parent_blocks_.push_back(parent_block);
|
||||
|
||||
return bit;
|
||||
return bit;
|
||||
}
|
||||
|
||||
void BitstreamManager::reserve_blocks(const size_t& num_blocks) {
|
||||
|
@ -190,13 +196,13 @@ ConfigBlockId BitstreamManager::create_block() {
|
|||
parent_block_ids_.push_back(ConfigBlockId::INVALID());
|
||||
child_block_ids_.emplace_back();
|
||||
|
||||
return block;
|
||||
return block;
|
||||
}
|
||||
|
||||
ConfigBlockId BitstreamManager::add_block(const std::string& block_name) {
|
||||
ConfigBlockId block = create_block();
|
||||
set_block_name(block, block_name);
|
||||
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
|
@ -216,7 +222,8 @@ void BitstreamManager::reserve_child_blocks(const ConfigBlockId& parent_block,
|
|||
child_block_ids_[parent_block].reserve(num_children);
|
||||
}
|
||||
|
||||
void BitstreamManager::add_child_block(const ConfigBlockId& parent_block, const ConfigBlockId& child_block) {
|
||||
void BitstreamManager::add_child_block(const ConfigBlockId& parent_block,
|
||||
const ConfigBlockId& child_block) {
|
||||
/* Ensure the input ids are valid */
|
||||
VTR_ASSERT(true == valid_block_id(parent_block));
|
||||
VTR_ASSERT(true == valid_block_id(child_block));
|
||||
|
@ -224,8 +231,11 @@ void BitstreamManager::add_child_block(const ConfigBlockId& parent_block, const
|
|||
/* We should have only a parent block for each block! */
|
||||
VTR_ASSERT(ConfigBlockId::INVALID() == parent_block_ids_[child_block]);
|
||||
|
||||
/* Ensure the child block is not in the list of children of the parent block */
|
||||
std::vector<ConfigBlockId>::iterator it = std::find(child_block_ids_[parent_block].begin(), child_block_ids_[parent_block].end(), child_block);
|
||||
/* Ensure the child block is not in the list of children of the parent block
|
||||
*/
|
||||
std::vector<ConfigBlockId>::iterator it =
|
||||
std::find(child_block_ids_[parent_block].begin(),
|
||||
child_block_ids_[parent_block].end(), child_block);
|
||||
VTR_ASSERT(it == child_block_ids_[parent_block].end());
|
||||
|
||||
/* Add the child_block to the parent_block */
|
||||
|
@ -234,12 +244,13 @@ void BitstreamManager::add_child_block(const ConfigBlockId& parent_block, const
|
|||
parent_block_ids_[child_block] = parent_block;
|
||||
}
|
||||
|
||||
void BitstreamManager::add_block_bits(const ConfigBlockId& block,
|
||||
const std::vector<bool>& block_bitstream) {
|
||||
void BitstreamManager::add_block_bits(
|
||||
const ConfigBlockId& block, const std::vector<bool>& block_bitstream) {
|
||||
/* Ensure the input ids are valid */
|
||||
VTR_ASSERT(true == valid_block_id(block));
|
||||
|
||||
/* Add the bit to the block, record anchors in bit indexing for block-level searching */
|
||||
/* Add the bit to the block, record anchors in bit indexing for block-level
|
||||
* searching */
|
||||
block_bit_id_lsbs_[block] = num_bits_;
|
||||
block_bit_lengths_[block] = block_bitstream.size();
|
||||
for (const bool& bit : block_bitstream) {
|
||||
|
@ -247,7 +258,8 @@ void BitstreamManager::add_block_bits(const ConfigBlockId& block,
|
|||
}
|
||||
}
|
||||
|
||||
void BitstreamManager::add_path_id_to_block(const ConfigBlockId& block, const int& path_id) {
|
||||
void BitstreamManager::add_path_id_to_block(const ConfigBlockId& block,
|
||||
const int& path_id) {
|
||||
/* Ensure the input ids are valid */
|
||||
VTR_ASSERT(true == valid_block_id(block));
|
||||
|
||||
|
@ -255,8 +267,8 @@ void BitstreamManager::add_path_id_to_block(const ConfigBlockId& block, const in
|
|||
block_path_ids_[block] = path_id;
|
||||
}
|
||||
|
||||
void BitstreamManager::add_input_net_id_to_block(const ConfigBlockId& block,
|
||||
const std::string& input_net_id) {
|
||||
void BitstreamManager::add_input_net_id_to_block(
|
||||
const ConfigBlockId& block, const std::string& input_net_id) {
|
||||
/* Ensure the input ids are valid */
|
||||
VTR_ASSERT(true == valid_block_id(block));
|
||||
|
||||
|
@ -264,8 +276,8 @@ void BitstreamManager::add_input_net_id_to_block(const ConfigBlockId& block,
|
|||
block_input_net_ids_[block] = input_net_id;
|
||||
}
|
||||
|
||||
void BitstreamManager::add_output_net_id_to_block(const ConfigBlockId& block,
|
||||
const std::string& output_net_id) {
|
||||
void BitstreamManager::add_output_net_id_to_block(
|
||||
const ConfigBlockId& block, const std::string& output_net_id) {
|
||||
/* Ensure the input ids are valid */
|
||||
VTR_ASSERT(true == valid_block_id(block));
|
||||
|
||||
|
@ -284,7 +296,8 @@ bool BitstreamManager::valid_block_id(const ConfigBlockId& block_id) const {
|
|||
return (size_t(block_id) < num_blocks_);
|
||||
}
|
||||
|
||||
bool BitstreamManager::valid_block_path_id(const ConfigBlockId& block_id) const {
|
||||
bool BitstreamManager::valid_block_path_id(
|
||||
const ConfigBlockId& block_id) const {
|
||||
return (true == valid_block_id(block_id)) && (-2 != block_path_id(block_id));
|
||||
}
|
||||
|
||||
|
|
|
@ -1,244 +1,266 @@
|
|||
/******************************************************************************
|
||||
* This file introduces a data structure to store bitstream-related information
|
||||
* This file introduces a data structure to store bitstream-related information
|
||||
*
|
||||
* General concept
|
||||
* ---------------
|
||||
* The idea is to create a unified data structure that stores all the configuration bits
|
||||
* with proper annotation to which modules in FPGA fabric it belongs to.
|
||||
* 1. It can be easily organized in fabric-dependent representation
|
||||
* (generate a sequence of bitstream which exactly fit the configuration protocol of FPGA fabric)
|
||||
* 2. Or it can be easily organized in fabric-independent representation (think about XML file)
|
||||
* The idea is to create a unified data structure that stores all the
|
||||
*configuration bits with proper annotation to which modules in FPGA fabric it
|
||||
*belongs to.
|
||||
* 1. It can be easily organized in fabric-dependent representation
|
||||
* (generate a sequence of bitstream which exactly fit the configuration
|
||||
*protocol of FPGA fabric)
|
||||
* 2. Or it can be easily organized in fabric-independent representation
|
||||
*(think about XML file)
|
||||
*
|
||||
* Cross-reference
|
||||
* Cross-reference
|
||||
* ---------------
|
||||
* May be used only when you want to bind the bitstream to a specific FPGA fabric!
|
||||
* If you do so, please make sure the block name is exactly same as the instance name
|
||||
* of a child module in ModuleManager!!!
|
||||
* The configurable modules/instances in module manager are arranged
|
||||
* in the sequence to fit different configuration protocol.
|
||||
* By using the link between ModuleManager and BitstreamManager,
|
||||
* we can build a sequence of configuration bits to fit different configuration protocols.
|
||||
* May be used only when you want to bind the bitstream to a specific FPGA
|
||||
*fabric! If you do so, please make sure the block name is exactly same as the
|
||||
*instance name of a child module in ModuleManager!!! The configurable
|
||||
*modules/instances in module manager are arranged in the sequence to fit
|
||||
*different configuration protocol. By using the link between ModuleManager and
|
||||
*BitstreamManager, we can build a sequence of configuration bits to fit
|
||||
*different configuration protocols.
|
||||
*
|
||||
* +------------------+ +-----------------+
|
||||
* | | block_name == instance_name | |
|
||||
* | BitstreamManager |-------------------------------->| ModuleManager |
|
||||
* | | | |
|
||||
* +------------------+ +-----------------+
|
||||
* +------------------+ +-----------------+
|
||||
*
|
||||
* Restrictions:
|
||||
* 1. Each block inside BitstreamManager should have only 1 parent block
|
||||
* 1. Each block inside BitstreamManager should have only 1 parent block
|
||||
* and multiple child block
|
||||
* 2. Each bit inside BitstreamManager should have only 1 parent block
|
||||
*
|
||||
* 2. Each bit inside BitstreamManager should have only 1 parent block
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef BITSTREAM_MANAGER_H
|
||||
#define BITSTREAM_MANAGER_H
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <unordered_set>
|
||||
#include <unordered_map>
|
||||
#include "vtr_vector.h"
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
#include "bitstream_manager_fwd.h"
|
||||
#include "vtr_vector.h"
|
||||
|
||||
/* begin namespace openfpga */
|
||||
namespace openfpga {
|
||||
|
||||
class BitstreamManager {
|
||||
public: /* Type implementations */
|
||||
/*
|
||||
* This class (forward delcared above) is a template used to represent a lazily calculated
|
||||
* iterator of the specified ID type. The key assumption made is that the ID space is
|
||||
* contiguous and can be walked by incrementing the underlying ID value. To account for
|
||||
* invalid IDs, it keeps a reference to the invalid ID set and returns ID::INVALID() for
|
||||
* ID values in the set.
|
||||
*
|
||||
* It is used to lazily create an iteration range (e.g. as returned by RRGraph::edges() RRGraph::nodes())
|
||||
* just based on the count of allocated elements (i.e. RRGraph::num_nodes_ or RRGraph::num_edges_),
|
||||
* and the set of any invalid IDs (i.e. RRGraph::invalid_node_ids_, RRGraph::invalid_edge_ids_).
|
||||
*/
|
||||
template<class ID>
|
||||
class lazy_id_iterator : public std::iterator<std::bidirectional_iterator_tag, ID> {
|
||||
public:
|
||||
//Since we pass ID as a template to std::iterator we need to use an explicit 'typename'
|
||||
//to bring the value_type and iterator names into scope
|
||||
typedef typename std::iterator<std::bidirectional_iterator_tag, ID>::value_type value_type;
|
||||
typedef typename std::iterator<std::bidirectional_iterator_tag, ID>::iterator iterator;
|
||||
public: /* Type implementations */
|
||||
/*
|
||||
* This class (forward delcared above) is a template used to represent a
|
||||
* lazily calculated iterator of the specified ID type. The key assumption
|
||||
* made is that the ID space is contiguous and can be walked by incrementing
|
||||
* the underlying ID value. To account for invalid IDs, it keeps a reference
|
||||
* to the invalid ID set and returns ID::INVALID() for ID values in the set.
|
||||
*
|
||||
* It is used to lazily create an iteration range (e.g. as returned by
|
||||
* RRGraph::edges() RRGraph::nodes()) just based on the count of allocated
|
||||
* elements (i.e. RRGraph::num_nodes_ or RRGraph::num_edges_), and the set of
|
||||
* any invalid IDs (i.e. RRGraph::invalid_node_ids_,
|
||||
* RRGraph::invalid_edge_ids_).
|
||||
*/
|
||||
template <class ID>
|
||||
class lazy_id_iterator
|
||||
: public std::iterator<std::bidirectional_iterator_tag, ID> {
|
||||
public:
|
||||
// Since we pass ID as a template to std::iterator we need to use an
|
||||
// explicit 'typename' to bring the value_type and iterator names into scope
|
||||
typedef
|
||||
typename std::iterator<std::bidirectional_iterator_tag, ID>::value_type
|
||||
value_type;
|
||||
typedef
|
||||
typename std::iterator<std::bidirectional_iterator_tag, ID>::iterator
|
||||
iterator;
|
||||
|
||||
lazy_id_iterator(value_type init, const std::unordered_set<ID>& invalid_ids)
|
||||
: value_(init)
|
||||
, invalid_ids_(invalid_ids) {}
|
||||
lazy_id_iterator(value_type init, const std::unordered_set<ID>& invalid_ids)
|
||||
: value_(init), invalid_ids_(invalid_ids) {}
|
||||
|
||||
//Advance to the next ID value
|
||||
iterator operator++() {
|
||||
value_ = ID(size_t(value_) + 1);
|
||||
return *this;
|
||||
}
|
||||
// Advance to the next ID value
|
||||
iterator operator++() {
|
||||
value_ = ID(size_t(value_) + 1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//Advance to the previous ID value
|
||||
iterator operator--() {
|
||||
value_ = ID(size_t(value_) - 1);
|
||||
return *this;
|
||||
}
|
||||
// Advance to the previous ID value
|
||||
iterator operator--() {
|
||||
value_ = ID(size_t(value_) - 1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//Dereference the iterator
|
||||
value_type operator*() const { return (invalid_ids_.count(value_)) ? ID::INVALID() : value_; }
|
||||
// Dereference the iterator
|
||||
value_type operator*() const {
|
||||
return (invalid_ids_.count(value_)) ? ID::INVALID() : value_;
|
||||
}
|
||||
|
||||
friend bool operator==(const lazy_id_iterator<ID> lhs, const lazy_id_iterator<ID> rhs) { return lhs.value_ == rhs.value_; }
|
||||
friend bool operator!=(const lazy_id_iterator<ID> lhs, const lazy_id_iterator<ID> rhs) { return !(lhs == rhs); }
|
||||
friend bool operator==(const lazy_id_iterator<ID> lhs,
|
||||
const lazy_id_iterator<ID> rhs) {
|
||||
return lhs.value_ == rhs.value_;
|
||||
}
|
||||
friend bool operator!=(const lazy_id_iterator<ID> lhs,
|
||||
const lazy_id_iterator<ID> rhs) {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
private:
|
||||
value_type value_;
|
||||
const std::unordered_set<ID>& invalid_ids_;
|
||||
};
|
||||
private:
|
||||
value_type value_;
|
||||
const std::unordered_set<ID>& invalid_ids_;
|
||||
};
|
||||
|
||||
public: /* Public constructor */
|
||||
BitstreamManager();
|
||||
public: /* Public constructor */
|
||||
BitstreamManager();
|
||||
|
||||
public: /* Types and ranges */
|
||||
//Lazy iterator utility forward declaration
|
||||
template<class ID>
|
||||
class lazy_id_iterator;
|
||||
public: /* Types and ranges */
|
||||
// Lazy iterator utility forward declaration
|
||||
template <class ID>
|
||||
class lazy_id_iterator;
|
||||
|
||||
typedef lazy_id_iterator<ConfigBitId> config_bit_iterator;
|
||||
typedef lazy_id_iterator<ConfigBlockId> config_block_iterator;
|
||||
typedef lazy_id_iterator<ConfigBitId> config_bit_iterator;
|
||||
typedef lazy_id_iterator<ConfigBlockId> config_block_iterator;
|
||||
|
||||
typedef vtr::Range<config_bit_iterator> config_bit_range;
|
||||
typedef vtr::Range<config_block_iterator> config_block_range;
|
||||
typedef vtr::Range<config_bit_iterator> config_bit_range;
|
||||
typedef vtr::Range<config_block_iterator> config_block_range;
|
||||
|
||||
public: /* Public aggregators */
|
||||
/* Find all the configuration bits */
|
||||
size_t num_bits() const;
|
||||
config_bit_range bits() const;
|
||||
public: /* Public aggregators */
|
||||
/* Find all the configuration bits */
|
||||
size_t num_bits() const;
|
||||
config_bit_range bits() const;
|
||||
|
||||
size_t num_blocks() const;
|
||||
config_block_range blocks() const;
|
||||
size_t num_blocks() const;
|
||||
config_block_range blocks() const;
|
||||
|
||||
public: /* Public Accessors */
|
||||
/* Find the value of bitstream */
|
||||
bool bit_value(const ConfigBitId& bit_id) const;
|
||||
public: /* Public Accessors */
|
||||
/* Find the value of bitstream */
|
||||
bool bit_value(const ConfigBitId& bit_id) const;
|
||||
|
||||
/* Find the parent block of a configuration bit */
|
||||
ConfigBlockId bit_parent_block(const ConfigBitId& bit_id) const;
|
||||
/* Find the parent block of a configuration bit */
|
||||
ConfigBlockId bit_parent_block(const ConfigBitId& bit_id) const;
|
||||
|
||||
/* Find a name of a block */
|
||||
std::string block_name(const ConfigBlockId& block_id) const;
|
||||
/* Find a name of a block */
|
||||
std::string block_name(const ConfigBlockId& block_id) const;
|
||||
|
||||
/* Find the parent of a block */
|
||||
ConfigBlockId block_parent(const ConfigBlockId& block_id) const;
|
||||
/* Find the parent of a block */
|
||||
ConfigBlockId block_parent(const ConfigBlockId& block_id) const;
|
||||
|
||||
/* Find the children of a block */
|
||||
std::vector<ConfigBlockId> block_children(const ConfigBlockId& block_id) const;
|
||||
/* Find the children of a block */
|
||||
std::vector<ConfigBlockId> block_children(
|
||||
const ConfigBlockId& block_id) const;
|
||||
|
||||
/* Find all the bits that belong to a block */
|
||||
std::vector<ConfigBitId> block_bits(const ConfigBlockId& block_id) const;
|
||||
/* Find all the bits that belong to a block */
|
||||
std::vector<ConfigBitId> block_bits(const ConfigBlockId& block_id) const;
|
||||
|
||||
/* Find the child block in a bitstream manager with a given name */
|
||||
ConfigBlockId find_child_block(const ConfigBlockId& block_id, const std::string& child_block_name) const;
|
||||
/* Find the child block in a bitstream manager with a given name */
|
||||
ConfigBlockId find_child_block(const ConfigBlockId& block_id,
|
||||
const std::string& child_block_name) const;
|
||||
|
||||
/* Find path id of a block */
|
||||
int block_path_id(const ConfigBlockId& block_id) const;
|
||||
/* Find path id of a block */
|
||||
int block_path_id(const ConfigBlockId& block_id) const;
|
||||
|
||||
/* Find input net ids of a block */
|
||||
std::string block_input_net_ids(const ConfigBlockId& block_id) const;
|
||||
/* Find input net ids of a block */
|
||||
std::string block_input_net_ids(const ConfigBlockId& block_id) const;
|
||||
|
||||
/* Find input net ids of a block */
|
||||
std::string block_output_net_ids(const ConfigBlockId& block_id) const;
|
||||
/* Find input net ids of a block */
|
||||
std::string block_output_net_ids(const ConfigBlockId& block_id) const;
|
||||
|
||||
public: /* Public Mutators */
|
||||
/* Add a new configuration bit to the bitstream manager */
|
||||
ConfigBitId add_bit(const ConfigBlockId& parent_block, const bool& bit_value);
|
||||
public: /* Public Mutators */
|
||||
/* Add a new configuration bit to the bitstream manager */
|
||||
ConfigBitId add_bit(const ConfigBlockId& parent_block, const bool& bit_value);
|
||||
|
||||
/* Reserve memory for a number of clocks */
|
||||
void reserve_blocks(const size_t& num_blocks);
|
||||
/* Reserve memory for a number of clocks */
|
||||
void reserve_blocks(const size_t& num_blocks);
|
||||
|
||||
/* Reserve memory for a number of bits */
|
||||
void reserve_bits(const size_t& num_bits);
|
||||
/* Reserve memory for a number of bits */
|
||||
void reserve_bits(const size_t& num_bits);
|
||||
|
||||
/* Create a new block of configuration bits */
|
||||
ConfigBlockId create_block();
|
||||
/* Create a new block of configuration bits */
|
||||
ConfigBlockId create_block();
|
||||
|
||||
/* Add a new block of configuration bits to the bitstream manager */
|
||||
ConfigBlockId add_block(const std::string& block_name);
|
||||
/* Add a new block of configuration bits to the bitstream manager */
|
||||
ConfigBlockId add_block(const std::string& block_name);
|
||||
|
||||
/* Set a name for a block */
|
||||
void set_block_name(const ConfigBlockId& block_id,
|
||||
const std::string& block_name);
|
||||
/* Set a name for a block */
|
||||
void set_block_name(const ConfigBlockId& block_id,
|
||||
const std::string& block_name);
|
||||
|
||||
/* Reserve child blocks for a block to be memory efficient */
|
||||
void reserve_child_blocks(const ConfigBlockId& parent_block,
|
||||
const size_t& num_children);
|
||||
/* Reserve child blocks for a block to be memory efficient */
|
||||
void reserve_child_blocks(const ConfigBlockId& parent_block,
|
||||
const size_t& num_children);
|
||||
|
||||
/* Set a block as a child block of another */
|
||||
void add_child_block(const ConfigBlockId& parent_block, const ConfigBlockId& child_block);
|
||||
/* Set a block as a child block of another */
|
||||
void add_child_block(const ConfigBlockId& parent_block,
|
||||
const ConfigBlockId& child_block);
|
||||
|
||||
/* Add a bitstream to a block */
|
||||
void add_block_bits(const ConfigBlockId& block,
|
||||
const std::vector<bool>& block_bitstream);
|
||||
/* Add a bitstream to a block */
|
||||
void add_block_bits(const ConfigBlockId& block,
|
||||
const std::vector<bool>& block_bitstream);
|
||||
|
||||
/* Add a path id to a block */
|
||||
void add_path_id_to_block(const ConfigBlockId& block, const int& path_id);
|
||||
|
||||
/* Add an input net id to a block */
|
||||
void add_input_net_id_to_block(const ConfigBlockId& block, const std::string& input_net_id);
|
||||
/* Add a path id to a block */
|
||||
void add_path_id_to_block(const ConfigBlockId& block, const int& path_id);
|
||||
|
||||
/* Add an output net id to a block */
|
||||
void add_output_net_id_to_block(const ConfigBlockId& block, const std::string& output_net_id);
|
||||
/* Add an input net id to a block */
|
||||
void add_input_net_id_to_block(const ConfigBlockId& block,
|
||||
const std::string& input_net_id);
|
||||
|
||||
public: /* Public Validators */
|
||||
bool valid_bit_id(const ConfigBitId& bit_id) const;
|
||||
/* Add an output net id to a block */
|
||||
void add_output_net_id_to_block(const ConfigBlockId& block,
|
||||
const std::string& output_net_id);
|
||||
|
||||
bool valid_block_id(const ConfigBlockId& block_id) const;
|
||||
public: /* Public Validators */
|
||||
bool valid_bit_id(const ConfigBitId& bit_id) const;
|
||||
|
||||
bool valid_block_path_id(const ConfigBlockId& block_id) const;
|
||||
bool valid_block_id(const ConfigBlockId& block_id) const;
|
||||
|
||||
private: /* Internal data */
|
||||
/* Unique id of a block of bits in the Bitstream */
|
||||
size_t num_blocks_;
|
||||
std::unordered_set<ConfigBlockId> invalid_block_ids_;
|
||||
vtr::vector<ConfigBlockId, size_t> block_bit_id_lsbs_;
|
||||
vtr::vector<ConfigBlockId, short> block_bit_lengths_;
|
||||
bool valid_block_path_id(const ConfigBlockId& block_id) const;
|
||||
|
||||
/* Back-annotation for the bits */
|
||||
/* Parent block of a bit in the Bitstream
|
||||
* For each bit, the block name can be designed to be same as the instance name in a module
|
||||
* to reflect its position in the module tree (ModuleManager)
|
||||
* Note that the blocks here all unique, unlike ModuleManager where modules can be instanciated
|
||||
* Therefore, this block graph can be considered as a flattened graph of ModuleGraph
|
||||
*/
|
||||
vtr::vector<ConfigBlockId, std::string> block_names_;
|
||||
vtr::vector<ConfigBlockId, ConfigBlockId> parent_block_ids_;
|
||||
vtr::vector<ConfigBlockId, std::vector<ConfigBlockId>> child_block_ids_;
|
||||
private: /* Internal data */
|
||||
/* Unique id of a block of bits in the Bitstream */
|
||||
size_t num_blocks_;
|
||||
std::unordered_set<ConfigBlockId> invalid_block_ids_;
|
||||
vtr::vector<ConfigBlockId, size_t> block_bit_id_lsbs_;
|
||||
vtr::vector<ConfigBlockId, short> block_bit_lengths_;
|
||||
|
||||
/* The ids of the inputs of routing multiplexer blocks which is propagated to outputs
|
||||
* By default, it will be -2 (which is invalid)
|
||||
* A valid id starts from -1
|
||||
* -1 indicates an unused routing multiplexer.
|
||||
* It will be converted to a valid id by bitstream builders)
|
||||
* For used routing multiplexers, the path id will be >= 0
|
||||
*
|
||||
* Note:
|
||||
* -Bitstream manager will NOT check if the id is good for bitstream builders
|
||||
* It just store the results
|
||||
*/
|
||||
vtr::vector<ConfigBlockId, short> block_path_ids_;
|
||||
/* Back-annotation for the bits */
|
||||
/* Parent block of a bit in the Bitstream
|
||||
* For each bit, the block name can be designed to be same as the instance
|
||||
* name in a module to reflect its position in the module tree (ModuleManager)
|
||||
* Note that the blocks here all unique, unlike ModuleManager where modules
|
||||
* can be instanciated Therefore, this block graph can be considered as a
|
||||
* flattened graph of ModuleGraph
|
||||
*/
|
||||
vtr::vector<ConfigBlockId, std::string> block_names_;
|
||||
vtr::vector<ConfigBlockId, ConfigBlockId> parent_block_ids_;
|
||||
vtr::vector<ConfigBlockId, std::vector<ConfigBlockId>> child_block_ids_;
|
||||
|
||||
/* Net ids that are mapped to inputs and outputs of this block
|
||||
*
|
||||
* Note:
|
||||
* -Bitstream manager will NOT check if the id is good for bitstream builders
|
||||
* It just store the results
|
||||
*/
|
||||
vtr::vector<ConfigBlockId, std::string> block_input_net_ids_;
|
||||
vtr::vector<ConfigBlockId, std::string> block_output_net_ids_;
|
||||
/* The ids of the inputs of routing multiplexer blocks which is propagated to
|
||||
* outputs By default, it will be -2 (which is invalid) A valid id starts from
|
||||
* -1 -1 indicates an unused routing multiplexer. It will be converted to a
|
||||
* valid id by bitstream builders) For used routing multiplexers, the path id
|
||||
* will be >= 0
|
||||
*
|
||||
* Note:
|
||||
* -Bitstream manager will NOT check if the id is good for bitstream
|
||||
* builders It just store the results
|
||||
*/
|
||||
vtr::vector<ConfigBlockId, short> block_path_ids_;
|
||||
|
||||
/* Unique id of a bit in the Bitstream */
|
||||
size_t num_bits_;
|
||||
std::unordered_set<ConfigBitId> invalid_bit_ids_;
|
||||
/* value of a bit in the Bitstream */
|
||||
vtr::vector<ConfigBitId, char> bit_values_;
|
||||
vtr::vector<ConfigBitId, ConfigBlockId> bit_parent_blocks_;
|
||||
/* Net ids that are mapped to inputs and outputs of this block
|
||||
*
|
||||
* Note:
|
||||
* -Bitstream manager will NOT check if the id is good for bitstream
|
||||
* builders It just store the results
|
||||
*/
|
||||
vtr::vector<ConfigBlockId, std::string> block_input_net_ids_;
|
||||
vtr::vector<ConfigBlockId, std::string> block_output_net_ids_;
|
||||
|
||||
/* Unique id of a bit in the Bitstream */
|
||||
size_t num_bits_;
|
||||
std::unordered_set<ConfigBitId> invalid_bit_ids_;
|
||||
/* value of a bit in the Bitstream */
|
||||
vtr::vector<ConfigBitId, char> bit_values_;
|
||||
vtr::vector<ConfigBitId, ConfigBlockId> bit_parent_blocks_;
|
||||
};
|
||||
|
||||
} /* end namespace openfpga */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/**************************************************
|
||||
* This file includes only declarations for
|
||||
* This file includes only declarations for
|
||||
* the data structures for bitstream database
|
||||
* Please refer to bitstream_manager.h for more details
|
||||
*************************************************/
|
||||
|
@ -22,4 +22,4 @@ class BitstreamManager;
|
|||
|
||||
} /* end namespace openfpga */
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -3,33 +3,32 @@
|
|||
* BitstreamManager
|
||||
*
|
||||
* Note: These functions are not generic enough so that they
|
||||
* should NOT be a member function!
|
||||
* should NOT be a member function!
|
||||
*******************************************************************/
|
||||
#include <algorithm>
|
||||
|
||||
/* Headers from vtrutil library */
|
||||
#include "vtr_assert.h"
|
||||
|
||||
#include "bitstream_manager_utils.h"
|
||||
#include "vtr_assert.h"
|
||||
|
||||
/* begin namespace openfpga */
|
||||
namespace openfpga {
|
||||
|
||||
/********************************************************************
|
||||
* Recursively find the hierarchy of a block of bitstream manager
|
||||
* Return a vector of the block ids, where the top-level block
|
||||
* locates in the head, while the leaf block locates in the tail
|
||||
* Recursively find the hierarchy of a block of bitstream manager
|
||||
* Return a vector of the block ids, where the top-level block
|
||||
* locates in the head, while the leaf block locates in the tail
|
||||
* top, next, ... , block
|
||||
*******************************************************************/
|
||||
std::vector<ConfigBlockId> find_bitstream_manager_block_hierarchy(const BitstreamManager& bitstream_manager,
|
||||
const ConfigBlockId& block) {
|
||||
std::vector<ConfigBlockId> find_bitstream_manager_block_hierarchy(
|
||||
const BitstreamManager& bitstream_manager, const ConfigBlockId& block) {
|
||||
std::vector<ConfigBlockId> block_hierarchy;
|
||||
ConfigBlockId temp_block = block;
|
||||
|
||||
/* Generate a tree of parent block */
|
||||
while (true == bitstream_manager.valid_block_id(temp_block)) {
|
||||
block_hierarchy.push_back(temp_block);
|
||||
/* Go to upper level */
|
||||
/* Go to upper level */
|
||||
temp_block = bitstream_manager.block_parent(temp_block);
|
||||
}
|
||||
|
||||
|
@ -40,10 +39,11 @@ std::vector<ConfigBlockId> find_bitstream_manager_block_hierarchy(const Bitstrea
|
|||
}
|
||||
|
||||
/********************************************************************
|
||||
* Find all the top-level blocks in a bitstream manager,
|
||||
* Find all the top-level blocks in a bitstream manager,
|
||||
* which have no parents
|
||||
*******************************************************************/
|
||||
std::vector<ConfigBlockId> find_bitstream_manager_top_blocks(const BitstreamManager& bitstream_manager) {
|
||||
std::vector<ConfigBlockId> find_bitstream_manager_top_blocks(
|
||||
const BitstreamManager& bitstream_manager) {
|
||||
std::vector<ConfigBlockId> top_blocks;
|
||||
for (const ConfigBlockId& blk : bitstream_manager.blocks()) {
|
||||
if (ConfigBlockId::INVALID() != bitstream_manager.block_parent(blk)) {
|
||||
|
@ -56,12 +56,14 @@ std::vector<ConfigBlockId> find_bitstream_manager_top_blocks(const BitstreamMana
|
|||
}
|
||||
|
||||
/********************************************************************
|
||||
* Find the index of a configuration bit in the children bits of its parent block
|
||||
* Find the index of a configuration bit in the children bits of its parent
|
||||
*block
|
||||
*******************************************************************/
|
||||
size_t find_bitstream_manager_config_bit_index_in_parent_block(const BitstreamManager& bitstream_manager,
|
||||
const ConfigBitId& bit_id) {
|
||||
size_t find_bitstream_manager_config_bit_index_in_parent_block(
|
||||
const BitstreamManager& bitstream_manager, const ConfigBitId& bit_id) {
|
||||
size_t curr_index = 0;
|
||||
for (const ConfigBitId& cand_bit : bitstream_manager.block_bits(bitstream_manager.bit_parent_block(bit_id))) {
|
||||
for (const ConfigBitId& cand_bit : bitstream_manager.block_bits(
|
||||
bitstream_manager.bit_parent_block(bit_id))) {
|
||||
if (cand_bit == bit_id) {
|
||||
break;
|
||||
}
|
||||
|
@ -77,9 +79,10 @@ size_t find_bitstream_manager_config_bit_index_in_parent_block(const BitstreamMa
|
|||
* this function will recursively visit all the child blocks
|
||||
* until reaching a leaf block, where we collect the number of bits
|
||||
*******************************************************************/
|
||||
size_t rec_find_bitstream_manager_block_sum_of_bits(const BitstreamManager& bitstream_manager,
|
||||
const ConfigBlockId& block) {
|
||||
/* For leaf block, return directly with the number of bits, because it has not child block */
|
||||
size_t rec_find_bitstream_manager_block_sum_of_bits(
|
||||
const BitstreamManager& bitstream_manager, const ConfigBlockId& block) {
|
||||
/* For leaf block, return directly with the number of bits, because it has not
|
||||
* child block */
|
||||
if (0 < bitstream_manager.block_bits(block).size()) {
|
||||
VTR_ASSERT_SAFE(bitstream_manager.block_children(block).empty());
|
||||
return bitstream_manager.block_bits(block).size();
|
||||
|
@ -87,8 +90,10 @@ size_t rec_find_bitstream_manager_block_sum_of_bits(const BitstreamManager& bits
|
|||
|
||||
size_t sum_of_bits = 0;
|
||||
/* Dive to child blocks if this block has any */
|
||||
for (const ConfigBlockId& child_block : bitstream_manager.block_children(block)) {
|
||||
sum_of_bits += rec_find_bitstream_manager_block_sum_of_bits(bitstream_manager, child_block);
|
||||
for (const ConfigBlockId& child_block :
|
||||
bitstream_manager.block_children(block)) {
|
||||
sum_of_bits += rec_find_bitstream_manager_block_sum_of_bits(
|
||||
bitstream_manager, child_block);
|
||||
}
|
||||
|
||||
return sum_of_bits;
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* Include header files that are required by function declaration
|
||||
*******************************************************************/
|
||||
#include <vector>
|
||||
|
||||
#include "bitstream_manager.h"
|
||||
|
||||
/********************************************************************
|
||||
|
@ -14,16 +15,17 @@
|
|||
/* begin namespace openfpga */
|
||||
namespace openfpga {
|
||||
|
||||
std::vector<ConfigBlockId> find_bitstream_manager_block_hierarchy(const BitstreamManager& bitstream_manager,
|
||||
const ConfigBlockId& block);
|
||||
std::vector<ConfigBlockId> find_bitstream_manager_block_hierarchy(
|
||||
const BitstreamManager& bitstream_manager, const ConfigBlockId& block);
|
||||
|
||||
std::vector<ConfigBlockId> find_bitstream_manager_top_blocks(const BitstreamManager& bitstream_manager);
|
||||
std::vector<ConfigBlockId> find_bitstream_manager_top_blocks(
|
||||
const BitstreamManager& bitstream_manager);
|
||||
|
||||
size_t find_bitstream_manager_config_bit_index_in_parent_block(const BitstreamManager& bitstream_manager,
|
||||
const ConfigBitId& bit_id);
|
||||
size_t find_bitstream_manager_config_bit_index_in_parent_block(
|
||||
const BitstreamManager& bitstream_manager, const ConfigBitId& bit_id);
|
||||
|
||||
size_t rec_find_bitstream_manager_block_sum_of_bits(const BitstreamManager& bitstream_manager,
|
||||
const ConfigBlockId& block);
|
||||
size_t rec_find_bitstream_manager_block_sum_of_bits(
|
||||
const BitstreamManager& bitstream_manager, const ConfigBlockId& block);
|
||||
|
||||
} /* end namespace openfpga */
|
||||
|
||||
|
|
|
@ -15,11 +15,9 @@
|
|||
|
||||
/* Headers from libarchfpga */
|
||||
#include "arch_error.h"
|
||||
#include "read_xml_util.h"
|
||||
|
||||
#include "openfpga_reserved_words.h"
|
||||
|
||||
#include "read_xml_arch_bitstream.h"
|
||||
#include "read_xml_util.h"
|
||||
|
||||
/* begin namespace openfpga */
|
||||
namespace openfpga {
|
||||
|
@ -28,14 +26,13 @@ namespace openfpga {
|
|||
* Parse XML codes of a <bitstream_block> to an object of BitstreamManager
|
||||
* This function goes recursively until we reach the leaf node
|
||||
*******************************************************************/
|
||||
static
|
||||
void rec_read_xml_bitstream_block(pugi::xml_node& xml_bitstream_block,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
BitstreamManager& bitstream_manager,
|
||||
const ConfigBlockId& parent_block) {
|
||||
|
||||
static void rec_read_xml_bitstream_block(pugi::xml_node& xml_bitstream_block,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
BitstreamManager& bitstream_manager,
|
||||
const ConfigBlockId& parent_block) {
|
||||
/* Find the name of this bitstream block */
|
||||
const std::string& block_name = get_attribute(xml_bitstream_block, "name", loc_data).as_string();
|
||||
const std::string& block_name =
|
||||
get_attribute(xml_bitstream_block, "name", loc_data).as_string();
|
||||
|
||||
/* Create the bitstream block */
|
||||
ConfigBlockId curr_block = bitstream_manager.add_block(block_name);
|
||||
|
@ -44,10 +41,12 @@ void rec_read_xml_bitstream_block(pugi::xml_node& xml_bitstream_block,
|
|||
bitstream_manager.add_child_block(parent_block, curr_block);
|
||||
|
||||
/* Parse input nets if defined */
|
||||
pugi::xml_node xml_input_nets = get_single_child(xml_bitstream_block, "input_nets", loc_data, pugiutil::ReqOpt::OPTIONAL);
|
||||
pugi::xml_node xml_input_nets = get_single_child(
|
||||
xml_bitstream_block, "input_nets", loc_data, pugiutil::ReqOpt::OPTIONAL);
|
||||
if (xml_input_nets) {
|
||||
std::vector<std::string> input_nets;
|
||||
size_t num_input_nets = count_children(xml_input_nets, "path", loc_data, pugiutil::ReqOpt::OPTIONAL);
|
||||
size_t num_input_nets = count_children(xml_input_nets, "path", loc_data,
|
||||
pugiutil::ReqOpt::OPTIONAL);
|
||||
input_nets.resize(num_input_nets);
|
||||
|
||||
/* Find the child paths/nets */
|
||||
|
@ -57,10 +56,11 @@ void rec_read_xml_bitstream_block(pugi::xml_node& xml_bitstream_block,
|
|||
bad_tag(xml_input_net, loc_data, xml_input_nets, {"path"});
|
||||
}
|
||||
const int& id = get_attribute(xml_input_net, "id", loc_data).as_int();
|
||||
const std::string& net_name = get_attribute(xml_input_net, "net_name", loc_data).as_string();
|
||||
const std::string& net_name =
|
||||
get_attribute(xml_input_net, "net_name", loc_data).as_string();
|
||||
VTR_ASSERT((size_t)id < input_nets.size());
|
||||
input_nets[id] = net_name;
|
||||
}
|
||||
input_nets[id] = net_name;
|
||||
}
|
||||
|
||||
std::string input_nets_str;
|
||||
bool need_splitter = false;
|
||||
|
@ -71,14 +71,16 @@ void rec_read_xml_bitstream_block(pugi::xml_node& xml_bitstream_block,
|
|||
input_nets_str += input_net;
|
||||
need_splitter = true;
|
||||
}
|
||||
bitstream_manager.add_input_net_id_to_block(curr_block, input_nets_str);
|
||||
bitstream_manager.add_input_net_id_to_block(curr_block, input_nets_str);
|
||||
}
|
||||
|
||||
/* Parse output nets if defined */
|
||||
pugi::xml_node xml_output_nets = get_single_child(xml_bitstream_block, "output_nets", loc_data, pugiutil::ReqOpt::OPTIONAL);
|
||||
pugi::xml_node xml_output_nets = get_single_child(
|
||||
xml_bitstream_block, "output_nets", loc_data, pugiutil::ReqOpt::OPTIONAL);
|
||||
if (xml_output_nets) {
|
||||
std::vector<std::string> output_nets;
|
||||
size_t num_output_nets = count_children(xml_output_nets, "path", loc_data, pugiutil::ReqOpt::OPTIONAL);
|
||||
size_t num_output_nets = count_children(xml_output_nets, "path", loc_data,
|
||||
pugiutil::ReqOpt::OPTIONAL);
|
||||
output_nets.resize(num_output_nets);
|
||||
|
||||
/* Find the child paths/nets */
|
||||
|
@ -88,10 +90,11 @@ void rec_read_xml_bitstream_block(pugi::xml_node& xml_bitstream_block,
|
|||
bad_tag(xml_output_net, loc_data, xml_output_nets, {"path"});
|
||||
}
|
||||
const int& id = get_attribute(xml_output_net, "id", loc_data).as_int();
|
||||
const std::string& net_name = get_attribute(xml_output_net, "net_name", loc_data).as_string();
|
||||
const std::string& net_name =
|
||||
get_attribute(xml_output_net, "net_name", loc_data).as_string();
|
||||
VTR_ASSERT((size_t)id < output_nets.size());
|
||||
output_nets[id] = net_name;
|
||||
}
|
||||
output_nets[id] = net_name;
|
||||
}
|
||||
|
||||
std::string output_nets_str;
|
||||
bool need_splitter = false;
|
||||
|
@ -102,16 +105,20 @@ void rec_read_xml_bitstream_block(pugi::xml_node& xml_bitstream_block,
|
|||
output_nets_str += output_net;
|
||||
need_splitter = true;
|
||||
}
|
||||
bitstream_manager.add_output_net_id_to_block(curr_block, output_nets_str);
|
||||
bitstream_manager.add_output_net_id_to_block(curr_block, output_nets_str);
|
||||
}
|
||||
|
||||
/* Parse configuration bits */
|
||||
pugi::xml_node xml_bitstream = get_single_child(xml_bitstream_block, "bitstream", loc_data, pugiutil::ReqOpt::OPTIONAL);
|
||||
pugi::xml_node xml_bitstream = get_single_child(
|
||||
xml_bitstream_block, "bitstream", loc_data, pugiutil::ReqOpt::OPTIONAL);
|
||||
if (xml_bitstream) {
|
||||
/* Parse path_id: -2 is an invalid value defined in the bitstream manager internally */
|
||||
const int& path_id = get_attribute(xml_bitstream, "path_id", loc_data, pugiutil::ReqOpt::OPTIONAL).as_int(-2);
|
||||
/* Parse path_id: -2 is an invalid value defined in the bitstream manager
|
||||
* internally */
|
||||
const int& path_id = get_attribute(xml_bitstream, "path_id", loc_data,
|
||||
pugiutil::ReqOpt::OPTIONAL)
|
||||
.as_int(-2);
|
||||
if (-2 < path_id) {
|
||||
bitstream_manager.add_path_id_to_block(curr_block, path_id);
|
||||
bitstream_manager.add_path_id_to_block(curr_block, path_id);
|
||||
}
|
||||
|
||||
/* Find the child paths/nets */
|
||||
|
@ -127,21 +134,21 @@ void rec_read_xml_bitstream_block(pugi::xml_node& xml_bitstream_block,
|
|||
/* Link the bit to parent block */
|
||||
bitstream_manager.add_block_bits(curr_block, block_bits);
|
||||
}
|
||||
|
||||
|
||||
/* Go recursively: find all the child blocks and parse */
|
||||
for (pugi::xml_node xml_child : xml_bitstream_block.children()) {
|
||||
/* We only care child bitstream blocks here */
|
||||
if (xml_child.name() == std::string("bitstream_block")) {
|
||||
rec_read_xml_bitstream_block(xml_child, loc_data, bitstream_manager, curr_block);
|
||||
rec_read_xml_bitstream_block(xml_child, loc_data, bitstream_manager,
|
||||
curr_block);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Parse XML codes about <bitstream> to an object of Bitstream
|
||||
*******************************************************************/
|
||||
BitstreamManager read_xml_architecture_bitstream(const char* fname) {
|
||||
|
||||
vtr::ScopedStartFinishTimer timer("Read Architecture Bitstream file");
|
||||
|
||||
BitstreamManager bitstream_manager;
|
||||
|
@ -155,11 +162,13 @@ BitstreamManager read_xml_architecture_bitstream(const char* fname) {
|
|||
|
||||
/* Count the child <bitstream_block> */
|
||||
|
||||
pugi::xml_node xml_root = get_single_child(doc, "bitstream_block", loc_data);
|
||||
pugi::xml_node xml_root =
|
||||
get_single_child(doc, "bitstream_block", loc_data);
|
||||
|
||||
/* Find the name of the top block*/
|
||||
const std::string& top_block_name = get_attribute(xml_root, "name", loc_data).as_string();
|
||||
|
||||
const std::string& top_block_name =
|
||||
get_attribute(xml_root, "name", loc_data).as_string();
|
||||
|
||||
if (top_block_name != std::string(FPGA_TOP_MODULE_NAME)) {
|
||||
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_root),
|
||||
"Top-level block must be named as '%s'!\n",
|
||||
|
@ -169,7 +178,8 @@ BitstreamManager read_xml_architecture_bitstream(const char* fname) {
|
|||
/* Create the top-level block */
|
||||
ConfigBlockId top_block = bitstream_manager.add_block(top_block_name);
|
||||
|
||||
size_t num_blks = count_children(xml_root, "bitstream_block", loc_data, pugiutil::ReqOpt::OPTIONAL);
|
||||
size_t num_blks = count_children(xml_root, "bitstream_block", loc_data,
|
||||
pugiutil::ReqOpt::OPTIONAL);
|
||||
|
||||
/* Reserve bitstream blocks in the data base */
|
||||
bitstream_manager.reserve_blocks(num_blks);
|
||||
|
@ -182,15 +192,14 @@ BitstreamManager read_xml_architecture_bitstream(const char* fname) {
|
|||
if (xml_blk.name() != std::string("bitstream_block")) {
|
||||
bad_tag(xml_blk, loc_data, xml_root, {"bitstream_block"});
|
||||
}
|
||||
rec_read_xml_bitstream_block(xml_blk, loc_data, bitstream_manager, top_block);
|
||||
}
|
||||
rec_read_xml_bitstream_block(xml_blk, loc_data, bitstream_manager,
|
||||
top_block);
|
||||
}
|
||||
} catch (pugiutil::XmlError& e) {
|
||||
archfpga_throw(fname, e.line(),
|
||||
"%s", e.what());
|
||||
archfpga_throw(fname, e.line(), "%s", e.what());
|
||||
}
|
||||
|
||||
return bitstream_manager;
|
||||
return bitstream_manager;
|
||||
}
|
||||
|
||||
} /* end namespace openfpga */
|
||||
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
/********************************************************************
|
||||
* Include header files that are required by function declaration
|
||||
*******************************************************************/
|
||||
#include "pugixml_util.hpp"
|
||||
#include "pugixml.hpp"
|
||||
#include "bitstream_manager.h"
|
||||
#include "pugixml.hpp"
|
||||
#include "pugixml_util.hpp"
|
||||
|
||||
/********************************************************************
|
||||
* Function declaration
|
||||
|
|
|
@ -11,13 +11,11 @@
|
|||
#include "vtr_time.h"
|
||||
|
||||
/* Headers from openfpgautil library */
|
||||
#include "bitstream_manager_utils.h"
|
||||
#include "openfpga_digest.h"
|
||||
#include "openfpga_reserved_words.h"
|
||||
#include "openfpga_tokenizer.h"
|
||||
#include "openfpga_version.h"
|
||||
|
||||
#include "openfpga_reserved_words.h"
|
||||
|
||||
#include "bitstream_manager_utils.h"
|
||||
#include "report_arch_bitstream_distribution.h"
|
||||
|
||||
/* begin namespace openfpga */
|
||||
|
@ -26,17 +24,15 @@ namespace openfpga {
|
|||
/********************************************************************
|
||||
* Recursively report the bitstream distribution of a block to a file
|
||||
* This function will use a Depth-First Search in outputting bitstream
|
||||
* for each block
|
||||
* for each block
|
||||
* For block with child blocks, we visit each child recursively
|
||||
* The reporting can be stopped at a given maximum hierarchy level
|
||||
* The reporting can be stopped at a given maximum hierarchy level
|
||||
* which is used to limit the length of the report
|
||||
*******************************************************************/
|
||||
static
|
||||
void rec_report_block_bitstream_distribution_to_xml_file(std::fstream& fp,
|
||||
const BitstreamManager& bitstream_manager,
|
||||
const ConfigBlockId& block,
|
||||
const size_t& max_hierarchy_level,
|
||||
const size_t& hierarchy_level) {
|
||||
static void rec_report_block_bitstream_distribution_to_xml_file(
|
||||
std::fstream& fp, const BitstreamManager& bitstream_manager,
|
||||
const ConfigBlockId& block, const size_t& max_hierarchy_level,
|
||||
const size_t& hierarchy_level) {
|
||||
valid_file_stream(fp);
|
||||
|
||||
if (hierarchy_level > max_hierarchy_level) {
|
||||
|
@ -46,33 +42,37 @@ void rec_report_block_bitstream_distribution_to_xml_file(std::fstream& fp,
|
|||
/* Write the bitstream distribution of this block */
|
||||
write_tab_to_file(fp, hierarchy_level);
|
||||
fp << "<block";
|
||||
fp << " name=\"" << bitstream_manager.block_name(block)<< "\"";
|
||||
fp << " number_of_bits=\"" << rec_find_bitstream_manager_block_sum_of_bits(bitstream_manager, block) << "\"";
|
||||
fp << " name=\"" << bitstream_manager.block_name(block) << "\"";
|
||||
fp << " number_of_bits=\""
|
||||
<< rec_find_bitstream_manager_block_sum_of_bits(bitstream_manager, block)
|
||||
<< "\"";
|
||||
fp << ">" << std::endl;
|
||||
|
||||
/* Dive to child blocks if this block has any */
|
||||
for (const ConfigBlockId& child_block : bitstream_manager.block_children(block)) {
|
||||
rec_report_block_bitstream_distribution_to_xml_file(fp, bitstream_manager, child_block,
|
||||
max_hierarchy_level, hierarchy_level + 1);
|
||||
for (const ConfigBlockId& child_block :
|
||||
bitstream_manager.block_children(block)) {
|
||||
rec_report_block_bitstream_distribution_to_xml_file(
|
||||
fp, bitstream_manager, child_block, max_hierarchy_level,
|
||||
hierarchy_level + 1);
|
||||
}
|
||||
|
||||
write_tab_to_file(fp, hierarchy_level);
|
||||
fp << "</block>" <<std::endl;
|
||||
fp << "</block>" << std::endl;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Report the distribution of bitstream by blocks, e.g., the number of
|
||||
* configuration bits per SB/CB/CLB
|
||||
* This function can generate a report to a file
|
||||
* This function can generate a report to a file
|
||||
*
|
||||
* Notes:
|
||||
* Notes:
|
||||
* - The output format is a table whose format is compatible with RST files
|
||||
*******************************************************************/
|
||||
int report_architecture_bitstream_distribution(std::fstream& fp,
|
||||
const BitstreamManager& bitstream_manager,
|
||||
const size_t& max_hierarchy_level,
|
||||
const size_t& hierarchy_level) {
|
||||
std::string timer_message = std::string("Report architecture bitstream distribution");
|
||||
int report_architecture_bitstream_distribution(
|
||||
std::fstream& fp, const BitstreamManager& bitstream_manager,
|
||||
const size_t& max_hierarchy_level, const size_t& hierarchy_level) {
|
||||
std::string timer_message =
|
||||
std::string("Report architecture bitstream distribution");
|
||||
vtr::ScopedStartFinishTimer timer(timer_message);
|
||||
|
||||
/* Check the file stream */
|
||||
|
@ -80,18 +80,21 @@ int report_architecture_bitstream_distribution(std::fstream& fp,
|
|||
|
||||
int curr_level = hierarchy_level;
|
||||
write_tab_to_file(fp, curr_level);
|
||||
fp << "<blocks>" <<std::endl;
|
||||
fp << "<blocks>" << std::endl;
|
||||
|
||||
/* Find the top block, which has not parents */
|
||||
std::vector<ConfigBlockId> top_block = find_bitstream_manager_top_blocks(bitstream_manager);
|
||||
std::vector<ConfigBlockId> top_block =
|
||||
find_bitstream_manager_top_blocks(bitstream_manager);
|
||||
/* Make sure we have only 1 top block */
|
||||
VTR_ASSERT(1 == top_block.size());
|
||||
|
||||
/* Write bitstream, block by block, in a recursive way */
|
||||
rec_report_block_bitstream_distribution_to_xml_file(fp, bitstream_manager, top_block[0], max_hierarchy_level + 2, curr_level + 1);
|
||||
rec_report_block_bitstream_distribution_to_xml_file(
|
||||
fp, bitstream_manager, top_block[0], max_hierarchy_level + 2,
|
||||
curr_level + 1);
|
||||
|
||||
write_tab_to_file(fp, curr_level);
|
||||
fp << "</blocks>" <<std::endl;
|
||||
fp << "</blocks>" << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* Include header files that are required by function declaration
|
||||
*******************************************************************/
|
||||
#include <string>
|
||||
|
||||
#include "bitstream_manager.h"
|
||||
|
||||
/********************************************************************
|
||||
|
@ -14,10 +15,9 @@
|
|||
/* begin namespace openfpga */
|
||||
namespace openfpga {
|
||||
|
||||
int report_architecture_bitstream_distribution(std::fstream& fp,
|
||||
const BitstreamManager& bitstream_manager,
|
||||
const size_t& max_hierarchy_level,
|
||||
const size_t& hierarchy_level);
|
||||
int report_architecture_bitstream_distribution(
|
||||
std::fstream& fp, const BitstreamManager& bitstream_manager,
|
||||
const size_t& max_hierarchy_level, const size_t& hierarchy_level);
|
||||
|
||||
} /* end namespace openfpga */
|
||||
|
||||
|
|
|
@ -12,12 +12,10 @@
|
|||
#include "vtr_time.h"
|
||||
|
||||
/* Headers from openfpgautil library */
|
||||
#include "openfpga_digest.h"
|
||||
#include "openfpga_tokenizer.h"
|
||||
|
||||
#include "openfpga_reserved_words.h"
|
||||
|
||||
#include "bitstream_manager_utils.h"
|
||||
#include "openfpga_digest.h"
|
||||
#include "openfpga_reserved_words.h"
|
||||
#include "openfpga_tokenizer.h"
|
||||
#include "write_xml_arch_bitstream.h"
|
||||
|
||||
/* begin namespace openfpga */
|
||||
|
@ -26,20 +24,19 @@ namespace openfpga {
|
|||
/********************************************************************
|
||||
* This function write header information to a bitstream file
|
||||
*******************************************************************/
|
||||
static
|
||||
void write_bitstream_xml_file_head(std::fstream& fp,
|
||||
const bool& include_time_stamp) {
|
||||
static void write_bitstream_xml_file_head(std::fstream& fp,
|
||||
const bool& include_time_stamp) {
|
||||
valid_file_stream(fp);
|
||||
|
||||
|
||||
fp << "<!--" << std::endl;
|
||||
fp << "\t- Architecture independent bitstream" << std::endl;
|
||||
fp << "\t- Author: Xifan TANG" << std::endl;
|
||||
fp << "\t- Organization: University of Utah" << std::endl;
|
||||
|
||||
if (include_time_stamp) {
|
||||
auto end = std::chrono::system_clock::now();
|
||||
auto end = std::chrono::system_clock::now();
|
||||
std::time_t end_time = std::chrono::system_clock::to_time_t(end);
|
||||
fp << "\t- Date: " << std::ctime(&end_time) ;
|
||||
fp << "\t- Date: " << std::ctime(&end_time);
|
||||
}
|
||||
|
||||
fp << "-->" << std::endl;
|
||||
|
@ -49,38 +46,39 @@ void write_bitstream_xml_file_head(std::fstream& fp,
|
|||
/********************************************************************
|
||||
* Recursively write the bitstream of a block to a xml file
|
||||
* This function will use a Depth-First Search in outputting bitstream
|
||||
* for each block
|
||||
* for each block
|
||||
* 1. For block with bits as children, we will output the XML lines
|
||||
* 2. For block without bits/child blocks, we can return
|
||||
* 2. For block without bits/child blocks, we can return
|
||||
* 3. For block with child blocks, we visit each child recursively
|
||||
*******************************************************************/
|
||||
static
|
||||
void rec_write_block_bitstream_to_xml_file(std::fstream& fp,
|
||||
const BitstreamManager& bitstream_manager,
|
||||
const ConfigBlockId& block,
|
||||
const size_t& hierarchy_level) {
|
||||
static void rec_write_block_bitstream_to_xml_file(
|
||||
std::fstream& fp, const BitstreamManager& bitstream_manager,
|
||||
const ConfigBlockId& block, const size_t& hierarchy_level) {
|
||||
valid_file_stream(fp);
|
||||
|
||||
/* Write the bits of this block */
|
||||
write_tab_to_file(fp, hierarchy_level);
|
||||
fp << "<bitstream_block";
|
||||
fp << " name=\"" << bitstream_manager.block_name(block)<< "\"";
|
||||
fp << " name=\"" << bitstream_manager.block_name(block) << "\"";
|
||||
fp << " hierarchy_level=\"" << hierarchy_level << "\"";
|
||||
fp << ">" << std::endl;
|
||||
|
||||
/* Dive to child blocks if this block has any */
|
||||
for (const ConfigBlockId& child_block : bitstream_manager.block_children(block)) {
|
||||
rec_write_block_bitstream_to_xml_file(fp, bitstream_manager, child_block, hierarchy_level + 1);
|
||||
for (const ConfigBlockId& child_block :
|
||||
bitstream_manager.block_children(block)) {
|
||||
rec_write_block_bitstream_to_xml_file(fp, bitstream_manager, child_block,
|
||||
hierarchy_level + 1);
|
||||
}
|
||||
|
||||
|
||||
if (0 == bitstream_manager.block_bits(block).size()) {
|
||||
write_tab_to_file(fp, hierarchy_level);
|
||||
fp << "</bitstream_block>" <<std::endl;
|
||||
fp << "</bitstream_block>" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<ConfigBlockId> block_hierarchy = find_bitstream_manager_block_hierarchy(bitstream_manager, block);
|
||||
|
||||
std::vector<ConfigBlockId> block_hierarchy =
|
||||
find_bitstream_manager_block_hierarchy(bitstream_manager, block);
|
||||
|
||||
/* Output hierarchy of this parent*/
|
||||
write_tab_to_file(fp, hierarchy_level + 1);
|
||||
fp << "<hierarchy>" << std::endl;
|
||||
|
@ -101,7 +99,8 @@ void rec_write_block_bitstream_to_xml_file(std::fstream& fp,
|
|||
fp << "<input_nets>\n";
|
||||
size_t path_counter = 0;
|
||||
/* Split with space */
|
||||
StringToken input_net_tokenizer(bitstream_manager.block_input_net_ids(block));
|
||||
StringToken input_net_tokenizer(
|
||||
bitstream_manager.block_input_net_ids(block));
|
||||
for (const std::string& net : input_net_tokenizer.split(std::string(" "))) {
|
||||
write_tab_to_file(fp, hierarchy_level + 2);
|
||||
fp << "<path id=\"" << path_counter << "\"";
|
||||
|
@ -121,8 +120,10 @@ void rec_write_block_bitstream_to_xml_file(std::fstream& fp,
|
|||
fp << "<output_nets>\n";
|
||||
size_t path_counter = 0;
|
||||
/* Split with space */
|
||||
StringToken output_net_tokenizer(bitstream_manager.block_output_net_ids(block));
|
||||
for (const std::string& net : output_net_tokenizer.split(std::string(" "))) {
|
||||
StringToken output_net_tokenizer(
|
||||
bitstream_manager.block_output_net_ids(block));
|
||||
for (const std::string& net :
|
||||
output_net_tokenizer.split(std::string(" "))) {
|
||||
write_tab_to_file(fp, hierarchy_level + 2);
|
||||
fp << "<path id=\"" << path_counter << "\"";
|
||||
fp << " net_name=\"";
|
||||
|
@ -149,7 +150,9 @@ void rec_write_block_bitstream_to_xml_file(std::fstream& fp,
|
|||
for (const ConfigBitId& child_bit : bitstream_manager.block_bits(block)) {
|
||||
write_tab_to_file(fp, hierarchy_level + 2);
|
||||
fp << "<bit";
|
||||
fp << " memory_port=\"" << CONFIGURABLE_MEMORY_DATA_OUT_NAME << "[" << bit_counter << "]" << "\"";
|
||||
fp << " memory_port=\"" << CONFIGURABLE_MEMORY_DATA_OUT_NAME << "["
|
||||
<< bit_counter << "]"
|
||||
<< "\"";
|
||||
fp << " value=\"" << bitstream_manager.bit_value(child_bit) << "\"";
|
||||
fp << "/>" << std::endl;
|
||||
bit_counter++;
|
||||
|
@ -158,32 +161,37 @@ void rec_write_block_bitstream_to_xml_file(std::fstream& fp,
|
|||
fp << "</bitstream>" << std::endl;
|
||||
|
||||
write_tab_to_file(fp, hierarchy_level);
|
||||
fp << "</bitstream_block>" <<std::endl;
|
||||
fp << "</bitstream_block>" << std::endl;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Write the bitstream to a file without binding to the configuration
|
||||
* Write the bitstream to a file without binding to the configuration
|
||||
* procotols of a given FPGA fabric in XML format
|
||||
*
|
||||
* Notes:
|
||||
* Notes:
|
||||
* This is a very generic representation for bitstream that are implemented
|
||||
* by VPR engine. It shows the bitstream for each blocks in the FPGA
|
||||
* by VPR engine. It shows the bitstream for each blocks in the FPGA
|
||||
* architecture that users are modeling.
|
||||
* This function can be used to:
|
||||
* This function can be used to:
|
||||
* 1. Debug the bitstream decoding to see if there is any bug
|
||||
* 2. Create an intermediate file to reorganize a bitstream for
|
||||
* 2. Create an intermediate file to reorganize a bitstream for
|
||||
* specific FPGAs
|
||||
* 3. TODO: support FASM format
|
||||
* 3. TODO: support FASM format
|
||||
*******************************************************************/
|
||||
void write_xml_architecture_bitstream(const BitstreamManager& bitstream_manager,
|
||||
const std::string& fname,
|
||||
const bool& include_time_stamp) {
|
||||
/* Ensure that we have a valid file name */
|
||||
if (true == fname.empty()) {
|
||||
VTR_LOG_ERROR("Received empty file name to output bitstream!\n\tPlease specify a valid file name.\n");
|
||||
VTR_LOG_ERROR(
|
||||
"Received empty file name to output bitstream!\n\tPlease specify a valid "
|
||||
"file name.\n");
|
||||
}
|
||||
|
||||
std::string timer_message = std::string("Write ") + std::to_string(bitstream_manager.bits().size()) + std::string(" architecture independent bitstream into XML file '") + fname + std::string("'");
|
||||
std::string timer_message =
|
||||
std::string("Write ") + std::to_string(bitstream_manager.bits().size()) +
|
||||
std::string(" architecture independent bitstream into XML file '") + fname +
|
||||
std::string("'");
|
||||
vtr::ScopedStartFinishTimer timer(timer_message);
|
||||
|
||||
/* Create the file stream */
|
||||
|
@ -196,7 +204,8 @@ void write_xml_architecture_bitstream(const BitstreamManager& bitstream_manager,
|
|||
write_bitstream_xml_file_head(fp, include_time_stamp);
|
||||
|
||||
/* Find the top block, which has not parents */
|
||||
std::vector<ConfigBlockId> top_block = find_bitstream_manager_top_blocks(bitstream_manager);
|
||||
std::vector<ConfigBlockId> top_block =
|
||||
find_bitstream_manager_top_blocks(bitstream_manager);
|
||||
/* Make sure we have only 1 top block */
|
||||
VTR_ASSERT(1 == top_block.size());
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* Include header files that are required by function declaration
|
||||
*******************************************************************/
|
||||
#include <string>
|
||||
|
||||
#include "bitstream_manager.h"
|
||||
|
||||
/********************************************************************
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/********************************************************************
|
||||
* Unit test functions to validate the correctness of
|
||||
* Unit test functions to validate the correctness of
|
||||
* 1. parser of data structures
|
||||
* 2. writer of data structures
|
||||
*******************************************************************/
|
||||
|
@ -10,22 +10,22 @@
|
|||
|
||||
/* Headers from fabric key */
|
||||
#include "read_xml_arch_bitstream.h"
|
||||
#include "write_xml_arch_bitstream.h"
|
||||
#include "report_arch_bitstream_distribution.h"
|
||||
#include "write_xml_arch_bitstream.h"
|
||||
|
||||
int main(int argc, const char** argv) {
|
||||
/* Ensure we have only one or two or 3 argument */
|
||||
VTR_ASSERT((2 == argc) || (3 == argc) || (4 == argc) || (5 == argc));
|
||||
|
||||
/* Parse the bitstream from an XML file */
|
||||
openfpga::BitstreamManager test_bitstream = openfpga::read_xml_architecture_bitstream(argv[1]);
|
||||
VTR_LOG("Read the bitstream from an XML file: %s.\n",
|
||||
argv[1]);
|
||||
openfpga::BitstreamManager test_bitstream =
|
||||
openfpga::read_xml_architecture_bitstream(argv[1]);
|
||||
VTR_LOG("Read the bitstream from an XML file: %s.\n", argv[1]);
|
||||
|
||||
/* Output the bitstream database to an XML file
|
||||
* This is optional only used when there is a second argument
|
||||
*/
|
||||
if (3 <= argc) {
|
||||
if (3 <= argc) {
|
||||
openfpga::write_xml_architecture_bitstream(test_bitstream, argv[2], true);
|
||||
VTR_LOG("Echo the bitstream (with time stamp) to an XML file: %s.\n",
|
||||
argv[2]);
|
||||
|
@ -36,16 +36,13 @@ int main(int argc, const char** argv) {
|
|||
/* Output the bitstream distribution to an XML file
|
||||
* This is optional only used when there is a third argument
|
||||
*/
|
||||
if (4 <= argc) {
|
||||
if (4 <= argc) {
|
||||
/* Create the file stream */
|
||||
std::fstream fp;
|
||||
fp.open(argv[3], std::fstream::out | std::fstream::trunc);
|
||||
|
||||
openfpga::report_architecture_bitstream_distribution(fp, test_bitstream, 1, 0);
|
||||
VTR_LOG("Echo the bitstream distribution to an XML file: %s.\n",
|
||||
argv[3]);
|
||||
openfpga::report_architecture_bitstream_distribution(fp, test_bitstream, 1,
|
||||
0);
|
||||
VTR_LOG("Echo the bitstream distribution to an XML file: %s.\n", argv[3]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,25 +1,22 @@
|
|||
/*********************************************************************
|
||||
* Member functions for class Command
|
||||
********************************************************************/
|
||||
#include "vtr_assert.h"
|
||||
#include "command.h"
|
||||
|
||||
#include "vtr_assert.h"
|
||||
|
||||
/* Begin namespace openfpga */
|
||||
namespace openfpga {
|
||||
|
||||
/*********************************************************************
|
||||
* Public constructors
|
||||
********************************************************************/
|
||||
Command::Command(const char* name) {
|
||||
name_ = std::string(name);
|
||||
}
|
||||
Command::Command(const char* name) { name_ = std::string(name); }
|
||||
|
||||
/************************************************************************
|
||||
* Public Accessors : aggregates
|
||||
***********************************************************************/
|
||||
std::string Command::name() const {
|
||||
return name_;
|
||||
}
|
||||
std::string Command::name() const { return name_; }
|
||||
|
||||
Command::command_option_range Command::options() const {
|
||||
return vtr::make_range(option_ids_.begin(), option_ids_.end());
|
||||
|
@ -47,7 +44,8 @@ std::vector<CommandOptionId> Command::require_value_options() const {
|
|||
|
||||
CommandOptionId Command::option(const std::string& name) const {
|
||||
/* Ensure that the name is unique in the option list */
|
||||
std::map<std::string, CommandOptionId>::const_iterator name_it = option_name2ids_.find(name);
|
||||
std::map<std::string, CommandOptionId>::const_iterator name_it =
|
||||
option_name2ids_.find(name);
|
||||
if (name_it == option_name2ids_.end()) {
|
||||
return CommandOptionId::INVALID();
|
||||
}
|
||||
|
@ -56,7 +54,8 @@ CommandOptionId Command::option(const std::string& name) const {
|
|||
|
||||
CommandOptionId Command::short_option(const std::string& name) const {
|
||||
/* Ensure that the name is unique in the option list */
|
||||
std::map<std::string, CommandOptionId>::const_iterator name_it = option_short_name2ids_.find(name);
|
||||
std::map<std::string, CommandOptionId>::const_iterator name_it =
|
||||
option_short_name2ids_.find(name);
|
||||
if (name_it == option_short_name2ids_.end()) {
|
||||
return CommandOptionId::INVALID();
|
||||
}
|
||||
|
@ -87,13 +86,15 @@ bool Command::option_require_value(const CommandOptionId& option_id) const {
|
|||
return NUM_OPT_VALUE_TYPES != option_require_value_types_[option_id];
|
||||
}
|
||||
|
||||
e_option_value_type Command::option_require_value_type(const CommandOptionId& option_id) const {
|
||||
e_option_value_type Command::option_require_value_type(
|
||||
const CommandOptionId& option_id) const {
|
||||
/* Validate the option id */
|
||||
VTR_ASSERT(true == valid_option_id(option_id));
|
||||
return option_require_value_types_[option_id];
|
||||
}
|
||||
|
||||
std::string Command::option_description(const CommandOptionId& option_id) const {
|
||||
std::string Command::option_description(
|
||||
const CommandOptionId& option_id) const {
|
||||
/* Validate the option id */
|
||||
VTR_ASSERT(true == valid_option_id(option_id));
|
||||
return option_description_[option_id];
|
||||
|
@ -105,10 +106,11 @@ std::string Command::option_description(const CommandOptionId& option_id) const
|
|||
|
||||
/* Add an option without required values */
|
||||
CommandOptionId Command::add_option(const char* name,
|
||||
const bool& option_required,
|
||||
const bool& option_required,
|
||||
const char* description) {
|
||||
/* Ensure that the name is unique in the option list */
|
||||
std::map<std::string, CommandOptionId>::const_iterator name_it = option_name2ids_.find(std::string(name));
|
||||
std::map<std::string, CommandOptionId>::const_iterator name_it =
|
||||
option_name2ids_.find(std::string(name));
|
||||
if (name_it != option_name2ids_.end()) {
|
||||
return CommandOptionId::INVALID();
|
||||
}
|
||||
|
@ -126,22 +128,23 @@ CommandOptionId Command::add_option(const char* name,
|
|||
option_name2ids_[std::string(name)] = option;
|
||||
|
||||
return option;
|
||||
}
|
||||
}
|
||||
|
||||
/* Add a short name to an option */
|
||||
bool Command::set_option_short_name(const CommandOptionId& option_id,
|
||||
bool Command::set_option_short_name(const CommandOptionId& option_id,
|
||||
const char* short_name) {
|
||||
/* Validate the option id */
|
||||
VTR_ASSERT(true == valid_option_id(option_id));
|
||||
|
||||
/* Short name is optional, so do the following only when it is not empty
|
||||
* Ensure that the short name is unique in the option list
|
||||
* Ensure that the short name is unique in the option list
|
||||
*/
|
||||
if (true == std::string(short_name).empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::map<std::string, CommandOptionId>::const_iterator short_name_it = option_short_name2ids_.find(std::string(short_name));
|
||||
std::map<std::string, CommandOptionId>::const_iterator short_name_it =
|
||||
option_short_name2ids_.find(std::string(short_name));
|
||||
if (short_name_it != option_short_name2ids_.end()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -152,10 +155,11 @@ bool Command::set_option_short_name(const CommandOptionId& option_id,
|
|||
option_short_name2ids_[std::string(short_name)] = option_id;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void Command::set_option_require_value(const CommandOptionId& option_id,
|
||||
const e_option_value_type& option_require_value_type) {
|
||||
void Command::set_option_require_value(
|
||||
const CommandOptionId& option_id,
|
||||
const e_option_value_type& option_require_value_type) {
|
||||
/* Validate the option id */
|
||||
VTR_ASSERT(true == valid_option_id(option_id));
|
||||
|
||||
|
@ -163,10 +167,11 @@ void Command::set_option_require_value(const CommandOptionId& option_id,
|
|||
}
|
||||
|
||||
/************************************************************************
|
||||
* Public invalidators/validators
|
||||
* Public invalidators/validators
|
||||
***********************************************************************/
|
||||
bool Command::valid_option_id(const CommandOptionId& option_id) const {
|
||||
return ( size_t(option_id) < option_ids_.size() ) && ( option_id == option_ids_[option_id] );
|
||||
return (size_t(option_id) < option_ids_.size()) &&
|
||||
(option_id == option_ids_[option_id]);
|
||||
}
|
||||
|
||||
} /* End namespace openfpga */
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* This is a cornerstone data structure of mini shell
|
||||
* which aims to store command-line options for parser
|
||||
*
|
||||
* This data structue is design to read-in the command line options
|
||||
* This data structue is design to read-in the command line options
|
||||
* which are organized as follows:
|
||||
*
|
||||
* <command_name> --<command_option_1> <command_option_1_value>
|
||||
|
@ -15,13 +15,13 @@
|
|||
* This is not only used by each command available in the shell
|
||||
* but also the interface of the shell, such as interactive mode
|
||||
********************************************************************/
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "vtr_vector.h"
|
||||
#include "vtr_range.h"
|
||||
#include "command_fwd.h"
|
||||
#include "vtr_range.h"
|
||||
#include "vtr_vector.h"
|
||||
|
||||
/* Begin namespace openfpga */
|
||||
namespace openfpga {
|
||||
|
@ -37,7 +37,7 @@ enum e_option_value_type {
|
|||
};
|
||||
|
||||
/*********************************************************************
|
||||
* Data structure to stores all the information related to a command
|
||||
* Data structure to stores all the information related to a command
|
||||
* to be defined in the mini shell
|
||||
* This data structure should NOT contain any parsing results!
|
||||
* It should be a read-only once created!
|
||||
|
@ -45,7 +45,7 @@ enum e_option_value_type {
|
|||
* An example of how to use
|
||||
* -----------------------
|
||||
* // Create a new command with a name of 'read_file'
|
||||
* // This command can be called as
|
||||
* // This command can be called as
|
||||
* // read_file --file <file_name>
|
||||
* // read_file -f <file_name>
|
||||
* // read_file --help
|
||||
|
@ -79,64 +79,73 @@ enum e_option_value_type {
|
|||
* When adding an option name, please do NOT add any dash at the beginning!!!
|
||||
********************************************************************/
|
||||
class Command {
|
||||
public: /* Types */
|
||||
typedef vtr::vector<CommandOptionId, CommandOptionId>::const_iterator command_option_iterator;
|
||||
/* Create range */
|
||||
typedef vtr::Range<command_option_iterator> command_option_range;
|
||||
public: /* Constructor */
|
||||
Command(const char* name);
|
||||
public: /* Public accessors */
|
||||
std::string name() const;
|
||||
command_option_range options() const;
|
||||
/* Find all the options that are mandatory */
|
||||
std::vector<CommandOptionId> required_options() const;
|
||||
/* Find all the options that require a value */
|
||||
std::vector<CommandOptionId> require_value_options() const;
|
||||
CommandOptionId option(const std::string& name) const;
|
||||
CommandOptionId short_option(const std::string& name) const;
|
||||
std::string option_name(const CommandOptionId& option_id) const;
|
||||
std::string option_short_name(const CommandOptionId& option_id) const;
|
||||
bool option_required(const CommandOptionId& option_id) const;
|
||||
bool option_require_value(const CommandOptionId& option_id) const;
|
||||
e_option_value_type option_require_value_type(const CommandOptionId& option_id) const;
|
||||
std::string option_description(const CommandOptionId& option_id) const;
|
||||
public: /* Public mutators */
|
||||
CommandOptionId add_option(const char* name,
|
||||
const bool& option_required,
|
||||
const char* description);
|
||||
bool set_option_short_name(const CommandOptionId& option_id, const char* short_name);
|
||||
void set_option_require_value(const CommandOptionId& option_id,
|
||||
const e_option_value_type& option_require_value_type);
|
||||
public: /* Public validators */
|
||||
bool valid_option_id(const CommandOptionId& option_id) const;
|
||||
private: /* Internal data */
|
||||
/* The name of the command */
|
||||
std::string name_;
|
||||
public: /* Types */
|
||||
typedef vtr::vector<CommandOptionId, CommandOptionId>::const_iterator
|
||||
command_option_iterator;
|
||||
/* Create range */
|
||||
typedef vtr::Range<command_option_iterator> command_option_range;
|
||||
|
||||
vtr::vector<CommandOptionId, CommandOptionId> option_ids_;
|
||||
public: /* Constructor */
|
||||
Command(const char* name);
|
||||
|
||||
/* Information about the options available in this command */
|
||||
/* Name of command line option to appear in the user interface
|
||||
* Regular names are typically with a prefix of double dash '--'
|
||||
* Short names are typically with a prefix of single dash '-'
|
||||
*/
|
||||
vtr::vector<CommandOptionId, std::string> option_names_;
|
||||
vtr::vector<CommandOptionId, std::string> option_short_names_;
|
||||
public: /* Public accessors */
|
||||
std::string name() const;
|
||||
command_option_range options() const;
|
||||
/* Find all the options that are mandatory */
|
||||
std::vector<CommandOptionId> required_options() const;
|
||||
/* Find all the options that require a value */
|
||||
std::vector<CommandOptionId> require_value_options() const;
|
||||
CommandOptionId option(const std::string& name) const;
|
||||
CommandOptionId short_option(const std::string& name) const;
|
||||
std::string option_name(const CommandOptionId& option_id) const;
|
||||
std::string option_short_name(const CommandOptionId& option_id) const;
|
||||
bool option_required(const CommandOptionId& option_id) const;
|
||||
bool option_require_value(const CommandOptionId& option_id) const;
|
||||
e_option_value_type option_require_value_type(
|
||||
const CommandOptionId& option_id) const;
|
||||
std::string option_description(const CommandOptionId& option_id) const;
|
||||
|
||||
/* If the option is manadatory when parsing */
|
||||
vtr::vector<CommandOptionId, bool> option_required_;
|
||||
public: /* Public mutators */
|
||||
CommandOptionId add_option(const char* name, const bool& option_required,
|
||||
const char* description);
|
||||
bool set_option_short_name(const CommandOptionId& option_id,
|
||||
const char* short_name);
|
||||
void set_option_require_value(
|
||||
const CommandOptionId& option_id,
|
||||
const e_option_value_type& option_require_value_type);
|
||||
|
||||
/* Data type of the option values to be converted
|
||||
* If the option does NOT require a value, this will be an invalid type
|
||||
*/
|
||||
vtr::vector<CommandOptionId, e_option_value_type> option_require_value_types_;
|
||||
public: /* Public validators */
|
||||
bool valid_option_id(const CommandOptionId& option_id) const;
|
||||
|
||||
/* Description of the option, this is going to be printed out in the help desk */
|
||||
vtr::vector<CommandOptionId, std::string> option_description_;
|
||||
private: /* Internal data */
|
||||
/* The name of the command */
|
||||
std::string name_;
|
||||
|
||||
/* Fast name look-up */
|
||||
std::map<std::string, CommandOptionId> option_name2ids_;
|
||||
std::map<std::string, CommandOptionId> option_short_name2ids_;
|
||||
vtr::vector<CommandOptionId, CommandOptionId> option_ids_;
|
||||
|
||||
/* Information about the options available in this command */
|
||||
/* Name of command line option to appear in the user interface
|
||||
* Regular names are typically with a prefix of double dash '--'
|
||||
* Short names are typically with a prefix of single dash '-'
|
||||
*/
|
||||
vtr::vector<CommandOptionId, std::string> option_names_;
|
||||
vtr::vector<CommandOptionId, std::string> option_short_names_;
|
||||
|
||||
/* If the option is manadatory when parsing */
|
||||
vtr::vector<CommandOptionId, bool> option_required_;
|
||||
|
||||
/* Data type of the option values to be converted
|
||||
* If the option does NOT require a value, this will be an invalid type
|
||||
*/
|
||||
vtr::vector<CommandOptionId, e_option_value_type> option_require_value_types_;
|
||||
|
||||
/* Description of the option, this is going to be printed out in the help desk
|
||||
*/
|
||||
vtr::vector<CommandOptionId, std::string> option_description_;
|
||||
|
||||
/* Fast name look-up */
|
||||
std::map<std::string, CommandOptionId> option_name2ids_;
|
||||
std::map<std::string, CommandOptionId> option_short_name2ids_;
|
||||
};
|
||||
|
||||
} /* End namespace openfpga */
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
/*********************************************************************
|
||||
* Member functions for class CommandContext
|
||||
* Member functions for class CommandContext
|
||||
********************************************************************/
|
||||
#include "vtr_assert.h"
|
||||
#include "command_context.h"
|
||||
|
||||
#include "vtr_assert.h"
|
||||
|
||||
/* Begin namespace openfpga */
|
||||
namespace openfpga {
|
||||
|
||||
|
@ -24,13 +25,14 @@ bool CommandContext::option_enable(const Command& command,
|
|||
return option_enabled_[option_id];
|
||||
}
|
||||
|
||||
std::string CommandContext::option_value(const Command& command,
|
||||
const CommandOptionId& option_id) const {
|
||||
std::string CommandContext::option_value(
|
||||
const Command& command, const CommandOptionId& option_id) const {
|
||||
VTR_ASSERT(true == command.valid_option_id(option_id));
|
||||
return option_values_[option_id];
|
||||
}
|
||||
|
||||
std::vector<CommandOptionId> CommandContext::check_required_options(const Command& command) const {
|
||||
std::vector<CommandOptionId> CommandContext::check_required_options(
|
||||
const Command& command) const {
|
||||
std::vector<CommandOptionId> fail_options;
|
||||
for (const CommandOptionId& option_id : command.required_options()) {
|
||||
if (false == option_enabled_[option_id]) {
|
||||
|
@ -40,7 +42,8 @@ std::vector<CommandOptionId> CommandContext::check_required_options(const Comman
|
|||
return fail_options;
|
||||
}
|
||||
|
||||
std::vector<CommandOptionId> CommandContext::check_required_option_values(const Command& command) const {
|
||||
std::vector<CommandOptionId> CommandContext::check_required_option_values(
|
||||
const Command& command) const {
|
||||
std::vector<CommandOptionId> fail_options;
|
||||
for (const CommandOptionId& option_id : command.require_value_options()) {
|
||||
if (true == option_values_[option_id].empty()) {
|
||||
|
@ -50,18 +53,19 @@ std::vector<CommandOptionId> CommandContext::check_required_option_values(const
|
|||
return fail_options;
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
* Public mutators
|
||||
********************************************************************/
|
||||
void CommandContext::set_option(const Command& command,
|
||||
const CommandOptionId& option_id, const bool& status) {
|
||||
const CommandOptionId& option_id,
|
||||
const bool& status) {
|
||||
VTR_ASSERT(true == command.valid_option_id(option_id));
|
||||
option_enabled_[option_id] = status;
|
||||
}
|
||||
|
||||
void CommandContext::set_option_value(const Command& command,
|
||||
const CommandOptionId& option_id, const std::string& value) {
|
||||
const CommandOptionId& option_id,
|
||||
const std::string& value) {
|
||||
VTR_ASSERT(true == command.valid_option_id(option_id));
|
||||
option_values_[option_id] = value;
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue