[engine] update source files subject to code formatting rules

This commit is contained in:
tangxifan 2022-10-06 17:08:50 -07:00
parent b8c59db9e9
commit 6d31b319a2
551 changed files with 45312 additions and 38408 deletions

View File

@ -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]);
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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();
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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 */

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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]);
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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";
}

View File

@ -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

View File

@ -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";
}

View File

@ -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

View File

@ -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";
}

View File

@ -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);

View File

@ -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 */

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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";
}

View File

@ -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);

View File

@ -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";
}

View File

@ -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

View File

@ -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";
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 << "\"";
}
/********************************************************************

View File

@ -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);

View File

@ -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]);
}
}

View File

@ -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]);

View File

@ -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]);

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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]);
}
}

View File

@ -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]);
}

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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();

View File

@ -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

View File

@ -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]);
}
}

View File

@ -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));
}

View File

@ -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 */

View File

@ -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

View File

@ -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;

View File

@ -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 */

View File

@ -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 */

View File

@ -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

View File

@ -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;
}

View File

@ -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 */

View File

@ -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());

View File

@ -5,6 +5,7 @@
* Include header files that are required by function declaration
*******************************************************************/
#include <string>
#include "bitstream_manager.h"
/********************************************************************

View File

@ -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]);
}
}

1110
libs/libini/src/ini.h Executable file → Normal file

File diff suppressed because it is too large Load Diff

View File

@ -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 */

View File

@ -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 */

View File

@ -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