add XML parser for simulation setting

This commit is contained in:
tangxifan 2020-01-18 15:40:20 -07:00
parent 2a902c7e55
commit bc3130d196
7 changed files with 302 additions and 13 deletions

View File

@ -277,13 +277,13 @@
</delay>
</measurement_setting>
<stimulus>
<port type="clock">
<clock>
<rise slew_time="20e-12" slew_type="abs"/>
<fall slew_time="20e-12" slew_type="abs"/>
</port>
<port type="input">
</clock>
<input>
<rise slew_time="25e-12" slew_type="abs"/>
<fall slew_time="25e-12" slew_type="abs"/>
</port>
</input>
</stimulus>
</openfpga_simulation_setting>

View File

@ -15,6 +15,7 @@
#include "read_xml_technology_library.h"
#include "read_xml_circuit_library.h"
#include "read_xml_simulation_setting.h"
#include "read_xml_openfpga_arch.h"
/********************************************************************
@ -58,6 +59,7 @@ openfpga::Arch read_xml_openfpga_arch(const char* arch_file_name) {
auto xml_simulation_settings = get_single_child(doc, "openfpga_simulation_setting", loc_data);
/* Parse simulation settings to data structure */
openfpga_arch.sim_setting = read_xml_simulation_setting(xml_simulation_settings, loc_data);
} catch (pugiutil::XmlError& e) {
archfpga_throw(arch_file_name, e.line(),

View File

@ -0,0 +1,271 @@
/********************************************************************
* This file includes the top-level function of this library
* which reads an XML modeling OpenFPGA architecture to the associated
* data structures
*******************************************************************/
#include <string>
/* Headers from pugi XML library */
#include "pugixml.hpp"
#include "pugixml_util.hpp"
/* Headers from vtr util library */
#include "vtr_assert.h"
/* Headers from libarchfpga */
#include "arch_error.h"
#include "read_xml_util.h"
#include "read_xml_simulation_setting.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) {
if (std::string("frac") == type_string) {
return SIM_ACCURACY_FRAC;
}
if (std::string("abs") == type_string) {
return SIM_ACCURACY_ABS;
}
return NUM_SIM_ACCURACY_TYPES;
}
/********************************************************************
* 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,
SimulationSetting& sim_setting) {
/* Parse operating clock setting */
pugi::xml_node xml_operating_clock_setting = get_single_child(xml_clock_setting, "operating", loc_data);
sim_setting.set_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();
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 {
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.));
/* Parse programming clock setting */
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.));
}
/********************************************************************
* 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,
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_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);
/* 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));
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);
}
sim_setting.set_simulation_accuracy_type(accuracy_type);
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())) {
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",
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));
}
/********************************************************************
* 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,
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,
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.));
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.));
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.));
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.));
}
/********************************************************************
* 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,
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();
/* Translate the type of design technology to enumerate */
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);
}
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.));
/* 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",
sim_setting.stimuli_clock_slew(signal_type));
}
}
}
/********************************************************************
* 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,
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();
/* Translate the type of design technology to enumerate */
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);
}
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.));
/* 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",
sim_setting.stimuli_input_slew(signal_type));
}
}
}
/********************************************************************
* 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,
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);
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);
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);
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);
}
/********************************************************************
* Parse XML codes about <openfpga_simulation_setting> to an object of technology library
*******************************************************************/
SimulationSetting read_xml_simulation_setting(pugi::xml_node& Node,
const pugiutil::loc_data& loc_data) {
SimulationSetting sim_setting;
/* Parse clock settings */
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);
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);
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);
read_xml_measurement_setting(xml_measurement, loc_data, sim_setting);
/* Parse stimulus settings */
pugi::xml_node xml_stimulus = get_single_child(Node, "stimulus", loc_data);
read_xml_stimulus(xml_stimulus, loc_data, sim_setting);
return sim_setting;
}

View File

@ -0,0 +1,17 @@
#ifndef READ_XML_SIMULATION_SETTING_H
#define READ_XML_SIMULATION_SETTING_H
/********************************************************************
* Include header files that are required by function declaration
*******************************************************************/
#include "pugixml_util.hpp"
#include "pugixml.hpp"
#include "simulation_setting.h"
/********************************************************************
* Function declaration
*******************************************************************/
SimulationSetting read_xml_simulation_setting(pugi::xml_node& Node,
const pugiutil::loc_data& loc_data);
#endif

View File

@ -277,4 +277,3 @@ TechnologyLibrary read_xml_technology_library(pugi::xml_node& Node,
return tech_lib;
}

View File

@ -16,11 +16,11 @@ SimulationSetting::SimulationSetting() {
/************************************************************************
* Public Accessors
***********************************************************************/
float SimulationSetting::operating_clock_freqency() const {
float SimulationSetting::operating_clock_frequency() const {
return clock_frequencies_.x();
}
float SimulationSetting::programming_clock_freqency() const {
float SimulationSetting::programming_clock_frequency() const {
return clock_frequencies_.y();
}
@ -119,11 +119,11 @@ float SimulationSetting::stimuli_input_slew(const e_sim_signal_type& signal_type
/************************************************************************
* Public Mutators
***********************************************************************/
void SimulationSetting::set_operating_clock_freqency(const float& clock_freq) {
void SimulationSetting::set_operating_clock_frequency(const float& clock_freq) {
clock_frequencies_.set_x(clock_freq);
}
void SimulationSetting::set_programming_clock_freqency(const float& clock_freq) {
void SimulationSetting::set_programming_clock_frequency(const float& clock_freq) {
clock_frequencies_.set_y(clock_freq);
}

View File

@ -48,8 +48,8 @@ class SimulationSetting {
public: /* Constructors */
SimulationSetting();
public: /* Public Accessors */
float operating_clock_freqency() const;
float programming_clock_freqency() const;
float operating_clock_frequency() const;
float programming_clock_frequency() const;
bool auto_select_num_clock_cycles() const;
size_t num_clock_cycles() const;
float operating_clock_frequency_slack() const;
@ -70,8 +70,8 @@ class SimulationSetting {
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_operating_clock_freqency(const float& clock_freq);
void set_programming_clock_freqency(const float& clock_freq);
void set_operating_clock_frequency(const float& clock_freq);
void set_programming_clock_frequency(const float& clock_freq);
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);