[Engine] Support programming shift register clock in XML syntax

This commit is contained in:
tangxifan 2021-10-01 11:00:38 -07:00
parent fa57117f50
commit 7b010ba0f4
14 changed files with 217 additions and 12 deletions

View File

@ -949,7 +949,6 @@ bool CircuitLibrary::port_is_config_enable(const CircuitPortId& circuit_port_id)
return port_is_config_enable_[circuit_port_id];
}
/* Return a flag if the port is used during programming a FPGA in a circuit model */
bool CircuitLibrary::port_is_prog(const CircuitPortId& circuit_port_id) const {
/* validate the circuit_port_id */
@ -957,6 +956,13 @@ bool CircuitLibrary::port_is_prog(const CircuitPortId& circuit_port_id) const {
return port_is_prog_[circuit_port_id];
}
/* Return a flag if the port is used by shift register in a circuit model */
bool CircuitLibrary::port_is_shift_register(const CircuitPortId& circuit_port_id) const {
/* validate the circuit_port_id */
VTR_ASSERT(valid_circuit_port_id(circuit_port_id));
return port_is_shift_register_[circuit_port_id];
}
/* Return which level the output port locates at a LUT multiplexing structure */
size_t CircuitLibrary::port_lut_frac_level(const CircuitPortId& circuit_port_id) const {
/* validate the circuit_port_id */
@ -1401,6 +1407,7 @@ CircuitPortId CircuitLibrary::add_model_port(const CircuitModelId& model_id,
port_is_set_.push_back(false);
port_is_config_enable_.push_back(false);
port_is_prog_.push_back(false);
port_is_shift_register_.push_back(false);
port_tri_state_model_names_.emplace_back();
port_tri_state_model_ids_.push_back(CircuitModelId::INVALID());
port_inv_model_names_.emplace_back();
@ -1538,6 +1545,15 @@ void CircuitLibrary::set_port_is_prog(const CircuitPortId& circuit_port_id,
return;
}
/* Set the is_prog for a port of a circuit model */
void CircuitLibrary::set_port_is_shift_register(const CircuitPortId& circuit_port_id,
const bool& is_shift_register) {
/* validate the circuit_port_id */
VTR_ASSERT(valid_circuit_port_id(circuit_port_id));
port_is_shift_register_[circuit_port_id] = is_shift_register;
return;
}
/* Set the model_name for a port of a circuit model */
void CircuitLibrary::set_port_tri_state_model_name(const CircuitPortId& circuit_port_id,
const std::string& model_name) {

View File

@ -288,6 +288,7 @@ class CircuitLibrary {
bool port_is_set(const CircuitPortId& circuit_port_id) const;
bool port_is_config_enable(const CircuitPortId& circuit_port_id) const;
bool port_is_prog(const CircuitPortId& circuit_port_id) const;
bool port_is_shift_register(const CircuitPortId& circuit_port_id) const;
size_t port_lut_frac_level(const CircuitPortId& circuit_port_id) const;
bool port_is_harden_lut_port(const CircuitPortId& circuit_port_id) const;
std::vector<size_t> port_lut_output_mask(const CircuitPortId& circuit_port_id) const;
@ -372,6 +373,8 @@ class CircuitLibrary {
const bool& is_config_enable);
void set_port_is_prog(const CircuitPortId& circuit_port_id,
const bool& is_prog);
void set_port_is_shift_register(const CircuitPortId& circuit_port_id,
const bool& is_shift_register);
void set_port_tri_state_model_name(const CircuitPortId& circuit_port_id,
const std::string& model_name);
void set_port_tri_state_model_id(const CircuitPortId& circuit_port_id,
@ -560,6 +563,7 @@ class CircuitLibrary {
vtr::vector<CircuitPortId, bool> port_is_set_;
vtr::vector<CircuitPortId, bool> port_is_config_enable_;
vtr::vector<CircuitPortId, bool> port_is_prog_;
vtr::vector<CircuitPortId, bool> port_is_shift_register_;
vtr::vector<CircuitPortId, std::string> port_tri_state_model_names_;
vtr::vector<CircuitPortId, CircuitModelId> port_tri_state_model_ids_;
vtr::vector<CircuitPortId, std::string> port_inv_model_names_;

View File

@ -484,6 +484,9 @@ void read_xml_circuit_port(pugi::xml_node& xml_port,
/* Identify if the port is in programming purpose, by default it is NOT */
circuit_lib.set_port_is_prog(port, get_attribute(xml_port, "is_prog", loc_data, pugiutil::ReqOpt::OPTIONAL).as_bool(false));
/* Identify if the port is in shift register purpose, by default it is NOT */
circuit_lib.set_port_is_shift_register(port, get_attribute(xml_port, "is_shift_register", loc_data, pugiutil::ReqOpt::OPTIONAL).as_bool(false));
/* Identify if the port is to enable programming for FPGAs, by default it is NOT */
circuit_lib.set_port_is_config_enable(port, get_attribute(xml_port, "is_config_enable", loc_data, pugiutil::ReqOpt::OPTIONAL).as_bool(false));

View File

@ -36,7 +36,7 @@ e_sim_accuracy_type string_to_sim_accuracy_type(const std::string& type_string)
}
/********************************************************************
* Parse XML codes of a <clock> line 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,
@ -62,6 +62,40 @@ void read_xml_operating_clock_override_setting(pugi::xml_node& xml_clock_overrid
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
*******************************************************************/
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 */
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",
clock_name.c_str());
}
/* Parse port information */
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();
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_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));
}
/********************************************************************
* Parse XML codes of a <clock_setting> to an object of simulation setting
*******************************************************************/
@ -102,6 +136,15 @@ void read_xml_clock_setting(pugi::xml_node& xml_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.));
/* Iterate over multiple operating clock settings and parse one by one */
for (pugi::xml_node xml_clock : xml_programming_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_programming_clock_setting, {"clock"});
}
read_xml_programming_clock_override_setting(xml_clock, loc_data, sim_setting);
}
}
/********************************************************************

View File

@ -16,6 +16,36 @@ SimulationSetting::simulation_clock_range SimulationSetting::clocks() const {
return vtr::make_range(clock_ids_.begin(), clock_ids_.end());
}
std::vector<SimulationClockId> SimulationSetting::operating_clocks() const {
std::vector<SimulationClockId> op_clks;
for (const SimulationClockId& clk : clocks()) {
if (!clock_is_programming(clk)) {
op_clks.push_back(clk);
}
}
return op_clks;
}
std::vector<SimulationClockId> SimulationSetting::programming_clocks() const {
std::vector<SimulationClockId> prog_clks;
for (const SimulationClockId& clk : clocks()) {
if (clock_is_programming(clk)) {
prog_clks.push_back(clk);
}
}
return prog_clks;
}
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)) {
prog_clks.push_back(clk);
}
}
return prog_clks;
}
/************************************************************************
* Constructors
***********************************************************************/
@ -53,6 +83,16 @@ float SimulationSetting::clock_frequency(const SimulationClockId& clock_id) cons
return clock_frequencies_[clock_id];
}
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 {
VTR_ASSERT(valid_clock_id(clock_id));
return clock_is_shift_register_[clock_id];
}
bool SimulationSetting::auto_select_num_clock_cycles() const {
return 0 == num_clock_cycles_;
}
@ -157,6 +197,8 @@ SimulationClockId SimulationSetting::create_clock(const std::string& name) {
clock_names_.push_back(name);
clock_ports_.emplace_back();
clock_frequencies_.push_back(0.);
clock_is_programming_.push_back(false);
clock_is_shift_register_.push_back(false);
/* Register in the name-to-id map */
clock_name2ids_[name] = clock_id;
@ -176,6 +218,18 @@ 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) {
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) {
VTR_ASSERT(valid_clock_id(clock_id));
clock_is_shift_register_[clock_id] = is_sr;
}
void SimulationSetting::set_num_clock_cycles(const size_t& num_clk_cycles) {
num_clock_cycles_ = num_clk_cycles;
}

View File

@ -62,6 +62,9 @@ class SimulationSetting {
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;
@ -69,6 +72,8 @@ class SimulationSetting {
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;
@ -102,6 +107,10 @@ class SimulationSetting {
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);
@ -150,6 +159,8 @@ class SimulationSetting {
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_;
/* Fast name-to-id lookup */
std::map<std::string, SimulationClockId> clock_name2ids_;

View File

@ -220,6 +220,10 @@ void write_xml_circuit_port(std::fstream& fp,
write_xml_attribute(fp, "is_prog", "true");
}
if (true == circuit_lib.port_is_shift_register(port)) {
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");
}

View File

@ -41,7 +41,7 @@ void write_xml_clock_setting(std::fstream& fp,
fp << ">" << "\n";
/* Output clock information one by one */
for (const SimulationClockId& clock_id : sim_setting.clocks()) {
for (const SimulationClockId& clock_id : sim_setting.operating_clocks()) {
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());
@ -52,9 +52,22 @@ void write_xml_clock_setting(std::fstream& fp,
fp << "\t\t" << "</operating";
fp << ">" << "\n";
fp << "\t\t" << "<operating";
fp << "\t\t" << "<programming";
write_xml_attribute(fp, "frequency", sim_setting.programming_clock_frequency());
fp << "/>" << "\n";
fp << ">" << "\n";
/* Output clock information one by one */
for (const SimulationClockId& clock_id : sim_setting.programming_clocks()) {
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";
}
fp << "\t\t" << "</programming";
fp << ">" << "\n";
fp << "\t" << "</clock_setting>" << "\n";
}

View File

@ -50,6 +50,11 @@ bool FabricGlobalPortInfo::global_port_is_prog(const FabricGlobalPortId& global_
return global_port_is_prog_[global_port_id];
}
bool FabricGlobalPortInfo::global_port_is_shift_register(const FabricGlobalPortId& global_port_id) const {
VTR_ASSERT(valid_global_port_id(global_port_id));
return global_port_is_shift_register_[global_port_id];
}
bool FabricGlobalPortInfo::global_port_is_config_enable(const FabricGlobalPortId& global_port_id) const {
VTR_ASSERT(valid_global_port_id(global_port_id));
return global_port_is_config_enable_[global_port_id];
@ -77,6 +82,7 @@ FabricGlobalPortId FabricGlobalPortInfo::create_global_port(const ModulePortId&
global_port_is_set_.push_back(false);
global_port_is_reset_.push_back(false);
global_port_is_prog_.push_back(false);
global_port_is_shift_register_.push_back(false);
global_port_is_io_.push_back(false);
global_port_is_config_enable_.push_back(false);
global_port_default_values_.push_back(0);
@ -108,6 +114,12 @@ void FabricGlobalPortInfo::set_global_port_is_prog(const FabricGlobalPortId& glo
global_port_is_prog_[global_port_id] = is_prog;
}
void FabricGlobalPortInfo::set_global_port_is_shift_register(const FabricGlobalPortId& global_port_id,
const bool& is_shift_register) {
VTR_ASSERT(valid_global_port_id(global_port_id));
global_port_is_shift_register_[global_port_id] = is_shift_register;
}
void FabricGlobalPortInfo::set_global_port_is_config_enable(const FabricGlobalPortId& global_port_id,
const bool& is_config_enable) {
VTR_ASSERT(valid_global_port_id(global_port_id));

View File

@ -36,6 +36,7 @@ class FabricGlobalPortInfo {
bool global_port_is_set(const FabricGlobalPortId& global_port_id) const;
bool global_port_is_reset(const FabricGlobalPortId& global_port_id) const;
bool global_port_is_prog(const FabricGlobalPortId& global_port_id) const;
bool global_port_is_shift_register(const FabricGlobalPortId& global_port_id) const;
bool global_port_is_config_enable(const FabricGlobalPortId& global_port_id) const;
bool global_port_is_io(const FabricGlobalPortId& global_port_id) const;
size_t global_port_default_value(const FabricGlobalPortId& global_port_id) const;
@ -52,6 +53,8 @@ class FabricGlobalPortInfo {
const bool& is_reset);
void set_global_port_is_prog(const FabricGlobalPortId& global_port_id,
const bool& is_prog);
void set_global_port_is_shift_register(const FabricGlobalPortId& global_port_id,
const bool& is_shift_register);
void set_global_port_is_config_enable(const FabricGlobalPortId& global_port_id,
const bool& is_config_enable);
void set_global_port_is_io(const FabricGlobalPortId& global_port_id,
@ -68,6 +71,7 @@ class FabricGlobalPortInfo {
vtr::vector<FabricGlobalPortId, bool> global_port_is_reset_;
vtr::vector<FabricGlobalPortId, bool> global_port_is_set_;
vtr::vector<FabricGlobalPortId, bool> global_port_is_prog_;
vtr::vector<FabricGlobalPortId, bool> global_port_is_shift_register_;
vtr::vector<FabricGlobalPortId, bool> global_port_is_config_enable_;
vtr::vector<FabricGlobalPortId, bool> global_port_is_io_;
vtr::vector<FabricGlobalPortId, size_t> global_port_default_values_;

View File

@ -97,7 +97,7 @@ void print_pnr_sdc_global_clock_ports(std::fstream& fp,
/* Should try to find a port defintion from simulation parameters
* If found, it means that we need to use special clock name!
*/
for (const SimulationClockId& sim_clock : sim_setting.clocks()) {
for (const SimulationClockId& sim_clock : sim_setting.operating_clocks()) {
if (port_to_constrain == sim_setting.clock_port(sim_clock)) {
clock_period = 1./sim_setting.clock_frequency(sim_clock);
}

View File

@ -515,7 +515,7 @@ void print_verilog_testbench_clock_stimuli(std::fstream& fp,
/* Skip all the unrelated pin constraints */
VTR_ASSERT(clock_port.get_name() == pin_constraints.net(pin_constraint));
/* Try to find which clock source is considered in simulation settings for this pin */
for (const SimulationClockId& sim_clock_id : simulation_parameters.clocks()) {
for (const SimulationClockId& sim_clock_id : simulation_parameters.operating_clocks()) {
if (pin_constraints.pin(pin_constraint) == simulation_parameters.clock_port(sim_clock_id)) {
clk_freq_to_use = (0.5 / simulation_parameters.clock_frequency(sim_clock_id)) / VERILOG_SIM_TIMESCALE;
}

View File

@ -290,7 +290,7 @@ void print_verilog_top_testbench_global_clock_ports_stimuli(std::fstream& fp,
/* Should try to find a port defintion from simulation parameters
* If found, it means that we need to use special clock name!
*/
for (const SimulationClockId& sim_clock : simulation_parameters.clocks()) {
for (const SimulationClockId& sim_clock : simulation_parameters.operating_clocks()) {
if (global_port_to_connect == simulation_parameters.clock_port(sim_clock)) {
stimuli_clock_port.set_name(generate_top_testbench_clock_name(std::string(TOP_TB_OP_CLOCK_PORT_PREFIX), simulation_parameters.clock_name(sim_clock)));
}
@ -640,7 +640,7 @@ void print_verilog_top_testbench_benchmark_clock_ports(std::fstream& fp,
/* Skip all the unrelated pin constraints */
VTR_ASSERT(clock_port_name == pin_constraints.net(pin_constraint));
/* Try to find which clock source is considered in simulation settings for this pin */
for (const SimulationClockId& sim_clock_id : simulation_parameters.clocks()) {
for (const SimulationClockId& sim_clock_id : simulation_parameters.operating_clocks()) {
if (pin_constraints.pin(pin_constraint) == simulation_parameters.clock_port(sim_clock_id)) {
std::string sim_clock_port_name = generate_top_testbench_clock_name(std::string(TOP_TB_OP_CLOCK_PORT_PREFIX), simulation_parameters.clock_name(sim_clock_id));
clock_source_to_connect = BasicPort(sim_clock_port_name, 1);
@ -742,7 +742,7 @@ void print_verilog_top_testbench_ports(std::fstream& fp,
fp << generate_verilog_port(VERILOG_PORT_REG, prog_clock_register_port) << ";" << std::endl;
/* Multiple operating clocks based on the simulation settings */
for (const SimulationClockId& sim_clock : simulation_parameters.clocks()) {
for (const SimulationClockId& sim_clock : simulation_parameters.operating_clocks()) {
std::string sim_clock_port_name = generate_top_testbench_clock_name(std::string(TOP_TB_OP_CLOCK_PORT_PREFIX), simulation_parameters.clock_name(sim_clock));
BasicPort sim_clock_port(sim_clock_port_name, 1);
fp << generate_verilog_port(VERILOG_PORT_WIRE, sim_clock_port) << ";" << std::endl;
@ -1010,7 +1010,7 @@ void print_verilog_top_testbench_generic_stimulus(std::fstream& fp,
fp << std::endl;
/* Generate stimuli waveform for multiple user-defined operating clock signals */
for (const SimulationClockId& sim_clock : simulation_parameters.clocks()) {
for (const SimulationClockId& sim_clock : simulation_parameters.operating_clocks()) {
print_verilog_comment(fp, "----- Begin raw operating clock signal '" + simulation_parameters.clock_name(sim_clock) + "' generation -----");
std::string sim_clock_port_name = generate_top_testbench_clock_name(std::string(TOP_TB_OP_CLOCK_PORT_PREFIX), simulation_parameters.clock_name(sim_clock));
BasicPort sim_clock_port(sim_clock_port_name, 1);
@ -1935,7 +1935,7 @@ int print_verilog_full_testbench(const ModuleManager& module_manager,
float prog_clock_period = (1./simulation_parameters.programming_clock_frequency());
float default_op_clock_period = (1./simulation_parameters.default_operating_clock_frequency());
float max_op_clock_period = 0.;
for (const SimulationClockId& clock_id : simulation_parameters.clocks()) {
for (const SimulationClockId& clock_id : simulation_parameters.operating_clocks()) {
max_op_clock_period = std::max(max_op_clock_period, (float)(1./simulation_parameters.clock_frequency(clock_id)));
}

View File

@ -0,0 +1,41 @@
<!-- Simulation Setting for OpenFPGA framework
This file will use automatic inference for any settings
including:
- auto select the number of simulation cycles
- auto select the simulation clock frequency from VPR results
-->
<openfpga_simulation_setting>
<clock_setting>
<operating frequency="auto" num_cycles="auto" slack="0.2"/>
<programming frequency="100e6">
<clock name="shift_register_clk" port="sr_clk[0:0]" frequency="auto" is_shift_register="true"/>
</programming>
</clock_setting>
<simulator_option>
<operating_condition temperature="25"/>
<output_log verbose="false" captab="false"/>
<accuracy type="abs" value="1e-13"/>
<runtime fast_simulation="true"/>
</simulator_option>
<monte_carlo num_simulation_points="2"/>
<measurement_setting>
<slew>
<rise upper_thres_pct="0.95" lower_thres_pct="0.05"/>
<fall upper_thres_pct="0.05" lower_thres_pct="0.95"/>
</slew>
<delay>
<rise input_thres_pct="0.5" output_thres_pct="0.5"/>
<fall input_thres_pct="0.5" output_thres_pct="0.5"/>
</delay>
</measurement_setting>
<stimulus>
<clock>
<rise slew_type="abs" slew_time="20e-12" />
<fall slew_type="abs" slew_time="20e-12" />
</clock>
<input>
<rise slew_type="abs" slew_time="25e-12" />
<fall slew_type="abs" slew_time="25e-12" />
</input>
</stimulus>
</openfpga_simulation_setting>