[Tool] Update simulation setting object to support multi-clock and associated XML parsers/writers

This commit is contained in:
tangxifan 2021-01-14 15:38:24 -07:00
parent 923f3a3401
commit 852f5bb72e
10 changed files with 131 additions and 24 deletions

View File

@ -32,6 +32,20 @@ e_sim_accuracy_type string_to_sim_accuracy_type(const std::string& type_string)
return NUM_SIM_ACCURACY_TYPES;
}
/********************************************************************
* Parse XML codes of a <clock> line 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) {
/* Create a new clock override object in the sim_setting object with the given name */
SimulationClockId clock_id = sim_setting.create_simulation_clock(get_attribute(xml_clock_override_setting, "name", loc_data).as_string());
VTR_ASSERT(sim_setting.valid_clock_id(clock_id));
sim_setting.set_simulation_clock_frequency(clock_id, get_attribute(xml_clock_override_setting, "frequency", loc_data).as_float(0.));
}
/********************************************************************
* Parse XML codes of a <clock_setting> to an object of simulation setting
*******************************************************************/
@ -42,7 +56,7 @@ void read_xml_clock_setting(pugi::xml_node& xml_clock_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.));
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
@ -59,6 +73,15 @@ void read_xml_clock_setting(pugi::xml_node& xml_clock_setting,
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()) {
/* Error out if the XML child has an invalid name! */
if (xml_clock.name() != std::string("clock")) {
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);

View File

@ -9,6 +9,13 @@ namespace openfpga {
* Member functions for class SimulationSetting
***********************************************************************/
/************************************************************************
* Public Accessors : aggregates
***********************************************************************/
SimulationSetting::simulation_clock_range SimulationSetting::clocks() const {
return vtr::make_range(clock_ids_.begin(), clock_ids_.end());
}
/************************************************************************
* Constructors
***********************************************************************/
@ -19,12 +26,26 @@ SimulationSetting::SimulationSetting() {
/************************************************************************
* Public Accessors
***********************************************************************/
float SimulationSetting::operating_clock_frequency() const {
return clock_frequencies_.x();
float SimulationSetting::default_operating_clock_frequency() const {
return default_clock_frequencies_.x();
}
float SimulationSetting::programming_clock_frequency() const {
return clock_frequencies_.y();
return default_clock_frequencies_.y();
}
size_t SimulationSetting::num_simulation_clock_cycles() const {
return clock_ids_.size();
}
std::string SimulationSetting::clock_name(const SimulationClockId& clock_id) const {
VTR_ASSERT(valid_clock_id(clock_id));
return clock_names_[clock_id];
}
float SimulationSetting::clock_frequency(const SimulationClockId& clock_id) const {
VTR_ASSERT(valid_clock_id(clock_id));
return clock_frequencies_[clock_id];
}
bool SimulationSetting::auto_select_num_clock_cycles() const {
@ -110,12 +131,27 @@ float SimulationSetting::stimuli_input_slew(const e_sim_signal_type& signal_type
/************************************************************************
* Public Mutators
***********************************************************************/
void SimulationSetting::set_operating_clock_frequency(const float& clock_freq) {
clock_frequencies_.set_x(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) {
clock_frequencies_.set_y(clock_freq);
default_clock_frequencies_.set_y(clock_freq);
}
SimulationClockId SimulationSetting::create_simulation_clock(const std::string& name) {
SimulationClockId clock_id = SimulationClockId(clock_ids_.size());
clock_ids_.push_back(clock_id);
clock_names_.push_back(name);
clock_frequencies_.push_back(0.);
return clock_id;
}
void SimulationSetting::set_simulation_clock_frequency(const SimulationClockId& clock_id,
const float& frequency) {
VTR_ASSERT(valid_clock_id(clock_id));
clock_frequencies_[clock_id] = frequency;
}
void SimulationSetting::set_num_clock_cycles(const size_t& num_clk_cycles) {
@ -212,4 +248,9 @@ 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] );
}
} /* namespace openfpga ends */

View File

@ -8,8 +8,11 @@
#include <string>
#include <array>
#include "vtr_vector.h"
#include "vtr_geometry.h"
#include "simulation_setting_fwd.h"
/********************************************************************
* Types of signal type in measurement and stimuli
*******************************************************************/
@ -48,11 +51,20 @@ 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;
public: /* Public Accessors */
float operating_clock_frequency() const;
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;
float clock_frequency(const SimulationClockId& clock_id) const;
bool auto_select_num_clock_cycles() const;
size_t num_clock_cycles() const;
float operating_clock_frequency_slack() const;
@ -73,8 +85,16 @@ 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_frequency(const float& clock_freq);
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 default zero frequency which can be overwritten by
* the operating_clock_frequency()
*/
SimulationClockId create_simulation_clock(const std::string& name);
void set_simulation_clock_frequency(const SimulationClockId& clock_id,
const float& frequency);
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);
@ -102,13 +122,25 @@ class SimulationSetting {
const float& input_slew);
public: /* Public Validators */
bool valid_signal_threshold(const float& threshold) const;
bool valid_clock_id(const SimulationClockId& clock_id) const;
private: /* Internal data */
/* Operating clock frequency: the clock frequency to be applied to users' implemetation on FPGA
/* 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> clock_frequencies_;
vtr::Point<float> default_clock_frequencies_;
/* Multiple simulation clocks with detailed information
* Each clock has
* - a unique id
* - a unique name 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, float> clock_frequencies_;
/* Number of clock cycles to be used in simulation
* If the value is 0, the clock cycles can be automatically

View File

@ -27,7 +27,7 @@ void write_xml_clock_setting(std::fstream& fp,
fp << "\t" << "<clock_setting>" << "\n";
fp << "\t\t" << "<operating";
write_xml_attribute(fp, "frequency", sim_setting.operating_clock_frequency());
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");
@ -37,8 +37,19 @@ void write_xml_clock_setting(std::fstream& fp,
}
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.clocks()) {
fp << "\t\t\t" << "<clock";
write_xml_attribute(fp, "name", sim_setting.clock_name(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" << "<operating";
write_xml_attribute(fp, "frequency", sim_setting.programming_clock_frequency());
@ -219,7 +230,7 @@ void write_xml_simulation_setting(std::fstream& fp,
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";

View File

@ -191,7 +191,7 @@ int annotate_simulation_setting(const AtomContext& atom_ctx,
SimulationSetting& sim_setting) {
/* Find if the operating frequency is binded to vpr results */
if (0. == sim_setting.operating_clock_frequency()) {
if (0. == sim_setting.default_operating_clock_frequency()) {
VTR_LOG("User specified the operating clock frequency to use VPR results\n");
/* Run timing analysis and collect critical path delay
* This code is copied from function vpr_analysis() in vpr_api.h
@ -212,12 +212,12 @@ int annotate_simulation_setting(const AtomContext& atom_ctx,
/* Get critical path delay. Update simulation settings */
float T_crit = timing_info->least_slack_critical_path().delay() * (1. + sim_setting.operating_clock_frequency_slack());
sim_setting.set_operating_clock_frequency(1 / T_crit);
sim_setting.set_default_operating_clock_frequency(1 / T_crit);
VTR_LOG("Use VPR critical path delay %g [ns] with a %g [%] slack in OpenFPGA.\n",
T_crit / 1e9, sim_setting.operating_clock_frequency_slack() * 100);
}
VTR_LOG("Will apply operating clock frequency %g [MHz] to simulations\n",
sim_setting.operating_clock_frequency() / 1e6);
sim_setting.default_operating_clock_frequency() / 1e6);
if (0. == sim_setting.num_clock_cycles()) {
/* Find the number of clock cycles to be used in simulation

View File

@ -84,7 +84,7 @@ int write_pnr_sdc(const OpenfpgaContext& openfpga_ctx,
if (true == options.generate_sdc_pnr()) {
print_pnr_sdc(options,
1./openfpga_ctx.simulation_setting().programming_clock_frequency(),
1./openfpga_ctx.simulation_setting().operating_clock_frequency(),
1./openfpga_ctx.simulation_setting().default_operating_clock_frequency(),
g_vpr_ctx.device(),
openfpga_ctx.vpr_device_annotation(),
openfpga_ctx.device_rr_gsb(),
@ -190,7 +190,7 @@ int write_analysis_sdc(const OpenfpgaContext& openfpga_ctx,
if (true == options.generate_sdc_analysis()) {
print_analysis_sdc(options,
1./openfpga_ctx.simulation_setting().operating_clock_frequency(),
1./openfpga_ctx.simulation_setting().default_operating_clock_frequency(),
g_vpr_ctx,
openfpga_ctx,
openfpga_ctx.flow_manager().compress_routing());

View File

@ -226,7 +226,7 @@ void fpga_verilog_testbench(const ModuleManager &module_manager,
bitstream_manager.num_bits(),
simulation_setting.num_clock_cycles(),
simulation_setting.programming_clock_frequency(),
simulation_setting.operating_clock_frequency());
simulation_setting.default_operating_clock_frequency());
}
/* Generate a Verilog file including all the netlists that have been generated */

View File

@ -254,7 +254,7 @@ void print_verilog_random_top_testbench(const std::string& circuit_name,
float simulation_time = find_operating_phase_simulation_time(MAGIC_NUMBER_FOR_SIMULATION_TIME,
simulation_parameters.num_clock_cycles(),
1./simulation_parameters.operating_clock_frequency(),
1./simulation_parameters.default_operating_clock_frequency(),
VERILOG_SIM_TIMESCALE);
/* Add Icarus requirement */

View File

@ -488,7 +488,7 @@ void print_verilog_testbench_clock_stimuli(std::fstream& fp,
/* Create clock stimuli */
fp << "\t\t" << generate_verilog_port(VERILOG_PORT_CONKT, clock_port) << " <= 1'b0;" << std::endl;
fp << "\t\twhile(1) begin" << std::endl;
fp << "\t\t\t#" << std::setprecision(10) << ((0.5/simulation_parameters.operating_clock_frequency())/VERILOG_SIM_TIMESCALE) << std::endl;
fp << "\t\t\t#" << std::setprecision(10) << ((0.5/simulation_parameters.default_operating_clock_frequency())/VERILOG_SIM_TIMESCALE) << std::endl;
fp << "\t\t\t" << generate_verilog_port(VERILOG_PORT_CONKT, clock_port);
fp << " <= !";
fp << generate_verilog_port(VERILOG_PORT_CONKT, clock_port);

View File

@ -1839,7 +1839,7 @@ void print_verilog_top_testbench(const ModuleManager& module_manager,
/* Find the clock period */
float prog_clock_period = (1./simulation_parameters.programming_clock_frequency());
float op_clock_period = (1./simulation_parameters.operating_clock_frequency());
float op_clock_period = (1./simulation_parameters.default_operating_clock_frequency());
/* Estimate the number of configuration clock cycles */
size_t num_config_clock_cycles = calculate_num_config_clock_cycles(config_protocol.type(),
apply_fast_configuration,
@ -1968,7 +1968,7 @@ void print_verilog_top_testbench(const ModuleManager& module_manager,
num_config_clock_cycles,
1./simulation_parameters.programming_clock_frequency(),
simulation_parameters.num_clock_cycles(),
1./simulation_parameters.operating_clock_frequency());
1./simulation_parameters.default_operating_clock_frequency());
/* Add Icarus requirement: