Merge pull request #173 from lnis-uofu/dev
Support Multiple Clock Definition in Testbench and SDC Generators
This commit is contained in:
commit
4f1d815d7b
|
@ -49,6 +49,8 @@ Similar to the Switch Boxes and Connection Blocks, the channel wire segments in
|
|||
|
||||
- ``circuit_model_name="<string>"`` should match a circuit model whose type is ``chan_wire`` defined in :ref:`circuit_library`.
|
||||
|
||||
.. _annotate_vpr_arch_physical_tile_annotation:
|
||||
|
||||
Physical Tile Annotation
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
|
|
@ -136,6 +136,8 @@ Pass Gate Logic
|
|||
.. note:: pass-gate logic are used in building multiplexers and LUTs.
|
||||
|
||||
|
||||
.. _circuit_library_circuit_port:
|
||||
|
||||
Circuit Port
|
||||
^^^^^^^^^^^^
|
||||
|
||||
|
|
|
@ -10,7 +10,10 @@ General organization is as follows
|
|||
|
||||
<openfpga_simulation_setting>
|
||||
<clock_setting>
|
||||
<operating frequency="<int>|<string>" num_cycles="<int>|<string>" slack="<float>"/>
|
||||
<operating frequency="<int>|<string>" num_cycles="<int>|<string>" slack="<float>">
|
||||
<clock name="<string>" port="<string>" frequency="<float>"/>
|
||||
...
|
||||
</operating>
|
||||
<programming frequency="<int>"/>
|
||||
</clock_setting>
|
||||
<simulator_option>
|
||||
|
@ -54,13 +57,17 @@ We should the full syntax in the code block below and then provide details on ea
|
|||
.. code-block:: xml
|
||||
|
||||
<clock_setting>
|
||||
<operating frequency="<float>|<string>" num_cycles="<int>|<string>" slack="<float>"/>
|
||||
<operating frequency="<float>|<string>" num_cycles="<int>|<string>" slack="<float>">
|
||||
<clock name="<string>" port="<string>" frequency="<float>"/>
|
||||
...
|
||||
</operating>
|
||||
<programming frequency="<float>"/>
|
||||
</clock_setting>
|
||||
|
||||
Operating clock setting
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
Operating clocks are defined under the XML node ``<operating>``
|
||||
To support FPGA fabrics with multiple clocks, OpenFPGA allows users to define a default operating clock frequency as well as a set of clock ports using different frequencies.
|
||||
|
||||
.. option:: <operating frequency="<float>|<string>" num_cycles="<int>|<string>" slack="<float>"/>
|
||||
|
||||
|
@ -70,6 +77,8 @@ Operating clocks are defined under the XML node ``<operating>``
|
|||
This is very useful to validate the maximum operating frequency for users' implementations
|
||||
In such case, the value of this attribute should be a reserved word ``auto``.
|
||||
|
||||
.. note:: The frequency is considered as a default operating clock frequency, which will be used when a clock pin of a multi-clock FPGA fabric lacks explicit clock definition.
|
||||
|
||||
- ``num_cycles="<int>|<string>"``
|
||||
can be either ``auto`` or an integer. When set to ``auto``, OpenFPGA will infer the number of clock cycles from the average/median of all the signal activities.
|
||||
When set to an integer, OpenFPGA will use the given number of clock cycles in HDL and SPICE simulations.
|
||||
|
@ -86,6 +95,22 @@ Operating clocks are defined under the XML node ``<operating>``
|
|||
|
||||
.. warning:: Avoid to use a negative slack! This may cause your simulation to fail!
|
||||
|
||||
.. option:: <clock name="<string>" port="<string>" frequency="<float>"/>
|
||||
|
||||
- ``name="<string>``
|
||||
Specify a unique name for a clock signal. The name will be used in generating clock stimulus in testbenches.
|
||||
|
||||
- ``port="<string>``
|
||||
Specify the clock port which the clock signal should be applied to. The clock port must be a valid clock port defined in OpenFPGA architecture description. Explicit index is required, e.g., ``clk[1:1]``. Otherwise, default index ``0`` will be considered, e.g., ``clk`` will be translated as ``clk[0:0]``.
|
||||
|
||||
.. note:: You can define clock ports either through the tile annotation in :ref:`annotate_vpr_arch_physical_tile_annotation` or :ref:`circuit_library_circuit_port`.
|
||||
|
||||
- ``frequency="<float>``
|
||||
Specify frequency of a clock signal in the unit of ``[Hz]``
|
||||
|
||||
.. warning:: Currently, we only allow operating clocks to be overwritten!!!
|
||||
|
||||
|
||||
Programming clock setting
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
Programming clocks are defined under the XML node ``<programming>``
|
||||
|
|
|
@ -12,6 +12,9 @@
|
|||
/* Headers from vtr util library */
|
||||
#include "vtr_assert.h"
|
||||
|
||||
/* Headers from openfpga util library */
|
||||
#include "openfpga_port_parser.h"
|
||||
|
||||
/* Headers from libarchfpga */
|
||||
#include "arch_error.h"
|
||||
#include "read_xml_util.h"
|
||||
|
@ -32,6 +35,33 @@ 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) {
|
||||
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 */
|
||||
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_setting> to an object of simulation setting
|
||||
*******************************************************************/
|
||||
|
@ -42,7 +72,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 +89,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,31 @@ 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];
|
||||
}
|
||||
|
||||
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 {
|
||||
VTR_ASSERT(valid_clock_id(clock_id));
|
||||
return clock_frequencies_[clock_id];
|
||||
}
|
||||
|
||||
bool SimulationSetting::auto_select_num_clock_cycles() const {
|
||||
|
@ -110,12 +136,44 @@ 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_clock(const std::string& name) {
|
||||
/* Ensure a unique name for the clock definition */
|
||||
std::map<std::string, SimulationClockId>::iterator it = clock_name2ids_.find(name);
|
||||
if (it != clock_name2ids_.end()) {
|
||||
return SimulationClockId::INVALID();
|
||||
}
|
||||
|
||||
/* This is a legal name. we can create a new id */
|
||||
SimulationClockId clock_id = SimulationClockId(clock_ids_.size());
|
||||
clock_ids_.push_back(clock_id);
|
||||
clock_names_.push_back(name);
|
||||
clock_ports_.emplace_back();
|
||||
clock_frequencies_.push_back(0.);
|
||||
|
||||
/* Register in the name-to-id map */
|
||||
clock_name2ids_[name] = clock_id;
|
||||
|
||||
return clock_id;
|
||||
}
|
||||
|
||||
void SimulationSetting::set_clock_port(const SimulationClockId& clock_id,
|
||||
const BasicPort& port) {
|
||||
VTR_ASSERT(valid_clock_id(clock_id));
|
||||
clock_ports_[clock_id] = port;
|
||||
}
|
||||
|
||||
void SimulationSetting::set_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 +270,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 */
|
||||
|
|
|
@ -7,9 +7,15 @@
|
|||
*******************************************************************/
|
||||
#include <string>
|
||||
#include <array>
|
||||
#include <map>
|
||||
|
||||
#include "vtr_vector.h"
|
||||
#include "vtr_geometry.h"
|
||||
|
||||
#include "openfpga_port.h"
|
||||
|
||||
#include "simulation_setting_fwd.h"
|
||||
|
||||
/********************************************************************
|
||||
* Types of signal type in measurement and stimuli
|
||||
*******************************************************************/
|
||||
|
@ -48,11 +54,21 @@ 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;
|
||||
BasicPort clock_port(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 +89,19 @@ 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 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_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 +129,30 @@ 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
|
||||
* - 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_;
|
||||
|
||||
/* Fast name-to-id lookup */
|
||||
std::map<std::string, SimulationClockId> clock_name2ids_;
|
||||
|
||||
/* Number of clock cycles to be used in simulation
|
||||
* If the value is 0, the clock cycles can be automatically
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
/************************************************************************
|
||||
* 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
|
||||
***********************************************************************/
|
||||
#ifndef SIMULATION_SETTING_FWD_H
|
||||
#define SIMULATION_SETTING_FWD_H
|
||||
|
||||
#include "vtr_strong_id.h"
|
||||
|
||||
struct simulation_clock_id_tag;
|
||||
|
||||
typedef vtr::StrongId<simulation_clock_id_tag> SimulationClockId;
|
||||
|
||||
/* Short declaration of class */
|
||||
class SimulationSetting;
|
||||
|
||||
#endif
|
|
@ -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,20 @@ 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, "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" << "<operating";
|
||||
write_xml_attribute(fp, "frequency", sim_setting.programming_clock_frequency());
|
||||
|
@ -219,7 +231,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";
|
||||
|
|
|
@ -17,25 +17,6 @@
|
|||
/* namespace openfpga begins */
|
||||
namespace openfpga {
|
||||
|
||||
/********************************************************************
|
||||
* FIXME: Use a common function to output ports
|
||||
* Generate the full hierarchy name for a operating pb_type
|
||||
*******************************************************************/
|
||||
static
|
||||
std::string generate_tile_port_name(const BasicPort& pb_port) {
|
||||
std::string port_name;
|
||||
|
||||
/* Output format: <port_name>[<LSB>:<MSB>] */
|
||||
port_name += pb_port.get_name();
|
||||
port_name += std::string("[");
|
||||
port_name += std::to_string(pb_port.get_lsb());
|
||||
port_name += std::string(":");
|
||||
port_name += std::to_string(pb_port.get_msb());
|
||||
port_name += std::string("]");
|
||||
|
||||
return port_name;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* A writer to output a device variation in a technology library to XML format
|
||||
*******************************************************************/
|
||||
|
@ -64,7 +45,7 @@ void write_xml_tile_annotation_global_port(std::fstream& fp,
|
|||
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_tile_port_name(tile_annotation.global_port_tile_ports(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 << "/>";
|
||||
|
|
|
@ -90,3 +90,21 @@ void write_xml_attribute(std::fstream& fp,
|
|||
fp << std::scientific << value;
|
||||
fp << "\"";
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* FIXME: Use a common function to output ports
|
||||
* Generate the full hierarchy name for a operating pb_type
|
||||
*******************************************************************/
|
||||
std::string generate_xml_port_name(const openfpga::BasicPort& pb_port) {
|
||||
std::string port_name;
|
||||
|
||||
/* Output format: <port_name>[<LSB>:<MSB>] */
|
||||
port_name += pb_port.get_name();
|
||||
port_name += std::string("[");
|
||||
port_name += std::to_string(pb_port.get_lsb());
|
||||
port_name += std::string(":");
|
||||
port_name += std::to_string(pb_port.get_msb());
|
||||
port_name += std::string("]");
|
||||
|
||||
return port_name;
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
*******************************************************************/
|
||||
#include <fstream>
|
||||
#include "circuit_library.h"
|
||||
#include "openfpga_port.h"
|
||||
|
||||
/********************************************************************
|
||||
* Function declaration
|
||||
|
@ -30,4 +31,6 @@ 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);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -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,24 @@ 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);
|
||||
|
||||
/* Walk through all the clock information */
|
||||
for (const SimulationClockId& clock_id : sim_setting.clocks()) {
|
||||
if (0. == sim_setting.clock_frequency(clock_id)) {
|
||||
sim_setting.set_clock_frequency(clock_id, sim_setting.default_operating_clock_frequency());
|
||||
}
|
||||
VTR_LOG("Will apply clock frequency %g [MHz] to clock '%s[%d:%d]' in simulations\n",
|
||||
sim_setting.clock_frequency(clock_id) / 1e6,
|
||||
sim_setting.clock_port(clock_id).get_name().c_str(),
|
||||
sim_setting.clock_port(clock_id).get_lsb(),
|
||||
sim_setting.clock_port(clock_id).get_msb());
|
||||
}
|
||||
|
||||
if (0. == sim_setting.num_clock_cycles()) {
|
||||
/* Find the number of clock cycles to be used in simulation
|
||||
|
|
|
@ -83,8 +83,6 @@ int write_pnr_sdc(const OpenfpgaContext& openfpga_ctx,
|
|||
/* Execute only when sdc is enabled */
|
||||
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(),
|
||||
g_vpr_ctx.device(),
|
||||
openfpga_ctx.vpr_device_annotation(),
|
||||
openfpga_ctx.device_rr_gsb(),
|
||||
|
@ -92,6 +90,7 @@ int write_pnr_sdc(const OpenfpgaContext& openfpga_ctx,
|
|||
openfpga_ctx.mux_lib(),
|
||||
openfpga_ctx.arch().circuit_lib,
|
||||
openfpga_ctx.fabric_global_port_info(),
|
||||
openfpga_ctx.simulation_setting(),
|
||||
openfpga_ctx.flow_manager().compress_routing());
|
||||
}
|
||||
|
||||
|
@ -190,7 +189,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());
|
||||
|
|
|
@ -241,7 +241,10 @@ void print_analysis_sdc(const AnalysisSdcOption& option,
|
|||
ModuleId top_module = openfpga_ctx.module_graph().find_module(generate_fpga_top_module_name());
|
||||
VTR_ASSERT(true == openfpga_ctx.module_graph().valid_module_id(top_module));
|
||||
|
||||
/* Create clock and set I/O ports with input/output delays */
|
||||
/* Create clock and set I/O ports with input/output delays
|
||||
* FIXME: Now different I/Os have different delays due to multiple clock frequency
|
||||
* We need to consider these impacts and constrain different I/Os with different delays!!!
|
||||
*/
|
||||
print_analysis_sdc_io_delays(fp, option.time_unit(),
|
||||
vpr_ctx.atom(), vpr_ctx.placement(),
|
||||
openfpga_ctx.vpr_netlist_annotation(), openfpga_ctx.io_location_map(),
|
||||
|
|
|
@ -59,11 +59,10 @@ void print_pnr_sdc_clock_port(std::fstream& fp,
|
|||
*******************************************************************/
|
||||
static
|
||||
void print_pnr_sdc_global_clock_ports(std::fstream& fp,
|
||||
const float& programming_critical_path_delay,
|
||||
const float& operating_critical_path_delay,
|
||||
const ModuleManager& module_manager,
|
||||
const ModuleId& top_module,
|
||||
const FabricGlobalPortInfo& fabric_global_port_info) {
|
||||
const FabricGlobalPortInfo& fabric_global_port_info,
|
||||
const SimulationSetting& sim_setting) {
|
||||
|
||||
valid_file_stream(fp);
|
||||
|
||||
|
@ -73,11 +72,11 @@ void print_pnr_sdc_global_clock_ports(std::fstream& fp,
|
|||
continue;
|
||||
}
|
||||
/* Reach here, it means a clock port and we need print constraints */
|
||||
float clock_period = operating_critical_path_delay;
|
||||
float clock_period = 1./sim_setting.default_operating_clock_frequency();
|
||||
|
||||
/* For programming clock, we give a fixed period */
|
||||
if (true == fabric_global_port_info.global_port_is_prog(global_port)) {
|
||||
clock_period = programming_critical_path_delay;
|
||||
clock_period = 1./sim_setting.programming_clock_frequency();
|
||||
/* Print comments */
|
||||
fp << "##################################################" << std::endl;
|
||||
fp << "# Create programmable clock " << std::endl;
|
||||
|
@ -93,6 +92,15 @@ void print_pnr_sdc_global_clock_ports(std::fstream& fp,
|
|||
for (const size_t& pin : clock_port.pins()) {
|
||||
BasicPort port_to_constrain(clock_port.get_name(), pin, pin);
|
||||
|
||||
/* 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()) {
|
||||
if (port_to_constrain == sim_setting.clock_port(sim_clock)) {
|
||||
clock_period = 1./sim_setting.clock_frequency(sim_clock);
|
||||
}
|
||||
}
|
||||
|
||||
print_pnr_sdc_clock_port(fp,
|
||||
port_to_constrain,
|
||||
clock_period);
|
||||
|
@ -153,11 +161,10 @@ void print_pnr_sdc_global_non_clock_ports(std::fstream& fp,
|
|||
* In general, we do not recommend to do this
|
||||
*******************************************************************/
|
||||
void print_pnr_sdc_global_ports(const std::string& sdc_dir,
|
||||
const float& programming_critical_path_delay,
|
||||
const float& operating_critical_path_delay,
|
||||
const ModuleManager& module_manager,
|
||||
const ModuleId& top_module,
|
||||
const FabricGlobalPortInfo& global_ports,
|
||||
const SimulationSetting& sim_setting,
|
||||
const bool& constrain_non_clock_port) {
|
||||
|
||||
/* Create the file name for Verilog netlist */
|
||||
|
@ -177,14 +184,12 @@ void print_pnr_sdc_global_ports(const std::string& sdc_dir,
|
|||
print_sdc_file_header(fp, std::string("Clock contraints for PnR"));
|
||||
|
||||
print_pnr_sdc_global_clock_ports(fp,
|
||||
programming_critical_path_delay,
|
||||
operating_critical_path_delay,
|
||||
module_manager, top_module,
|
||||
global_ports);
|
||||
global_ports, sim_setting);
|
||||
|
||||
if (true == constrain_non_clock_port) {
|
||||
print_pnr_sdc_global_non_clock_ports(fp,
|
||||
operating_critical_path_delay,
|
||||
1./sim_setting.default_operating_clock_frequency(),
|
||||
module_manager, top_module,
|
||||
global_ports);
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <vector>
|
||||
#include "module_manager.h"
|
||||
#include "fabric_global_port_info.h"
|
||||
#include "simulation_setting.h"
|
||||
|
||||
/********************************************************************
|
||||
* Function declaration
|
||||
|
@ -17,11 +18,10 @@
|
|||
namespace openfpga {
|
||||
|
||||
void print_pnr_sdc_global_ports(const std::string& sdc_dir,
|
||||
const float& programming_critical_path_delay,
|
||||
const float& operating_critical_path_delay,
|
||||
const ModuleManager& module_manager,
|
||||
const ModuleId& top_module,
|
||||
const FabricGlobalPortInfo& global_ports,
|
||||
const SimulationSetting& sim_setting,
|
||||
const bool& constrain_non_clock_port);
|
||||
|
||||
} /* end namespace openfpga */
|
||||
|
|
|
@ -319,8 +319,6 @@ void print_pnr_sdc_compact_routing_disable_switch_block_outputs(const std::strin
|
|||
* 4. Design constraints for breaking the combinational loops in FPGA fabric
|
||||
*******************************************************************/
|
||||
void print_pnr_sdc(const PnrSdcOption& sdc_options,
|
||||
const float& programming_critical_path_delay,
|
||||
const float& operating_critical_path_delay,
|
||||
const DeviceContext& device_ctx,
|
||||
const VprDeviceAnnotation& device_annotation,
|
||||
const DeviceRRGSB& device_rr_gsb,
|
||||
|
@ -328,6 +326,7 @@ void print_pnr_sdc(const PnrSdcOption& sdc_options,
|
|||
const MuxLibrary& mux_lib,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
const FabricGlobalPortInfo& global_ports,
|
||||
const SimulationSetting& sim_setting,
|
||||
const bool& compact_routing_hierarchy) {
|
||||
|
||||
std::string top_module_name = generate_fpga_top_module_name();
|
||||
|
@ -337,9 +336,8 @@ void print_pnr_sdc(const PnrSdcOption& sdc_options,
|
|||
/* Constrain global ports */
|
||||
if (true == sdc_options.constrain_global_port()) {
|
||||
print_pnr_sdc_global_ports(sdc_options.sdc_dir(),
|
||||
programming_critical_path_delay,
|
||||
operating_critical_path_delay,
|
||||
module_manager, top_module, global_ports,
|
||||
sim_setting,
|
||||
sdc_options.constrain_non_clock_global_port());
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "module_manager.h"
|
||||
#include "mux_library.h"
|
||||
#include "circuit_library.h"
|
||||
#include "simulation_setting.h"
|
||||
#include "fabric_global_port_info.h"
|
||||
#include "pnr_sdc_option.h"
|
||||
|
||||
|
@ -23,8 +24,6 @@
|
|||
namespace openfpga {
|
||||
|
||||
void print_pnr_sdc(const PnrSdcOption& sdc_options,
|
||||
const float& programming_critical_path_delay,
|
||||
const float& operating_critical_path_delay,
|
||||
const DeviceContext& device_ctx,
|
||||
const VprDeviceAnnotation& device_annotation,
|
||||
const DeviceRRGSB& device_rr_gsb,
|
||||
|
@ -32,6 +31,7 @@ void print_pnr_sdc(const PnrSdcOption& sdc_options,
|
|||
const MuxLibrary& mux_lib,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
const FabricGlobalPortInfo& global_ports,
|
||||
const SimulationSetting& sim_setting,
|
||||
const bool& compact_routing_hierarchy);
|
||||
|
||||
} /* end namespace openfpga */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -484,11 +484,23 @@ void print_verilog_testbench_clock_stimuli(std::fstream& fp,
|
|||
for (const BasicPort& clock_port : clock_ports) {
|
||||
print_verilog_comment(fp, std::string("----- Clock '") + clock_port.get_name() + std::string("' Initialization -------"));
|
||||
|
||||
/* Find the corresponding clock frequency from the simulation parameters */
|
||||
float clk_freq_to_use = (0.5 / simulation_parameters.default_operating_clock_frequency()) / VERILOG_SIM_TIMESCALE;
|
||||
/* FIXME: This could be buggy because the implementation clock names do NOT have to
|
||||
* be the same as the clock definition in simulation settings!!!
|
||||
*/
|
||||
for (const SimulationClockId& sim_clock_id : simulation_parameters.clocks()) {
|
||||
/* If the clock name matches, we can use the clock frequency */
|
||||
if (simulation_parameters.clock_port(sim_clock_id) == clock_port) {
|
||||
clk_freq_to_use = (0.5 / simulation_parameters.clock_frequency(sim_clock_id)) / VERILOG_SIM_TIMESCALE;
|
||||
}
|
||||
}
|
||||
|
||||
fp << "\tinitial begin" << std::endl;
|
||||
/* 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) << clk_freq_to_use << std::endl;
|
||||
fp << "\t\t\t" << generate_verilog_port(VERILOG_PORT_CONKT, clock_port);
|
||||
fp << " <= !";
|
||||
fp << generate_verilog_port(VERILOG_PORT_CONKT, clock_port);
|
||||
|
|
|
@ -56,12 +56,24 @@ constexpr char* TOP_TB_PROG_RESET_PORT_NAME = "prog_reset";
|
|||
constexpr char* TOP_TB_PROG_SET_PORT_NAME = "prog_set";
|
||||
constexpr char* TOP_TB_CONFIG_DONE_PORT_NAME = "config_done";
|
||||
constexpr char* TOP_TB_OP_CLOCK_PORT_NAME = "op_clock";
|
||||
constexpr char* TOP_TB_OP_CLOCK_PORT_PREFIX = "operating_clk_";
|
||||
constexpr char* TOP_TB_PROG_CLOCK_PORT_NAME = "prog_clock";
|
||||
constexpr char* TOP_TB_INOUT_REG_POSTFIX = "_reg";
|
||||
constexpr char* TOP_TB_CLOCK_REG_POSTFIX = "_reg";
|
||||
|
||||
constexpr char* AUTOCHECK_TOP_TESTBENCH_VERILOG_MODULE_POSTFIX = "_autocheck_top_tb";
|
||||
|
||||
/********************************************************************
|
||||
* Generate a simulation clock port name
|
||||
* This function is designed to produce a uniform clock naming for these ports
|
||||
*******************************************************************/
|
||||
static
|
||||
std::string generate_top_testbench_clock_name(const std::string& prefix,
|
||||
const std::string& port_name) {
|
||||
return prefix + port_name;
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* Print local wires for flatten memory (standalone) configuration protocols
|
||||
*******************************************************************/
|
||||
|
@ -253,6 +265,7 @@ void print_verilog_top_testbench_global_ports_stimuli(std::fstream& fp,
|
|||
const ModuleManager& module_manager,
|
||||
const ModuleId& top_module,
|
||||
const FabricGlobalPortInfo& fabric_global_port_info,
|
||||
const SimulationSetting& simulation_parameters,
|
||||
const bool& active_global_prog_reset,
|
||||
const bool& active_global_prog_set) {
|
||||
/* Validate the file stream */
|
||||
|
@ -290,10 +303,15 @@ void print_verilog_top_testbench_global_ports_stimuli(std::fstream& fp,
|
|||
*/
|
||||
for (const size_t& pin : module_manager.module_port(top_module, module_global_port).pins()) {
|
||||
BasicPort global_port_to_connect(module_manager.module_port(top_module, module_global_port).get_name(), pin, pin);
|
||||
/* TODO: This is a temporary fix to make the testbench generator run in multi-clock scenario
|
||||
* Need to consider multiple clock sources to connect
|
||||
* each of which may operate in different ferquency!!!
|
||||
/* 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()) {
|
||||
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)));
|
||||
}
|
||||
}
|
||||
|
||||
print_verilog_wire_connection(fp, global_port_to_connect,
|
||||
stimuli_clock_port,
|
||||
1 == fabric_global_port_info.global_port_default_value(fabric_global_port));
|
||||
|
@ -488,6 +506,7 @@ void print_verilog_top_testbench_ports(std::fstream& fp,
|
|||
const AtomContext& atom_ctx,
|
||||
const VprNetlistAnnotation& netlist_annotation,
|
||||
const std::vector<std::string>& clock_port_names,
|
||||
const SimulationSetting& simulation_parameters,
|
||||
const ConfigProtocol& config_protocol,
|
||||
const std::string& circuit_name){
|
||||
/* Validate the file stream */
|
||||
|
@ -543,7 +562,21 @@ void print_verilog_top_testbench_ports(std::fstream& fp,
|
|||
BasicPort prog_clock_register_port(std::string(std::string(TOP_TB_PROG_CLOCK_PORT_NAME) + std::string(TOP_TB_CLOCK_REG_POSTFIX)), 1);
|
||||
fp << generate_verilog_port(VERILOG_PORT_REG, prog_clock_register_port) << ";" << std::endl;
|
||||
|
||||
/* Operating clock */
|
||||
/* Multiple operating clocks based on the simulation settings */
|
||||
for (const SimulationClockId& sim_clock : simulation_parameters.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;
|
||||
BasicPort sim_clock_register_port(std::string(sim_clock_port_name + std::string(TOP_TB_CLOCK_REG_POSTFIX)), 1);
|
||||
fp << generate_verilog_port(VERILOG_PORT_REG, sim_clock_register_port) << ";" << std::endl;
|
||||
}
|
||||
|
||||
/* FIXME: Actually, for multi-clock implementations, input and output ports
|
||||
* should be synchronized by different clocks. Currently, we lack the information
|
||||
* about what inputs are driven by which clock. Therefore, we use a unified clock
|
||||
* signal to do the job. However, this has to be fixed later!!!
|
||||
* Create an operating clock_port to synchronize checkers stimulus generator
|
||||
*/
|
||||
BasicPort op_clock_port(std::string(TOP_TB_OP_CLOCK_PORT_NAME), 1);
|
||||
fp << generate_verilog_port(VERILOG_PORT_WIRE, op_clock_port) << ";" << std::endl;
|
||||
BasicPort op_clock_register_port(std::string(std::string(TOP_TB_OP_CLOCK_PORT_NAME) + std::string(TOP_TB_CLOCK_REG_POSTFIX)), 1);
|
||||
|
@ -969,6 +1002,7 @@ void print_verilog_top_testbench_load_bitstream_task(std::fstream& fp,
|
|||
*******************************************************************/
|
||||
static
|
||||
void print_verilog_top_testbench_generic_stimulus(std::fstream& fp,
|
||||
const SimulationSetting& simulation_parameters,
|
||||
const size_t& num_config_clock_cycles,
|
||||
const float& prog_clock_period,
|
||||
const float& op_clock_period,
|
||||
|
@ -1021,6 +1055,32 @@ 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()) {
|
||||
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);
|
||||
BasicPort sim_clock_register_port(std::string(sim_clock_port_name + std::string(TOP_TB_CLOCK_REG_POSTFIX)), 1);
|
||||
|
||||
float sim_clock_period = 1. / simulation_parameters.clock_frequency(sim_clock);
|
||||
print_verilog_clock_stimuli(fp, sim_clock_register_port,
|
||||
0, /* Initial value */
|
||||
0.5 * sim_clock_period / timescale,
|
||||
std::string("~" + reset_port.get_name()));
|
||||
print_verilog_comment(fp, "----- End raw operating clock signal generation -----");
|
||||
|
||||
/* Operation clock should be enabled after programming phase finishes.
|
||||
* Before configuration is done (config_done is enabled), operation clock should be always zero.
|
||||
*/
|
||||
print_verilog_comment(fp, std::string("----- Actual operating clock is triggered only when " + config_done_port.get_name() + " is enabled -----"));
|
||||
fp << "\tassign " << generate_verilog_port(VERILOG_PORT_CONKT, sim_clock_port);
|
||||
fp << " = " << generate_verilog_port(VERILOG_PORT_CONKT, sim_clock_register_port);
|
||||
fp << " & " << generate_verilog_port(VERILOG_PORT_CONKT, config_done_port);
|
||||
fp << ";" << std::endl;
|
||||
|
||||
fp << std::endl;
|
||||
}
|
||||
|
||||
/* Generate stimuli waveform for operating clock signals */
|
||||
print_verilog_comment(fp, "----- Begin raw operating clock signal generation -----");
|
||||
print_verilog_clock_stimuli(fp, op_clock_register_port,
|
||||
|
@ -1834,12 +1894,17 @@ void print_verilog_top_testbench(const ModuleManager& module_manager,
|
|||
/* Start of testbench */
|
||||
print_verilog_top_testbench_ports(fp, module_manager, top_module,
|
||||
atom_ctx, netlist_annotation, clock_port_names,
|
||||
config_protocol,
|
||||
simulation_parameters, config_protocol,
|
||||
circuit_name);
|
||||
|
||||
/* 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 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()) {
|
||||
max_op_clock_period = std::max(max_op_clock_period, (float)(1./simulation_parameters.clock_frequency(clock_id)));
|
||||
}
|
||||
|
||||
/* Estimate the number of configuration clock cycles */
|
||||
size_t num_config_clock_cycles = calculate_num_config_clock_cycles(config_protocol.type(),
|
||||
apply_fast_configuration,
|
||||
|
@ -1849,9 +1914,10 @@ void print_verilog_top_testbench(const ModuleManager& module_manager,
|
|||
|
||||
/* Generate stimuli for general control signals */
|
||||
print_verilog_top_testbench_generic_stimulus(fp,
|
||||
simulation_parameters,
|
||||
num_config_clock_cycles,
|
||||
prog_clock_period,
|
||||
op_clock_period,
|
||||
default_op_clock_period,
|
||||
VERILOG_SIM_TIMESCALE);
|
||||
|
||||
/* Generate stimuli for programming interface */
|
||||
|
@ -1891,6 +1957,7 @@ void print_verilog_top_testbench(const ModuleManager& module_manager,
|
|||
print_verilog_top_testbench_global_ports_stimuli(fp,
|
||||
module_manager, top_module,
|
||||
global_ports,
|
||||
simulation_parameters,
|
||||
active_global_prog_reset,
|
||||
active_global_prog_set);
|
||||
|
||||
|
@ -1968,7 +2035,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:
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
<!-- 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>
|
||||
<!-- The frequency defined in the operating line will be
|
||||
the default operating clock frequency for all the clocks
|
||||
define specific frequency using <clock> line will overwrite the default value
|
||||
Note that
|
||||
- clock name must be unique as it is used in testbench genertion
|
||||
- the clock port must match clock port definition in OpenFPGA architecture XML!!!
|
||||
-->
|
||||
<operating frequency="50e6" num_cycles="20" slack="0.2">
|
||||
<clock name="clk_10MHz" port="clk[0:0]" frequency="10e6"/>
|
||||
<clock name="clk_20MHz" port="clk[1:1]" frequency="20e6"/>
|
||||
<clock name="clk_30MHz" port="clk[2:2]" frequency="30e6"/>
|
||||
<clock name="clk_40MHz" port="clk[3:3]" frequency="40e6"/>
|
||||
</operating>
|
||||
<programming frequency="100e6"/>
|
||||
</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>
|
|
@ -24,7 +24,7 @@ fpga_flow=vpr_blif
|
|||
[OpenFPGA_SHELL]
|
||||
openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/global_tile_clock_example_script.openfpga
|
||||
openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_GlobalTile4Clk_cc_openfpga.xml
|
||||
openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml
|
||||
openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/fixed_4clock_sim_openfpga.xml
|
||||
|
||||
[ARCHITECTURES]
|
||||
arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_GlobalTile4Clk_40nm.xml
|
||||
|
|
Loading…
Reference in New Issue