[Tool] Update simulation setting object to support multi-clock and associated XML parsers/writers
This commit is contained in:
parent
923f3a3401
commit
852f5bb72e
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue