Merge pull request #72 from LNIS-Projects/dev
Fabric Bitstream file writer
This commit is contained in:
commit
03dc0ee7ce
|
@ -44,4 +44,7 @@ python3 openfpga_flow/scripts/run_fpga_task.py fixed_simulation_settings --debug
|
|||
echo -e "Testing SDC generation with time units";
|
||||
python3 openfpga_flow/scripts/run_fpga_task.py sdc_time_unit --debug --show_thread_logs
|
||||
|
||||
echo -e "Testing FPGA-SPICE with netlist generation";
|
||||
python3 openfpga_flow/scripts/run_fpga_task.py generate_spice --debug --show_thread_logs
|
||||
|
||||
end_section "OpenFPGA.TaskTun"
|
||||
|
|
|
@ -78,6 +78,9 @@ python3 openfpga_flow/scripts/run_fpga_task.py fabric_key/load_external_key --de
|
|||
echo -e "Testing Power-gating designs";
|
||||
python3 openfpga_flow/scripts/run_fpga_task.py power_gated_design/power_gated_inverter --show_thread_logs --debug
|
||||
|
||||
echo -e "Testing Depopulated crossbar in local routing";
|
||||
python3 openfpga_flow/scripts/run_fpga_task.py depopulate_crossbar --debug --show_thread_logs
|
||||
|
||||
# Verify MCNC big20 benchmark suite with ModelSim
|
||||
# Please make sure you have ModelSim installed in the environment
|
||||
# Otherwise, it will fail
|
||||
|
|
|
@ -13,8 +13,8 @@ General organization is as follows.
|
|||
<device_model name="<string>" type="<string>">
|
||||
<lib type="<string>" corner="<string>" ref="<string>" path="<string>"/>
|
||||
<design vdd="<float>" pn_ratio="<float>"/>
|
||||
<pmos name="<string>" chan_length="<float>" min_width="<float>" variation="<string>"/>
|
||||
<nmos name="<string>" chan_length="<float>" min_width="<float>" variation="<string>"/>
|
||||
<pmos name="<string>" chan_length="<float>" min_width="<float>" max_width="<float>" variation="<string>"/>
|
||||
<nmos name="<string>" chan_length="<float>" min_width="<float>" max_width="<float>" variation="<string>"/>
|
||||
<rram rlrs="<float>" rhrs="<float>" variation="<string>"/>
|
||||
</device_model>
|
||||
</device_library>
|
||||
|
@ -71,15 +71,19 @@ A device model represents a transistor/RRAM model available in users' technology
|
|||
|
||||
- ``pn_ratio="<float>"`` specify the ratio between *p*-type and *n*-type transistors. The ratio will be used when building circuit structures such as inverters, buffers, etc.
|
||||
|
||||
.. option:: <pmos|nmos name="<string>" chan_length="<float>" min_width="<float>" variation="<string>"/>
|
||||
.. option:: <pmos|nmos name="<string>" chan_length="<float>" min_width="<float>" max_width="<float>" variation="<string>"/>
|
||||
|
||||
Specify device-level parameters for transistors
|
||||
|
||||
- ``name="<string>"`` specify the name of the p/n type transistor, which can be found in the manual of the technology provider.
|
||||
|
||||
- ``chan_length="<float>"`` specify the channel length of *p/n* type transistor.
|
||||
- ``chan_length="<float>"`` specify the channel length of a *p/n* type transistor.
|
||||
|
||||
- ``min_width="<float>"`` specify the minimum width of *p/n* type transistor. This parameter will be used in building inverter, buffer, *etc*. as a base number for transistor sizing.
|
||||
- ``min_width="<float>"`` specify the minimum width of a *p/n* type transistor. This parameter will be used in building inverter, buffer, *etc*. as a base number for transistor sizing.
|
||||
|
||||
- ``max_width="<float>"`` specify the maximum width of a *p/n* type transistor. This parameter will be used in building inverter, buffer, *etc*. as a base number for transistor sizing. If the required transistor width exceeds the maximum width, multiple transistors will be instanciated. Note that for FinFET technology, your ``max_width`` should be the same as your ``min_width``.
|
||||
|
||||
.. note:: The ``max_width`` is optional. By default, it will be set to be same as the ``min_width``.
|
||||
|
||||
- ``variation="<string>"`` specify the variation name defined in the ``<variation_library>``
|
||||
|
||||
|
|
|
@ -1,7 +1,131 @@
|
|||
Fabric-dependent Bitstream
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Usage
|
||||
`````
|
||||
|
||||
Fabric-dependent bitstream is design to be loadable to the configuration protocols of FPGAs.
|
||||
The bitstream just sets an order to the configuration bits in the database, without duplicating the database.
|
||||
OpenFPGA framework provides a fabric-dependent bitstream generator which is aligned to our Verilog netlists.
|
||||
The fabric-dependent bitstream can be found in autogenerated Verilog testbenches.
|
||||
The fabric-dependent bitstream can be found in the pre-configured Verilog testbenches.
|
||||
The fabric bitsteam can be outputted in different file format in terms of usage.
|
||||
|
||||
Plain Text File Format
|
||||
```````````````````````
|
||||
|
||||
This file format is designed to be directly loaded to an FPGA fabric.
|
||||
It does not include any comments but only bitstream.
|
||||
|
||||
The information depends on the type of configuration procotol.
|
||||
|
||||
.. option:: vanilla
|
||||
|
||||
A line consisting of ``0`` | ``1``
|
||||
|
||||
.. option:: scan_chain
|
||||
|
||||
A line consisting of ``0`` | ``1``
|
||||
|
||||
.. option:: memory_bank
|
||||
|
||||
Multiple lines will be included, each of which is organized as <address><space><bit>.
|
||||
Note that due to the use of Bit-Line and Word-Line decoders, every two lines are paired.
|
||||
The first line represents the Bit-Line address and configuration bit.
|
||||
The second line represents the Word-Line address and configuration bit.
|
||||
For example
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<bitline_address> <bit_value>
|
||||
<wordline_address> <bit_value>
|
||||
<bitline_address> <bit_value>
|
||||
<wordline_address> <bit_value>
|
||||
...
|
||||
<bitline_address> <bit_value>
|
||||
<wordline_address> <bit_value>
|
||||
|
||||
.. option:: frame_based
|
||||
|
||||
Multiple lines will be included, each of which is organized as <address><space><bit>.
|
||||
For example
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<frame_address> <bit_value>
|
||||
<frame_address> <bit_value>
|
||||
...
|
||||
<frame_address> <bit_value>
|
||||
|
||||
XML File Format
|
||||
```````````````
|
||||
|
||||
This file format is designed to generate testbenches using external tools, e.g., CocoTB.
|
||||
|
||||
In principle, the file consist a number of XML node ``<bit>``, each bit contains the following attributes:
|
||||
|
||||
- ``id``: The unique id of the configuration bit in the fabric bitstream.
|
||||
|
||||
- ``value``: The configuration bit value.
|
||||
|
||||
- ``hierarchy`` represents the location of this block in FPGA fabric.
|
||||
The hierachy includes the full hierarchy of this block
|
||||
|
||||
- ``instance`` denotes the instance name which you can find in the fabric netlists
|
||||
|
||||
- ``level`` denotes the depth of the block in the hierarchy
|
||||
|
||||
A quick example:
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<bit id="0" value="1">
|
||||
<hierarchy>
|
||||
<instance level="0" name="fpga_top"/>
|
||||
<instance level="1" name="grid_clb_1__2_"/>
|
||||
<instance level="2" name="logical_tile_clb_mode_clb__0"/>
|
||||
<instance level="3" name="mem_fle_9_in_5"/>
|
||||
</hierarchy>
|
||||
</bit>
|
||||
|
||||
Other information may depend on the type of configuration procotol.
|
||||
|
||||
.. option:: memory_bank
|
||||
|
||||
- ``bl``: Bit line address information
|
||||
|
||||
- ``wl``: Word line address information
|
||||
|
||||
A quick example:
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<bit id="0" value="1">
|
||||
<hierarchy>
|
||||
<instance level="0" name="fpga_top"/>
|
||||
<instance level="1" name="grid_io_bottom_1__0_"/>
|
||||
<instance level="2" name="logical_tile_io_mode_io__0"/>
|
||||
<instance level="3" name="logical_tile_io_mode_physical__iopad_0"/>
|
||||
<instance level="4" name="iopad_sram_blwl_mem"/>
|
||||
</hierarchy>
|
||||
<bl address="000000"/>
|
||||
<wl address="000000"/>
|
||||
</bit>
|
||||
|
||||
.. option:: frame_based
|
||||
|
||||
- ``frame``: frame address information
|
||||
|
||||
A quick example:
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<bit id="0" value="1">
|
||||
<hierarchy>
|
||||
<instance level="0" name="fpga_top"/>
|
||||
<instance level="1" name="grid_io_bottom_1__0_"/>
|
||||
<instance level="2" name="logical_tile_io_mode_io__0"/>
|
||||
<instance level="3" name="logical_tile_io_mode_physical__iopad_0"/>
|
||||
<instance level="4" name="iopad_config_latch_mem"/>
|
||||
</hierarchy>
|
||||
<frame address="0000000000000000"/>
|
||||
</bit>
|
||||
|
|
|
@ -30,4 +30,6 @@ build_fabric_bitstream
|
|||
|
||||
- ``--file`` or ``-f`` Output the fabric bitstream to an plain text file (only 0 or 1)
|
||||
|
||||
- ``--format`` Specify the file format [``plain_text``|``xml``]. By default is ``plain_text``.
|
||||
|
||||
- ``--verbose`` Show verbose log
|
||||
|
|
|
@ -109,6 +109,10 @@ build_fabric
|
|||
|
||||
- ``--write_fabric_key <xml_file>`` Output current fabric key to an XML file
|
||||
|
||||
- ``--frame_view`` Create only frame views of the module graph. When enabled, top-level module will not include any nets. This option is made for save runtime and memory.
|
||||
|
||||
.. warning:: Recommend to turn the option on when bitstream generation is the only purpose of the flow. Do not use it when you need generate netlists!
|
||||
|
||||
- ``--verbose`` Show verbose log
|
||||
|
||||
.. note:: This is a must-run command before launching FPGA-Verilog, FPGA-Bitstream, FPGA-SDC and FPGA-SPICE
|
||||
|
|
|
@ -122,6 +122,14 @@ void read_xml_device_transistor(pugi::xml_node& xml_device_transistor,
|
|||
tech_lib.set_transistor_model_min_width(device_model, transistor_type,
|
||||
get_attribute(xml_device_transistor, "min_width", loc_data).as_float(0.));
|
||||
|
||||
/* Parse the transistor maximum width, by default we consider the same as minimum width */
|
||||
tech_lib.set_transistor_model_max_width(device_model, transistor_type,
|
||||
get_attribute(xml_device_transistor, "max_width", loc_data, pugiutil::ReqOpt::OPTIONAL).as_float(0.));
|
||||
/* If the max_width is default value, we set it to be the same as min_width */
|
||||
if (0. == tech_lib.transistor_model_max_width(device_model, transistor_type)) {
|
||||
tech_lib.set_transistor_model_max_width(device_model, transistor_type, tech_lib.transistor_model_min_width(device_model, transistor_type));
|
||||
}
|
||||
|
||||
/* Parse the transistor variation name */
|
||||
tech_lib.set_transistor_model_variation_name(device_model, transistor_type,
|
||||
get_attribute(xml_device_transistor, "variation", loc_data).as_string());
|
||||
|
|
|
@ -157,6 +157,18 @@ float TechnologyLibrary::transistor_model_min_width(const TechnologyModelId& mod
|
|||
return transistor_model_min_widths_[model_id][transistor_type];
|
||||
}
|
||||
|
||||
/* Access the maximum width of a transistor (either PMOS or NMOS) for a technology model
|
||||
* Note: This is ONLY applicable to transistor model
|
||||
*/
|
||||
float TechnologyLibrary::transistor_model_max_width(const TechnologyModelId& model_id,
|
||||
const e_tech_lib_transistor_type& transistor_type) const {
|
||||
/* validate the model_id */
|
||||
VTR_ASSERT(valid_model_id(model_id));
|
||||
/* This is only applicable to transistor model */
|
||||
VTR_ASSERT(TECH_LIB_MODEL_TRANSISTOR == model_type(model_id));
|
||||
return transistor_model_max_widths_[model_id][transistor_type];
|
||||
}
|
||||
|
||||
/* Access the minimum width of a transistor (either PMOS or NMOS) for a technology model
|
||||
* Note: This is ONLY applicable to transistor model
|
||||
*/
|
||||
|
@ -270,6 +282,7 @@ TechnologyModelId TechnologyLibrary::add_model(const std::string& name) {
|
|||
transistor_model_names_.emplace_back();
|
||||
transistor_model_chan_lengths_.emplace_back();
|
||||
transistor_model_min_widths_.emplace_back();
|
||||
transistor_model_max_widths_.emplace_back();
|
||||
transistor_model_variation_names_.emplace_back();
|
||||
transistor_model_variation_ids_.push_back(std::array<TechnologyVariationId, 2>{TechnologyVariationId::INVALID(), TechnologyVariationId::INVALID()});
|
||||
|
||||
|
@ -394,6 +407,19 @@ void TechnologyLibrary::set_transistor_model_min_width(const TechnologyModelId&
|
|||
return;
|
||||
}
|
||||
|
||||
/* Set the maximum width for either PMOS or NMOS of a model in the library
|
||||
* This is ONLY applicable to transistors
|
||||
*/
|
||||
void TechnologyLibrary::set_transistor_model_max_width(const TechnologyModelId& model_id,
|
||||
const e_tech_lib_transistor_type& transistor_type,
|
||||
const float& max_width) {
|
||||
/* validate the model_id */
|
||||
VTR_ASSERT(valid_model_id(model_id));
|
||||
VTR_ASSERT(TECH_LIB_MODEL_TRANSISTOR == model_type(model_id));
|
||||
transistor_model_max_widths_[model_id][transistor_type] = max_width;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set the variation name for either PMOS or NMOS of a model in the library
|
||||
* This is ONLY applicable to transistors
|
||||
*/
|
||||
|
|
|
@ -101,6 +101,8 @@ class TechnologyLibrary {
|
|||
const e_tech_lib_transistor_type& transistor_type) const;
|
||||
float transistor_model_min_width(const TechnologyModelId& model_id,
|
||||
const e_tech_lib_transistor_type& transistor_type) const;
|
||||
float transistor_model_max_width(const TechnologyModelId& model_id,
|
||||
const e_tech_lib_transistor_type& transistor_type) const;
|
||||
TechnologyVariationId transistor_model_variation(const TechnologyModelId& model_id,
|
||||
const e_tech_lib_transistor_type& transistor_type) const;
|
||||
public: /* Public Accessors: Basic data query on RRAM models */
|
||||
|
@ -138,6 +140,9 @@ class TechnologyLibrary {
|
|||
void set_transistor_model_min_width(const TechnologyModelId& model_id,
|
||||
const e_tech_lib_transistor_type& transistor_type,
|
||||
const float& min_width);
|
||||
void set_transistor_model_max_width(const TechnologyModelId& model_id,
|
||||
const e_tech_lib_transistor_type& transistor_type,
|
||||
const float& max_width);
|
||||
void set_transistor_model_variation_name(const TechnologyModelId& model_id,
|
||||
const e_tech_lib_transistor_type& transistor_type,
|
||||
const std::string& variation_name);
|
||||
|
@ -231,6 +236,15 @@ class TechnologyLibrary {
|
|||
*/
|
||||
vtr::vector<TechnologyModelId, std::array<float, 2>> transistor_model_min_widths_;
|
||||
|
||||
/* The maximum width of a transistor.
|
||||
* This should be defined by your technology vendor
|
||||
* The maximum width of a transistor will be used to size your transistors
|
||||
* If the required width in circuit models in larger then the max width,
|
||||
* multiple transistor bin will be instanciated.
|
||||
* For FinFET, the maximum width should be the same as min_width
|
||||
*/
|
||||
vtr::vector<TechnologyModelId, std::array<float, 2>> transistor_model_max_widths_;
|
||||
|
||||
/* The variation name and id binded to PMOS and NMOS transistor
|
||||
* We expect users to provide the exact name of variation defined in this technology library
|
||||
* the name and id will be automatically matched by using function link_model_to_variation()
|
||||
|
|
|
@ -92,6 +92,25 @@ void write_xml_design_technology(std::fstream& fp,
|
|||
fp << "/>" << "\n";
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* A writer to output the device technology of a circuit model to XML format
|
||||
*******************************************************************/
|
||||
static
|
||||
void write_xml_device_technology(std::fstream& fp,
|
||||
const char* fname,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
const CircuitModelId& model) {
|
||||
/* Validate the file stream */
|
||||
openfpga::check_file_stream(fname, fp);
|
||||
|
||||
if (!circuit_lib.device_model_name(model).empty()) {
|
||||
fp << "\t\t\t" << "<device_technology";
|
||||
write_xml_attribute(fp, "device_model_name", circuit_lib.device_model_name(model).c_str());
|
||||
/* Finish all the attributes, we can return here */
|
||||
fp << "/>" << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* A writer to output a circuit port to XML format
|
||||
*******************************************************************/
|
||||
|
@ -401,6 +420,9 @@ void write_xml_circuit_model(std::fstream& fp,
|
|||
/* Write the design technology of circuit model */
|
||||
write_xml_design_technology(fp, fname, circuit_lib, model);
|
||||
|
||||
/* Write the device technology of circuit model */
|
||||
write_xml_device_technology(fp, fname, circuit_lib, model);
|
||||
|
||||
/* Write the input buffer information of circuit model,
|
||||
* only applicable when this circuit model is neither inverter nor buffer
|
||||
*/
|
||||
|
|
|
@ -60,6 +60,7 @@ void write_xml_device_model(std::fstream& fp,
|
|||
write_xml_attribute(fp, "name", tech_lib.transistor_model_name(device_model, TECH_LIB_TRANSISTOR_PMOS).c_str());
|
||||
write_xml_attribute(fp, "chan_length", tech_lib.transistor_model_chan_length(device_model, TECH_LIB_TRANSISTOR_PMOS));
|
||||
write_xml_attribute(fp, "min_width", tech_lib.transistor_model_min_width(device_model, TECH_LIB_TRANSISTOR_PMOS));
|
||||
write_xml_attribute(fp, "max_width", tech_lib.transistor_model_max_width(device_model, TECH_LIB_TRANSISTOR_PMOS));
|
||||
if (TechnologyVariationId::INVALID() != tech_lib.transistor_model_variation(device_model, TECH_LIB_TRANSISTOR_PMOS)) {
|
||||
write_xml_attribute(fp, "variation", tech_lib.variation_name(tech_lib.transistor_model_variation(device_model, TECH_LIB_TRANSISTOR_PMOS)).c_str());
|
||||
}
|
||||
|
|
|
@ -52,6 +52,13 @@ bool BitstreamManager::bit_value(const ConfigBitId& bit_id) const {
|
|||
return '1' == bit_values_[bit_id];
|
||||
}
|
||||
|
||||
ConfigBlockId BitstreamManager::bit_parent_block(const ConfigBitId& bit_id) const {
|
||||
/* Ensure a valid id */
|
||||
VTR_ASSERT(true == valid_bit_id(bit_id));
|
||||
|
||||
return bit_parent_blocks_[bit_id];
|
||||
}
|
||||
|
||||
std::string BitstreamManager::block_name(const ConfigBlockId& block_id) const {
|
||||
/* Ensure the input ids are valid */
|
||||
VTR_ASSERT(true == valid_block_id(block_id));
|
||||
|
@ -140,7 +147,7 @@ std::string BitstreamManager::block_output_net_ids(const ConfigBlockId& block_id
|
|||
/******************************************************************************
|
||||
* Public Mutators
|
||||
******************************************************************************/
|
||||
ConfigBitId BitstreamManager::add_bit(const bool& bit_value) {
|
||||
ConfigBitId BitstreamManager::add_bit(const ConfigBlockId& parent_block, const bool& bit_value) {
|
||||
ConfigBitId bit = ConfigBitId(num_bits_);
|
||||
/* Add a new bit, and allocate associated data structures */
|
||||
num_bits_++;
|
||||
|
@ -150,6 +157,8 @@ ConfigBitId BitstreamManager::add_bit(const bool& bit_value) {
|
|||
bit_values_.push_back('0');
|
||||
}
|
||||
|
||||
bit_parent_blocks_.push_back(parent_block);
|
||||
|
||||
return bit;
|
||||
}
|
||||
|
||||
|
@ -234,7 +243,7 @@ void BitstreamManager::add_block_bits(const ConfigBlockId& block,
|
|||
block_bit_id_lsbs_[block] = num_bits_;
|
||||
block_bit_lengths_[block] = block_bitstream.size();
|
||||
for (const bool& bit : block_bitstream) {
|
||||
add_bit(bit);
|
||||
add_bit(block, bit);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -119,6 +119,9 @@ class BitstreamManager {
|
|||
/* Find the value of bitstream */
|
||||
bool bit_value(const ConfigBitId& bit_id) const;
|
||||
|
||||
/* Find the parent block of a configuration bit */
|
||||
ConfigBlockId bit_parent_block(const ConfigBitId& bit_id) const;
|
||||
|
||||
/* Find a name of a block */
|
||||
std::string block_name(const ConfigBlockId& block_id) const;
|
||||
|
||||
|
@ -145,7 +148,7 @@ class BitstreamManager {
|
|||
|
||||
public: /* Public Mutators */
|
||||
/* Add a new configuration bit to the bitstream manager */
|
||||
ConfigBitId add_bit(const bool& bit_value);
|
||||
ConfigBitId add_bit(const ConfigBlockId& parent_block, const bool& bit_value);
|
||||
|
||||
/* Reserve memory for a number of clocks */
|
||||
void reserve_blocks(const size_t& num_blocks);
|
||||
|
@ -235,6 +238,7 @@ class BitstreamManager {
|
|||
std::unordered_set<ConfigBitId> invalid_bit_ids_;
|
||||
/* value of a bit in the Bitstream */
|
||||
vtr::vector<ConfigBitId, char> bit_values_;
|
||||
vtr::vector<ConfigBitId, ConfigBlockId> bit_parent_blocks_;
|
||||
};
|
||||
|
||||
} /* end namespace openfpga */
|
||||
|
|
|
@ -16,7 +16,8 @@
|
|||
#include "write_xml_arch_bitstream.h"
|
||||
|
||||
#include "build_device_bitstream.h"
|
||||
#include "fabric_bitstream_writer.h"
|
||||
#include "write_text_fabric_bitstream.h"
|
||||
#include "write_xml_fabric_bitstream.h"
|
||||
#include "build_fabric_bitstream.h"
|
||||
#include "openfpga_bitstream.h"
|
||||
|
||||
|
@ -66,6 +67,7 @@ int build_fabric_bitstream(OpenfpgaContext& openfpga_ctx,
|
|||
|
||||
CommandOptionId opt_verbose = cmd.option("verbose");
|
||||
CommandOptionId opt_file = cmd.option("file");
|
||||
CommandOptionId opt_file_format = cmd.option("format");
|
||||
|
||||
/* Build fabric bitstream here */
|
||||
openfpga_ctx.mutable_fabric_bitstream() = build_fabric_dependent_bitstream(openfpga_ctx.bitstream_manager(),
|
||||
|
@ -81,10 +83,24 @@ int build_fabric_bitstream(OpenfpgaContext& openfpga_ctx,
|
|||
/* Create directories */
|
||||
create_directory(src_dir_path);
|
||||
|
||||
status = write_fabric_bitstream_to_text_file(openfpga_ctx.bitstream_manager(),
|
||||
openfpga_ctx.fabric_bitstream(),
|
||||
openfpga_ctx.arch().config_protocol,
|
||||
cmd_context.option_value(cmd, opt_file));
|
||||
/* Check file format requirements */
|
||||
std::string file_format("plain_text");
|
||||
if (true == cmd_context.option_enable(cmd, opt_file_format)) {
|
||||
file_format = cmd_context.option_value(cmd, opt_file_format);
|
||||
}
|
||||
|
||||
if (std::string("xml") == file_format) {
|
||||
status = write_fabric_bitstream_to_xml_file(openfpga_ctx.bitstream_manager(),
|
||||
openfpga_ctx.fabric_bitstream(),
|
||||
openfpga_ctx.arch().config_protocol,
|
||||
cmd_context.option_value(cmd, opt_file));
|
||||
} else {
|
||||
/* By default, output in plain text format */
|
||||
status = write_fabric_bitstream_to_text_file(openfpga_ctx.bitstream_manager(),
|
||||
openfpga_ctx.fabric_bitstream(),
|
||||
openfpga_ctx.arch().config_protocol,
|
||||
cmd_context.option_value(cmd, opt_file));
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: should identify the error code from internal function execution */
|
||||
|
|
|
@ -85,6 +85,10 @@ ShellCommandId add_openfpga_fabric_bitstream_command(openfpga::Shell<OpenfpgaCon
|
|||
shell_cmd.set_option_short_name(opt_file, "f");
|
||||
shell_cmd.set_option_require_value(opt_file, openfpga::OPT_STRING);
|
||||
|
||||
/* Add an option '--file_format'*/
|
||||
CommandOptionId opt_file_format = shell_cmd.add_option("format", false, "file format of fabric bitstream [plain_text|xml]. Default: plain_text");
|
||||
shell_cmd.set_option_require_value(opt_file_format, openfpga::OPT_STRING);
|
||||
|
||||
/* Add an option '--verbose' */
|
||||
shell_cmd.add_option("verbose", false, "Enable verbose output");
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/********************************************************************
|
||||
* This file includes functions that output a fabric-dependent
|
||||
* bitstream database to files in different formats
|
||||
* bitstream database to files in plain text
|
||||
*******************************************************************/
|
||||
#include <chrono>
|
||||
#include <ctime>
|
||||
|
@ -17,7 +17,7 @@
|
|||
#include "openfpga_naming.h"
|
||||
|
||||
#include "bitstream_manager_utils.h"
|
||||
#include "fabric_bitstream_writer.h"
|
||||
#include "write_text_fabric_bitstream.h"
|
||||
|
||||
/* begin namespace openfpga */
|
||||
namespace openfpga {
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef FABRIC_BITSTREAM_WRITER_H
|
||||
#define FABRIC_BITSTREAM_WRITER_H
|
||||
#ifndef WRITE_TEXT_FABRIC_BITSTREAM_H
|
||||
#define WRITE_TEXT_FABRIC_BITSTREAM_H
|
||||
|
||||
/********************************************************************
|
||||
* Include header files that are required by function declaration
|
|
@ -0,0 +1,194 @@
|
|||
/********************************************************************
|
||||
* This file includes functions that output a fabric-dependent
|
||||
* bitstream database to files in XML format
|
||||
*******************************************************************/
|
||||
#include <chrono>
|
||||
#include <ctime>
|
||||
#include <fstream>
|
||||
|
||||
/* Headers from vtrutil library */
|
||||
#include "vtr_assert.h"
|
||||
#include "vtr_log.h"
|
||||
#include "vtr_time.h"
|
||||
|
||||
/* Headers from openfpgautil library */
|
||||
#include "openfpga_digest.h"
|
||||
|
||||
/* Headers from archopenfpga library */
|
||||
|
||||
#include "openfpga_naming.h"
|
||||
|
||||
#include "bitstream_manager_utils.h"
|
||||
#include "write_xml_fabric_bitstream.h"
|
||||
|
||||
/* begin namespace openfpga */
|
||||
namespace openfpga {
|
||||
|
||||
/********************************************************************
|
||||
* This function write header information to a bitstream file
|
||||
*******************************************************************/
|
||||
static
|
||||
void write_fabric_bitstream_xml_file_head(std::fstream& fp) {
|
||||
valid_file_stream(fp);
|
||||
|
||||
auto end = std::chrono::system_clock::now();
|
||||
std::time_t end_time = std::chrono::system_clock::to_time_t(end);
|
||||
|
||||
fp << "<!--" << std::endl;
|
||||
fp << "\t- Fabric bitstream" << std::endl;
|
||||
fp << "\t- Author: Xifan TANG" << std::endl;
|
||||
fp << "\t- Organization: University of Utah" << std::endl;
|
||||
fp << "\t- Date: " << std::ctime(&end_time) ;
|
||||
fp << "-->" << std::endl;
|
||||
fp << std::endl;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Write a configuration bit into a plain text file
|
||||
* General format
|
||||
* <bit id="<fabric_bit>" value="<config_bit_value>">
|
||||
* <hierarchy>
|
||||
* <!-- configurable memory hierarchy -->
|
||||
* </hierarchy>
|
||||
* <!-- address information -->
|
||||
* ...
|
||||
* </bit>
|
||||
* The format depends on the type of configuration protocol
|
||||
* - Vanilla (standalone): No more information to be included
|
||||
* - Configuration chain: No more information to be included
|
||||
* - Memory bank :
|
||||
* <bl address="<bl_address_value>"/>
|
||||
* <wl address="<wl_address_value>"/>
|
||||
* - Frame-based configuration protocol :
|
||||
* <frame address="<frame_address_value>"/>
|
||||
*
|
||||
* Return:
|
||||
* - 0 if succeed
|
||||
* - 1 if critical errors occured
|
||||
*******************************************************************/
|
||||
static
|
||||
int write_fabric_config_bit_to_xml_file(std::fstream& fp,
|
||||
const BitstreamManager& bitstream_manager,
|
||||
const FabricBitstream& fabric_bitstream,
|
||||
const FabricBitId& fabric_bit,
|
||||
const e_config_protocol_type& config_type) {
|
||||
if (false == valid_file_stream(fp)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
fp << "<bit id=\"" << size_t(fabric_bit) << "\" ";
|
||||
fp << "value=\"";
|
||||
fp << bitstream_manager.bit_value(fabric_bitstream.config_bit(fabric_bit));
|
||||
fp << "\">\n";
|
||||
|
||||
/* Output hierarchy of this parent*/
|
||||
const ConfigBitId& config_bit = fabric_bitstream.config_bit(fabric_bit);
|
||||
const ConfigBlockId& config_block = bitstream_manager.bit_parent_block(config_bit);
|
||||
std::vector<ConfigBlockId> block_hierarchy = find_bitstream_manager_block_hierarchy(bitstream_manager, config_block);
|
||||
write_tab_to_file(fp, 1);
|
||||
fp << "<hierarchy>\n";
|
||||
size_t hierarchy_counter = 0;
|
||||
for (const ConfigBlockId& temp_block : block_hierarchy) {
|
||||
write_tab_to_file(fp, 2);
|
||||
fp << "<instance level=\"" << hierarchy_counter << "\"";
|
||||
fp << " name=\"" << bitstream_manager.block_name(temp_block) << "\"";
|
||||
fp << "/>\n";
|
||||
hierarchy_counter++;
|
||||
}
|
||||
write_tab_to_file(fp, 1);
|
||||
fp << "</hierarchy>\n";
|
||||
|
||||
switch (config_type) {
|
||||
case CONFIG_MEM_STANDALONE:
|
||||
case CONFIG_MEM_SCAN_CHAIN:
|
||||
break;
|
||||
case CONFIG_MEM_MEMORY_BANK: {
|
||||
/* Bit line address */
|
||||
write_tab_to_file(fp, 1);
|
||||
fp << "<bl address=\"";
|
||||
for (const char& addr_bit : fabric_bitstream.bit_bl_address(fabric_bit)) {
|
||||
fp << addr_bit;
|
||||
}
|
||||
fp << "\"/>\n";
|
||||
|
||||
write_tab_to_file(fp, 1);
|
||||
fp << "<wl address=\"";
|
||||
for (const char& addr_bit : fabric_bitstream.bit_wl_address(fabric_bit)) {
|
||||
fp << addr_bit;
|
||||
}
|
||||
fp << "\"/>\n";
|
||||
break;
|
||||
}
|
||||
case CONFIG_MEM_FRAME_BASED: {
|
||||
write_tab_to_file(fp, 1);
|
||||
fp << "<frame address=\"";
|
||||
for (const char& addr_bit : fabric_bitstream.bit_address(fabric_bit)) {
|
||||
fp << addr_bit;
|
||||
}
|
||||
fp << "\"/>\n";
|
||||
break;
|
||||
}
|
||||
default:
|
||||
VTR_LOGF_ERROR(__FILE__, __LINE__,
|
||||
"Invalid configuration protocol type!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
fp << "</bit>\n";
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Write the fabric bitstream to an XML file
|
||||
* Notes:
|
||||
* - This file is designed to be reused by testbench generators, e.g., CocoTB
|
||||
* - It can NOT be directly loaded to the FPGA fabric
|
||||
* - It include configurable memory paths in full hierarchy
|
||||
*
|
||||
* Return:
|
||||
* - 0 if succeed
|
||||
* - 1 if critical errors occured
|
||||
*******************************************************************/
|
||||
int write_fabric_bitstream_to_xml_file(const BitstreamManager& bitstream_manager,
|
||||
const FabricBitstream& fabric_bitstream,
|
||||
const ConfigProtocol& config_protocol,
|
||||
const std::string& fname) {
|
||||
/* Ensure that we have a valid file name */
|
||||
if (true == fname.empty()) {
|
||||
VTR_LOG_ERROR("Received empty file name to output bitstream!\n\tPlease specify a valid file name.\n");
|
||||
}
|
||||
|
||||
std::string timer_message = std::string("Write ") + std::to_string(fabric_bitstream.num_bits()) + std::string(" fabric bitstream into xml file '") + fname + std::string("'");
|
||||
vtr::ScopedStartFinishTimer timer(timer_message);
|
||||
|
||||
/* Create the file stream */
|
||||
std::fstream fp;
|
||||
fp.open(fname, std::fstream::out | std::fstream::trunc);
|
||||
|
||||
check_file_stream(fname.c_str(), fp);
|
||||
|
||||
/* Write XML head */
|
||||
write_fabric_bitstream_xml_file_head(fp);
|
||||
|
||||
/* Output fabric bitstream to the file */
|
||||
int status = 0;
|
||||
for (const FabricBitId& fabric_bit : fabric_bitstream.bits()) {
|
||||
status = write_fabric_config_bit_to_xml_file(fp, bitstream_manager,
|
||||
fabric_bitstream,
|
||||
fabric_bit,
|
||||
config_protocol.type());
|
||||
if (1 == status) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Print an end to the file here */
|
||||
fp << std::endl;
|
||||
|
||||
/* Close file handler */
|
||||
fp.close();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
} /* end namespace openfpga */
|
|
@ -0,0 +1,27 @@
|
|||
#ifndef WRITE_XML_FABRIC_BITSTREAM_H
|
||||
#define WRITE_XML_FABRIC_BITSTREAM_H
|
||||
|
||||
/********************************************************************
|
||||
* Include header files that are required by function declaration
|
||||
*******************************************************************/
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "bitstream_manager.h"
|
||||
#include "fabric_bitstream.h"
|
||||
#include "config_protocol.h"
|
||||
|
||||
/********************************************************************
|
||||
* Function declaration
|
||||
*******************************************************************/
|
||||
|
||||
/* begin namespace openfpga */
|
||||
namespace openfpga {
|
||||
|
||||
int write_fabric_bitstream_to_xml_file(const BitstreamManager& bitstream_manager,
|
||||
const FabricBitstream& fabric_bitstream,
|
||||
const ConfigProtocol& config_protocol,
|
||||
const std::string& fname);
|
||||
|
||||
} /* end namespace openfpga */
|
||||
|
||||
#endif
|
|
@ -5,6 +5,7 @@
|
|||
* logic gates etc.
|
||||
***********************************************/
|
||||
#include <fstream>
|
||||
#include <cmath>
|
||||
#include <iomanip>
|
||||
|
||||
/* Headers from vtrutil library */
|
||||
|
@ -26,9 +27,9 @@
|
|||
/* begin namespace openfpga */
|
||||
namespace openfpga {
|
||||
|
||||
/************************************************
|
||||
/********************************************************************
|
||||
* Print a SPICE model wrapper for a transistor model
|
||||
***********************************************/
|
||||
*******************************************************************/
|
||||
static
|
||||
int print_spice_transistor_model_wrapper(std::fstream& fp,
|
||||
const TechnologyLibrary& tech_lib,
|
||||
|
@ -69,9 +70,9 @@ int print_spice_transistor_model_wrapper(std::fstream& fp,
|
|||
return CMD_EXEC_SUCCESS;
|
||||
}
|
||||
|
||||
/************************************************
|
||||
/********************************************************************
|
||||
* Generate the SPICE netlist for transistors
|
||||
***********************************************/
|
||||
*******************************************************************/
|
||||
int print_spice_transistor_wrapper(NetlistManager& netlist_manager,
|
||||
const TechnologyLibrary& tech_lib,
|
||||
const std::string& submodule_dir) {
|
||||
|
@ -85,9 +86,11 @@ int print_spice_transistor_wrapper(NetlistManager& netlist_manager,
|
|||
check_file_stream(spice_fname.c_str(), fp);
|
||||
|
||||
/* Create file */
|
||||
VTR_LOG("Generating SPICE netlist '%s' for essential gates...",
|
||||
VTR_LOG("Generating SPICE netlist '%s' for transistors...",
|
||||
spice_fname.c_str());
|
||||
|
||||
print_spice_file_header(fp, std::string("Transistor wrappers"));
|
||||
|
||||
/* Iterate over the transistor models */
|
||||
for (const TechnologyModelId& model : tech_lib.models()) {
|
||||
/* Focus on transistor model */
|
||||
|
@ -113,9 +116,147 @@ int print_spice_transistor_wrapper(NetlistManager& netlist_manager,
|
|||
return CMD_EXEC_SUCCESS;
|
||||
}
|
||||
|
||||
/************************************************
|
||||
/********************************************************************
|
||||
* Generate the SPICE modeling for a power-gated inverter
|
||||
*
|
||||
* This function is created to be shared by inverter and buffer SPICE netlist writer
|
||||
*
|
||||
* Note:
|
||||
* - This function does NOT create a file
|
||||
* but requires a file stream created
|
||||
* - This function only output SPICE modeling for
|
||||
* an inverter. Any preprocessing or subckt definition should not be included!
|
||||
*******************************************************************/
|
||||
static
|
||||
int print_spice_powergated_inverter_pmos_modeling(std::fstream& fp,
|
||||
const std::string& trans_name_postfix,
|
||||
const std::string& input_port_name,
|
||||
const std::string& output_port_name,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
const CircuitPortId& enb_port,
|
||||
const TechnologyLibrary& tech_lib,
|
||||
const TechnologyModelId& tech_model,
|
||||
const float& trans_width) {
|
||||
|
||||
if (false == valid_file_stream(fp)) {
|
||||
return CMD_EXEC_FATAL_ERROR;
|
||||
}
|
||||
|
||||
/* Write power-gating transistor pairs using the technology model
|
||||
* Note that for a mulit-bit power gating port, we should cascade the transistors
|
||||
*/
|
||||
bool first_enb_pin = true;
|
||||
size_t last_enb_pin;
|
||||
for (const auto& power_gate_pin : circuit_lib.pins(enb_port)) {
|
||||
BasicPort enb_pin(circuit_lib.port_prefix(enb_port), power_gate_pin, power_gate_pin);
|
||||
fp << "Xpmos_powergate_" << trans_name_postfix << "_pin_" << power_gate_pin << " ";
|
||||
/* For the first pin, we should connect it to local VDD*/
|
||||
if (true == first_enb_pin) {
|
||||
fp << output_port_name << "_pmos_pg_" << power_gate_pin << " ";
|
||||
fp << generate_spice_port(enb_pin) << " ";
|
||||
fp << "LVDD ";
|
||||
fp << "LVDD ";
|
||||
first_enb_pin = false;
|
||||
} else {
|
||||
VTR_ASSERT_SAFE(false == first_enb_pin);
|
||||
fp << output_port_name << "_pmos_pg_" << last_enb_pin << " ";
|
||||
fp << generate_spice_port(enb_pin) << " ";
|
||||
fp << output_port_name << "_pmos_pg_" << power_gate_pin << " ";
|
||||
fp << "LVDD ";
|
||||
}
|
||||
fp << tech_lib.transistor_model_name(tech_model, TECH_LIB_TRANSISTOR_PMOS) << TRANSISTOR_WRAPPER_POSTFIX;
|
||||
fp << " W=" << std::setprecision(10) << trans_width;
|
||||
fp << "\n";
|
||||
|
||||
/* Cache the last pin*/
|
||||
last_enb_pin = power_gate_pin;
|
||||
}
|
||||
|
||||
/* Write transistor pairs using the technology model */
|
||||
fp << "Xpmos_" << trans_name_postfix << " ";
|
||||
fp << output_port_name << " ";
|
||||
fp << input_port_name << " ";
|
||||
fp << output_port_name << "_pmos_pg_" << circuit_lib.pins(enb_port).back() << " ";
|
||||
fp << "LVDD ";
|
||||
fp << tech_lib.transistor_model_name(tech_model, TECH_LIB_TRANSISTOR_PMOS) << TRANSISTOR_WRAPPER_POSTFIX;
|
||||
fp << " W=" << std::setprecision(10) << trans_width;
|
||||
fp << "\n";
|
||||
|
||||
return CMD_EXEC_SUCCESS;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Generate the SPICE modeling for the NMOS part of a power-gated inverter
|
||||
*
|
||||
* This function is created to be shared by inverter and buffer SPICE netlist writer
|
||||
*
|
||||
* Note:
|
||||
* - This function does NOT create a file
|
||||
* but requires a file stream created
|
||||
* - This function only output SPICE modeling for
|
||||
* an inverter. Any preprocessing or subckt definition should not be included!
|
||||
*******************************************************************/
|
||||
static
|
||||
int print_spice_powergated_inverter_nmos_modeling(std::fstream& fp,
|
||||
const std::string& trans_name_postfix,
|
||||
const std::string& input_port_name,
|
||||
const std::string& output_port_name,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
const CircuitPortId& en_port,
|
||||
const TechnologyLibrary& tech_lib,
|
||||
const TechnologyModelId& tech_model,
|
||||
const float& trans_width) {
|
||||
|
||||
if (false == valid_file_stream(fp)) {
|
||||
return CMD_EXEC_FATAL_ERROR;
|
||||
}
|
||||
|
||||
bool first_en_pin = true;
|
||||
size_t last_en_pin;
|
||||
for (const auto& power_gate_pin : circuit_lib.pins(en_port)) {
|
||||
BasicPort en_pin(circuit_lib.port_prefix(en_port), power_gate_pin, power_gate_pin);
|
||||
fp << "Xnmos_powergate_" << trans_name_postfix << "_pin_" << power_gate_pin << " ";
|
||||
/* For the first pin, we should connect it to local VDD*/
|
||||
if (true == first_en_pin) {
|
||||
fp << output_port_name << "_nmos_pg_" << power_gate_pin << " ";
|
||||
fp << generate_spice_port(en_pin) << " ";
|
||||
fp << "LGND ";
|
||||
fp << "LGND ";
|
||||
first_en_pin = false;
|
||||
} else {
|
||||
VTR_ASSERT_SAFE(false == first_en_pin);
|
||||
fp << output_port_name << "_nmos_pg_" << last_en_pin << " ";
|
||||
fp << circuit_lib.port_prefix(en_port) << " ";
|
||||
fp << output_port_name << "_nmos_pg_" << power_gate_pin << " ";
|
||||
fp << "LGND ";
|
||||
}
|
||||
fp << tech_lib.transistor_model_name(tech_model, TECH_LIB_TRANSISTOR_NMOS) << TRANSISTOR_WRAPPER_POSTFIX;
|
||||
fp << " W=" << std::setprecision(10) << trans_width;
|
||||
fp << "\n";
|
||||
|
||||
/* Cache the last pin*/
|
||||
last_en_pin = power_gate_pin;
|
||||
}
|
||||
|
||||
fp << "Xnmos_" << trans_name_postfix << " ";
|
||||
fp << output_port_name << " ";
|
||||
fp << input_port_name << " ";
|
||||
fp << output_port_name << " _nmos_pg_" << circuit_lib.pins(en_port).back() << " ";
|
||||
fp << "LGND ";
|
||||
fp << tech_lib.transistor_model_name(tech_model, TECH_LIB_TRANSISTOR_NMOS) << TRANSISTOR_WRAPPER_POSTFIX;
|
||||
fp << " W=" << std::setprecision(10) << trans_width;
|
||||
fp << "\n";
|
||||
|
||||
return CMD_EXEC_SUCCESS;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Generate the SPICE subckt for a power gated inverter
|
||||
* The Enable signal controlled the power gating
|
||||
*
|
||||
* Note:
|
||||
* - This function supports multi-bit power gating
|
||||
*
|
||||
* Schematic
|
||||
* LVDD
|
||||
* |
|
||||
|
@ -127,7 +268,9 @@ int print_spice_transistor_wrapper(NetlistManager& netlist_manager,
|
|||
* ENb[1] -o||
|
||||
* -
|
||||
* |
|
||||
* ...
|
||||
*
|
||||
* ... <More control signals if available in the port>
|
||||
*
|
||||
* |
|
||||
* -
|
||||
* +-o||
|
||||
|
@ -138,7 +281,9 @@ int print_spice_transistor_wrapper(NetlistManager& netlist_manager,
|
|||
* | -
|
||||
* +--||
|
||||
* -
|
||||
* ...
|
||||
*
|
||||
* ... <More control signals if available in the port>
|
||||
*
|
||||
* |
|
||||
* -
|
||||
* EN[1] -||
|
||||
|
@ -150,7 +295,7 @@ int print_spice_transistor_wrapper(NetlistManager& netlist_manager,
|
|||
* |
|
||||
* LGND
|
||||
*
|
||||
***********************************************/
|
||||
*******************************************************************/
|
||||
static
|
||||
int print_spice_powergated_inverter_subckt(std::fstream& fp,
|
||||
const ModuleManager& module_manager,
|
||||
|
@ -187,75 +332,68 @@ int print_spice_powergated_inverter_subckt(std::fstream& fp,
|
|||
VTR_ASSERT(true == circuit_lib.valid_circuit_port_id(en_port));
|
||||
VTR_ASSERT(true == circuit_lib.valid_circuit_port_id(enb_port));
|
||||
|
||||
/* TODO: may consider use size/bin to compact layout etc. */
|
||||
for (size_t i = 0; i < circuit_lib.buffer_size(circuit_model); ++i) {
|
||||
/* Write power-gating transistor pairs using the technology model
|
||||
* Note that for a mulit-bit power gating port, we should cascade the transistors
|
||||
*/
|
||||
bool first_enb_pin = true;
|
||||
size_t last_enb_pin;
|
||||
for (const auto& power_gate_pin : circuit_lib.pins(enb_port)) {
|
||||
BasicPort enb_pin(circuit_lib.port_prefix(enb_port), power_gate_pin, power_gate_pin);
|
||||
fp << "Xpmos_powergate_" << i << "_pin_" << power_gate_pin << " ";
|
||||
/* For the first pin, we should connect it to local VDD*/
|
||||
if (true == first_enb_pin) {
|
||||
fp << circuit_lib.port_prefix(output_ports[0]) << "_pmos_pg_" << power_gate_pin << " ";
|
||||
fp << generate_spice_port(enb_pin) << " ";
|
||||
fp << "LVDD ";
|
||||
fp << "LVDD ";
|
||||
first_enb_pin = false;
|
||||
} else {
|
||||
VTR_ASSERT_SAFE(false == first_enb_pin);
|
||||
fp << circuit_lib.port_prefix(output_ports[0]) << "_pmos_pg_" << last_enb_pin << " ";
|
||||
fp << generate_spice_port(enb_pin) << " ";
|
||||
fp << circuit_lib.port_prefix(output_ports[0]) << "_pmos_pg_" << power_gate_pin << " ";
|
||||
fp << "LVDD ";
|
||||
}
|
||||
fp << tech_lib.transistor_model_name(tech_model, TECH_LIB_TRANSISTOR_PMOS) << TRANSISTOR_WRAPPER_POSTFIX;
|
||||
int status = CMD_EXEC_SUCCESS;
|
||||
|
||||
/* Cache the last pin*/
|
||||
last_enb_pin = power_gate_pin;
|
||||
/* Consider use size/bin to compact layout:
|
||||
* Try to size transistors to the max width for each bin
|
||||
* The last bin may not reach the max width
|
||||
*/
|
||||
float regular_pmos_bin_width = tech_lib.transistor_model_max_width(tech_model, TECH_LIB_TRANSISTOR_PMOS);
|
||||
float total_pmos_width = circuit_lib.buffer_size(circuit_model)
|
||||
* tech_lib.model_pn_ratio(tech_model)
|
||||
* tech_lib.transistor_model_min_width(tech_model, TECH_LIB_TRANSISTOR_PMOS);
|
||||
int num_pmos_bins = std::ceil(total_pmos_width / regular_pmos_bin_width);
|
||||
float last_pmos_bin_width = std::fmod(total_pmos_width, regular_pmos_bin_width);
|
||||
for (int ibin = 0; ibin < num_pmos_bins; ++ibin) {
|
||||
float curr_bin_width = regular_pmos_bin_width;
|
||||
/* For last bin, we need an irregular width */
|
||||
if ((ibin == num_pmos_bins - 1)
|
||||
&& (0. != last_pmos_bin_width)) {
|
||||
curr_bin_width = last_pmos_bin_width;
|
||||
}
|
||||
status = print_spice_powergated_inverter_pmos_modeling(fp,
|
||||
std::to_string(ibin),
|
||||
circuit_lib.port_prefix(input_ports[0]),
|
||||
circuit_lib.port_prefix(output_ports[0]),
|
||||
circuit_lib,
|
||||
enb_port,
|
||||
tech_lib,
|
||||
tech_model,
|
||||
curr_bin_width);
|
||||
if (CMD_EXEC_FATAL_ERROR == status) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
/* Consider use size/bin to compact layout:
|
||||
* Try to size transistors to the max width for each bin
|
||||
* The last bin may not reach the max width
|
||||
*/
|
||||
float regular_nmos_bin_width = tech_lib.transistor_model_max_width(tech_model, TECH_LIB_TRANSISTOR_NMOS);
|
||||
float total_nmos_width = circuit_lib.buffer_size(circuit_model)
|
||||
* tech_lib.transistor_model_min_width(tech_model, TECH_LIB_TRANSISTOR_NMOS);
|
||||
int num_nmos_bins = std::ceil(total_nmos_width / regular_nmos_bin_width);
|
||||
float last_nmos_bin_width = std::fmod(total_nmos_width, regular_nmos_bin_width);
|
||||
for (int ibin = 0; ibin < num_nmos_bins; ++ibin) {
|
||||
float curr_bin_width = regular_nmos_bin_width;
|
||||
/* For last bin, we need an irregular width */
|
||||
if ((ibin == num_nmos_bins - 1)
|
||||
&& (0. != last_nmos_bin_width)) {
|
||||
curr_bin_width = last_nmos_bin_width;
|
||||
}
|
||||
|
||||
bool first_en_pin = true;
|
||||
size_t last_en_pin;
|
||||
for (const auto& power_gate_pin : circuit_lib.pins(en_port)) {
|
||||
BasicPort en_pin(circuit_lib.port_prefix(en_port), power_gate_pin, power_gate_pin);
|
||||
fp << "Xnmos_powergate_" << i << "_pin_" << power_gate_pin << " ";
|
||||
/* For the first pin, we should connect it to local VDD*/
|
||||
if (true == first_en_pin) {
|
||||
fp << circuit_lib.port_prefix(output_ports[0]) << "_nmos_pg_" << power_gate_pin << " ";
|
||||
fp << generate_spice_port(en_pin) << " ";
|
||||
fp << "LGND ";
|
||||
fp << "LGND ";
|
||||
first_en_pin = false;
|
||||
} else {
|
||||
VTR_ASSERT_SAFE(false == first_enb_pin);
|
||||
fp << circuit_lib.port_prefix(output_ports[0]) << "_nmos_pg_" << last_en_pin << " ";
|
||||
fp << circuit_lib.port_prefix(en_port) << " ";
|
||||
fp << circuit_lib.port_prefix(output_ports[0]) << "_nmos_pg_" << power_gate_pin << " ";
|
||||
fp << "LGND ";
|
||||
}
|
||||
fp << tech_lib.transistor_model_name(tech_model, TECH_LIB_TRANSISTOR_NMOS) << TRANSISTOR_WRAPPER_POSTFIX;
|
||||
|
||||
/* Cache the last pin*/
|
||||
last_enb_pin = power_gate_pin;
|
||||
status = print_spice_powergated_inverter_nmos_modeling(fp,
|
||||
std::to_string(ibin),
|
||||
circuit_lib.port_prefix(input_ports[0]),
|
||||
circuit_lib.port_prefix(output_ports[0]),
|
||||
circuit_lib,
|
||||
en_port,
|
||||
tech_lib,
|
||||
tech_model,
|
||||
curr_bin_width);
|
||||
if (CMD_EXEC_FATAL_ERROR == status) {
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Write transistor pairs using the technology model */
|
||||
fp << "Xpmos_" << i << " ";
|
||||
fp << circuit_lib.port_prefix(output_ports[0]) << " ";
|
||||
fp << circuit_lib.port_prefix(input_ports[0]) << " ";
|
||||
fp << circuit_lib.port_prefix(output_ports[0]) << "_pmos_pg_" << circuit_lib.pins(enb_port).back() << " ";
|
||||
fp << "LVDD ";
|
||||
fp << tech_lib.transistor_model_name(tech_model, TECH_LIB_TRANSISTOR_PMOS) << TRANSISTOR_WRAPPER_POSTFIX;
|
||||
|
||||
fp << "Xnmos_" << i << " ";
|
||||
fp << circuit_lib.port_prefix(output_ports[0]) << " ";
|
||||
fp << circuit_lib.port_prefix(input_ports[0]) << " ";
|
||||
fp << circuit_lib.port_prefix(output_ports[0]) << " _nmos_pg_" << circuit_lib.pins(en_port).back() << " ";
|
||||
fp << "LGND ";
|
||||
fp << tech_lib.transistor_model_name(tech_model, TECH_LIB_TRANSISTOR_NMOS) << TRANSISTOR_WRAPPER_POSTFIX;
|
||||
}
|
||||
|
||||
print_spice_subckt_end(fp, module_manager.module_name(module_id));
|
||||
|
@ -263,8 +401,86 @@ int print_spice_powergated_inverter_subckt(std::fstream& fp,
|
|||
return CMD_EXEC_SUCCESS;
|
||||
}
|
||||
|
||||
/************************************************
|
||||
/********************************************************************
|
||||
* Generate the SPICE modeling for the PMOS part of a regular inverter
|
||||
*
|
||||
* This function is created to be shared by inverter and buffer SPICE netlist writer
|
||||
*
|
||||
* Note:
|
||||
* - This function does NOT create a file
|
||||
* but requires a file stream created
|
||||
* - This function only output SPICE modeling for
|
||||
* an inverter. Any preprocessing or subckt definition should not be included!
|
||||
*******************************************************************/
|
||||
static
|
||||
int print_spice_regular_inverter_pmos_modeling(std::fstream& fp,
|
||||
const std::string& trans_name_postfix,
|
||||
const std::string& input_port_name,
|
||||
const std::string& output_port_name,
|
||||
const TechnologyLibrary& tech_lib,
|
||||
const TechnologyModelId& tech_model,
|
||||
const float& trans_width) {
|
||||
|
||||
if (false == valid_file_stream(fp)) {
|
||||
return CMD_EXEC_FATAL_ERROR;
|
||||
}
|
||||
|
||||
/* Write transistor pairs using the technology model */
|
||||
fp << "Xpmos_" << trans_name_postfix << " ";
|
||||
fp << output_port_name << " ";
|
||||
fp << input_port_name << " ";
|
||||
fp << "LVDD ";
|
||||
fp << "LVDD ";
|
||||
fp << tech_lib.transistor_model_name(tech_model, TECH_LIB_TRANSISTOR_PMOS) << TRANSISTOR_WRAPPER_POSTFIX;
|
||||
fp << " W=" << std::setprecision(10) << trans_width;
|
||||
fp << "\n";
|
||||
|
||||
return CMD_EXEC_SUCCESS;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Generate the SPICE modeling for the NMOS part of a regular inverter
|
||||
*
|
||||
* This function is created to be shared by inverter and buffer SPICE netlist writer
|
||||
*
|
||||
* Note:
|
||||
* - This function does NOT create a file
|
||||
* but requires a file stream created
|
||||
* - This function only output SPICE modeling for
|
||||
* an inverter. Any preprocessing or subckt definition should not be included!
|
||||
*******************************************************************/
|
||||
static
|
||||
int print_spice_regular_inverter_nmos_modeling(std::fstream& fp,
|
||||
const std::string& trans_name_postfix,
|
||||
const std::string& input_port_name,
|
||||
const std::string& output_port_name,
|
||||
const TechnologyLibrary& tech_lib,
|
||||
const TechnologyModelId& tech_model,
|
||||
const float& trans_width) {
|
||||
|
||||
if (false == valid_file_stream(fp)) {
|
||||
return CMD_EXEC_FATAL_ERROR;
|
||||
}
|
||||
|
||||
fp << "Xnmos_" << trans_name_postfix << " ";
|
||||
fp << output_port_name << " ";
|
||||
fp << input_port_name << " ";
|
||||
fp << "LGND ";
|
||||
fp << "LGND ";
|
||||
fp << tech_lib.transistor_model_name(tech_model, TECH_LIB_TRANSISTOR_NMOS) << TRANSISTOR_WRAPPER_POSTFIX;
|
||||
fp << " W=" << std::setprecision(10) << trans_width;
|
||||
fp << "\n";
|
||||
|
||||
return CMD_EXEC_SUCCESS;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Generate the SPICE subckt for a regular inverter
|
||||
*
|
||||
* Note:
|
||||
* - This function does NOT support power-gating
|
||||
* It should be managed in a separated function
|
||||
*
|
||||
* Schematic
|
||||
* LVDD
|
||||
* |
|
||||
|
@ -280,7 +496,7 @@ int print_spice_powergated_inverter_subckt(std::fstream& fp,
|
|||
* |
|
||||
* LGND
|
||||
*
|
||||
***********************************************/
|
||||
*******************************************************************/
|
||||
static
|
||||
int print_spice_regular_inverter_subckt(std::fstream& fp,
|
||||
const ModuleManager& module_manager,
|
||||
|
@ -310,33 +526,77 @@ int print_spice_regular_inverter_subckt(std::fstream& fp,
|
|||
VTR_ASSERT( (1 == input_ports.size()) && (1 == circuit_lib.port_size(input_ports[0])) );
|
||||
VTR_ASSERT( (1 == output_ports.size()) && (1 == circuit_lib.port_size(output_ports[0])) );
|
||||
|
||||
/* TODO: may consider use size/bin to compact layout etc. */
|
||||
for (size_t i = 0; i < circuit_lib.buffer_size(circuit_model); ++i) {
|
||||
/* Write transistor pairs using the technology model */
|
||||
fp << "Xpmos_" << i << " ";
|
||||
fp << circuit_lib.port_prefix(output_ports[0]) << " ";
|
||||
fp << circuit_lib.port_prefix(input_ports[0]) << " ";
|
||||
fp << "LVDD ";
|
||||
fp << "LVDD ";
|
||||
fp << tech_lib.transistor_model_name(tech_model, TECH_LIB_TRANSISTOR_PMOS) << TRANSISTOR_WRAPPER_POSTFIX;
|
||||
int status = CMD_EXEC_SUCCESS;
|
||||
|
||||
fp << "Xnmos_" << i << " ";
|
||||
fp << circuit_lib.port_prefix(output_ports[0]) << " ";
|
||||
fp << circuit_lib.port_prefix(input_ports[0]) << " ";
|
||||
fp << "LGND ";
|
||||
fp << "LGND ";
|
||||
fp << tech_lib.transistor_model_name(tech_model, TECH_LIB_TRANSISTOR_NMOS) << TRANSISTOR_WRAPPER_POSTFIX;
|
||||
/* Consider use size/bin to compact layout:
|
||||
* Try to size transistors to the max width for each bin
|
||||
* The last bin may not reach the max width
|
||||
*/
|
||||
float regular_pmos_bin_width = tech_lib.transistor_model_max_width(tech_model, TECH_LIB_TRANSISTOR_PMOS);
|
||||
float total_pmos_width = circuit_lib.buffer_size(circuit_model)
|
||||
* tech_lib.model_pn_ratio(tech_model)
|
||||
* tech_lib.transistor_model_min_width(tech_model, TECH_LIB_TRANSISTOR_PMOS);
|
||||
int num_pmos_bins = std::ceil(total_pmos_width / regular_pmos_bin_width);
|
||||
float last_pmos_bin_width = std::fmod(total_pmos_width, regular_pmos_bin_width);
|
||||
for (int ibin = 0; ibin < num_pmos_bins; ++ibin) {
|
||||
float curr_bin_width = regular_pmos_bin_width;
|
||||
/* For last bin, we need an irregular width */
|
||||
if ((ibin == num_pmos_bins - 1)
|
||||
&& (0. != last_pmos_bin_width)) {
|
||||
curr_bin_width = last_pmos_bin_width;
|
||||
}
|
||||
|
||||
status = print_spice_regular_inverter_pmos_modeling(fp,
|
||||
std::to_string(ibin),
|
||||
circuit_lib.port_prefix(input_ports[0]),
|
||||
circuit_lib.port_prefix(output_ports[0]),
|
||||
tech_lib,
|
||||
tech_model,
|
||||
curr_bin_width);
|
||||
if (CMD_EXEC_FATAL_ERROR == status) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
/* Consider use size/bin to compact layout:
|
||||
* Try to size transistors to the max width for each bin
|
||||
* The last bin may not reach the max width
|
||||
*/
|
||||
float regular_nmos_bin_width = tech_lib.transistor_model_max_width(tech_model, TECH_LIB_TRANSISTOR_NMOS);
|
||||
float total_nmos_width = circuit_lib.buffer_size(circuit_model)
|
||||
* tech_lib.transistor_model_min_width(tech_model, TECH_LIB_TRANSISTOR_NMOS);
|
||||
int num_nmos_bins = std::ceil(total_nmos_width / regular_nmos_bin_width);
|
||||
float last_nmos_bin_width = std::fmod(total_nmos_width, regular_nmos_bin_width);
|
||||
|
||||
for (int ibin = 0; ibin < num_nmos_bins; ++ibin) {
|
||||
float curr_bin_width = regular_nmos_bin_width;
|
||||
/* For last bin, we need an irregular width */
|
||||
if ((ibin == num_nmos_bins - 1)
|
||||
&& (0. != last_nmos_bin_width)) {
|
||||
curr_bin_width = last_nmos_bin_width;
|
||||
}
|
||||
|
||||
status = print_spice_regular_inverter_nmos_modeling(fp,
|
||||
std::to_string(ibin),
|
||||
circuit_lib.port_prefix(input_ports[0]),
|
||||
circuit_lib.port_prefix(output_ports[0]),
|
||||
tech_lib,
|
||||
tech_model,
|
||||
curr_bin_width);
|
||||
if (CMD_EXEC_FATAL_ERROR == status) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
print_spice_subckt_end(fp, module_manager.module_name(module_id));
|
||||
|
||||
return CMD_EXEC_SUCCESS;
|
||||
return status;
|
||||
}
|
||||
|
||||
/************************************************
|
||||
/********************************************************************
|
||||
* Generate the SPICE subckt for an inverter
|
||||
* Branch on the different circuit topologies
|
||||
***********************************************/
|
||||
*******************************************************************/
|
||||
static
|
||||
int print_spice_inverter_subckt(std::fstream& fp,
|
||||
const ModuleManager& module_manager,
|
||||
|
@ -362,13 +622,378 @@ int print_spice_inverter_subckt(std::fstream& fp,
|
|||
return status;
|
||||
}
|
||||
|
||||
/************************************************
|
||||
/********************************************************************
|
||||
* Generate the SPICE subckt for a power-gated buffer
|
||||
* which contains at least 2 stages
|
||||
*
|
||||
* Schematic of a multi-stage buffer
|
||||
*
|
||||
* LVDD LVDD
|
||||
* | |
|
||||
* - -
|
||||
* ENb[0] -o|| ENb[0] -o||
|
||||
* - -
|
||||
* | |
|
||||
* - -
|
||||
* ENb[1] -o|| ENb[1] -o||
|
||||
* - -
|
||||
* | |
|
||||
*
|
||||
* ... <More control signals if available in the port>
|
||||
*
|
||||
* | |
|
||||
* - -
|
||||
* +-o|| +-o||
|
||||
* | - | -
|
||||
* | | | |
|
||||
* in-->+ +-- ... ---+---->+---> out
|
||||
* | | | |
|
||||
* | - | -
|
||||
* +--|| +--||
|
||||
* - -
|
||||
* | |
|
||||
*
|
||||
* ... <More control signals if available in the port>
|
||||
*
|
||||
* | |
|
||||
* - -
|
||||
* EN[0] -|| EN[0] -||
|
||||
* - -
|
||||
* | |
|
||||
* - -
|
||||
* EN[1] -|| EN[1] -||
|
||||
* - -
|
||||
* | |
|
||||
|
||||
* | |
|
||||
* LGND LGND
|
||||
*
|
||||
*******************************************************************/
|
||||
static
|
||||
int print_spice_powergated_buffer_subckt(std::fstream& fp,
|
||||
const ModuleManager& module_manager,
|
||||
const ModuleId& module_id,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
const CircuitModelId& circuit_model,
|
||||
const TechnologyLibrary& tech_lib,
|
||||
const TechnologyModelId& tech_model) {
|
||||
if (false == valid_file_stream(fp)) {
|
||||
return CMD_EXEC_FATAL_ERROR;
|
||||
}
|
||||
|
||||
/* Print the inverter subckt definition */
|
||||
print_spice_subckt_definition(fp, module_manager, module_id);
|
||||
|
||||
/* Find the input and output ports:
|
||||
* we do NOT support global ports here,
|
||||
* it should be handled in another type of inverter subckt (power-gated)
|
||||
*/
|
||||
std::vector<CircuitPortId> input_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_INPUT, true);
|
||||
std::vector<CircuitPortId> output_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, true);
|
||||
|
||||
/* Make sure:
|
||||
* There is only 1 input port and 1 output port,
|
||||
* each size of which is 1
|
||||
*/
|
||||
VTR_ASSERT( (1 == input_ports.size()) && (1 == circuit_lib.port_size(input_ports[0])) );
|
||||
VTR_ASSERT( (1 == output_ports.size()) && (1 == circuit_lib.port_size(output_ports[0])) );
|
||||
|
||||
/* If the circuit model is power-gated, we need to find at least one global config_enable signals */
|
||||
VTR_ASSERT(true == circuit_lib.is_power_gated(circuit_model));
|
||||
CircuitPortId en_port = find_circuit_model_power_gate_en_port(circuit_lib, circuit_model);
|
||||
CircuitPortId enb_port = find_circuit_model_power_gate_enb_port(circuit_lib, circuit_model);
|
||||
VTR_ASSERT(true == circuit_lib.valid_circuit_port_id(en_port));
|
||||
VTR_ASSERT(true == circuit_lib.valid_circuit_port_id(enb_port));
|
||||
|
||||
int status = CMD_EXEC_SUCCESS;
|
||||
|
||||
/* Buffers must have >= 2 stages */
|
||||
VTR_ASSERT(2 <= circuit_lib.buffer_num_levels(circuit_model));
|
||||
|
||||
/* Build the array denoting width of inverters per stage */
|
||||
std::vector<float> buffer_widths(circuit_lib.buffer_num_levels(circuit_model), 1);
|
||||
for (size_t level = 0; level < circuit_lib.buffer_num_levels(circuit_model); ++level) {
|
||||
buffer_widths[level] = circuit_lib.buffer_size(circuit_model)
|
||||
* std::pow(circuit_lib.buffer_f_per_stage(circuit_model), level);
|
||||
}
|
||||
|
||||
for (size_t level = 0; level < circuit_lib.buffer_num_levels(circuit_model); ++level) {
|
||||
std::string input_port_name = circuit_lib.port_prefix(input_ports[0]);
|
||||
std::string output_port_name = circuit_lib.port_prefix(output_ports[0]);
|
||||
|
||||
/* Special for first stage: output port should be an intermediate node
|
||||
* Special for rest of stages: input port should be the output of previous stage
|
||||
*/
|
||||
if (0 == level) {
|
||||
output_port_name += std::string("_level") + std::to_string(level);
|
||||
} else {
|
||||
VTR_ASSERT(0 < level);
|
||||
input_port_name += std::string("_level") + std::to_string(level - 1);
|
||||
}
|
||||
|
||||
/* Consider use size/bin to compact layout:
|
||||
* Try to size transistors to the max width for each bin
|
||||
* The last bin may not reach the max width
|
||||
*/
|
||||
float regular_pmos_bin_width = tech_lib.transistor_model_max_width(tech_model, TECH_LIB_TRANSISTOR_PMOS);
|
||||
float total_pmos_width = buffer_widths[level]
|
||||
* tech_lib.model_pn_ratio(tech_model)
|
||||
* tech_lib.transistor_model_min_width(tech_model, TECH_LIB_TRANSISTOR_PMOS);
|
||||
int num_pmos_bins = std::ceil(total_pmos_width / regular_pmos_bin_width);
|
||||
float last_pmos_bin_width = std::fmod(total_pmos_width, regular_pmos_bin_width);
|
||||
|
||||
for (int ibin = 0; ibin < num_pmos_bins; ++ibin) {
|
||||
float curr_bin_width = regular_pmos_bin_width;
|
||||
/* For last bin, we need an irregular width */
|
||||
if ((ibin == num_pmos_bins - 1)
|
||||
&& (0. != last_pmos_bin_width)) {
|
||||
curr_bin_width = last_pmos_bin_width;
|
||||
}
|
||||
|
||||
std::string name_postfix = std::string("level") + std::to_string(level) + std::string("_bin") + std::to_string(ibin);
|
||||
|
||||
status = print_spice_powergated_inverter_pmos_modeling(fp,
|
||||
name_postfix,
|
||||
circuit_lib.port_prefix(input_ports[0]),
|
||||
circuit_lib.port_prefix(output_ports[0]),
|
||||
circuit_lib,
|
||||
enb_port,
|
||||
tech_lib,
|
||||
tech_model,
|
||||
curr_bin_width);
|
||||
if (CMD_EXEC_FATAL_ERROR == status) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
/* Consider use size/bin to compact layout:
|
||||
* Try to size transistors to the max width for each bin
|
||||
* The last bin may not reach the max width
|
||||
*/
|
||||
float regular_nmos_bin_width = tech_lib.transistor_model_max_width(tech_model, TECH_LIB_TRANSISTOR_NMOS);
|
||||
float total_nmos_width = buffer_widths[level]
|
||||
* tech_lib.transistor_model_min_width(tech_model, TECH_LIB_TRANSISTOR_NMOS);
|
||||
int num_nmos_bins = std::ceil(total_nmos_width / regular_nmos_bin_width);
|
||||
float last_nmos_bin_width = std::fmod(total_nmos_width, regular_nmos_bin_width);
|
||||
|
||||
for (int ibin = 0; ibin < num_nmos_bins; ++ibin) {
|
||||
float curr_bin_width = regular_nmos_bin_width;
|
||||
/* For last bin, we need an irregular width */
|
||||
if ((ibin == num_nmos_bins - 1)
|
||||
&& (0. != last_nmos_bin_width)) {
|
||||
curr_bin_width = last_nmos_bin_width;
|
||||
}
|
||||
|
||||
std::string name_postfix = std::string("level") + std::to_string(level) + std::string("_bin") + std::to_string(ibin);
|
||||
|
||||
status = print_spice_powergated_inverter_nmos_modeling(fp,
|
||||
name_postfix,
|
||||
circuit_lib.port_prefix(input_ports[0]),
|
||||
circuit_lib.port_prefix(output_ports[0]),
|
||||
circuit_lib,
|
||||
en_port,
|
||||
tech_lib,
|
||||
tech_model,
|
||||
curr_bin_width);
|
||||
if (CMD_EXEC_FATAL_ERROR == status) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
print_spice_subckt_end(fp, module_manager.module_name(module_id));
|
||||
|
||||
return CMD_EXEC_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* Generate the SPICE subckt for a regular buffer
|
||||
* which contains at least 2 stages
|
||||
*
|
||||
* Note:
|
||||
* - This function does NOT support power-gating
|
||||
* It should be managed in a separated function
|
||||
*
|
||||
* Schematic of a multi-stage buffer
|
||||
*
|
||||
* LVDD LVDD
|
||||
* | |
|
||||
* - -
|
||||
* +-o|| +-o||
|
||||
* | - | -
|
||||
* | | | |
|
||||
* in-->+ +-- ... ---+---->+---> out
|
||||
* | | | |
|
||||
* | - | -
|
||||
* +--|| +--||
|
||||
* - -
|
||||
* | |
|
||||
* LGND LGND
|
||||
*
|
||||
*******************************************************************/
|
||||
static
|
||||
int print_spice_regular_buffer_subckt(std::fstream& fp,
|
||||
const ModuleManager& module_manager,
|
||||
const ModuleId& module_id,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
const CircuitModelId& circuit_model,
|
||||
const TechnologyLibrary& tech_lib,
|
||||
const TechnologyModelId& tech_model) {
|
||||
if (false == valid_file_stream(fp)) {
|
||||
return CMD_EXEC_FATAL_ERROR;
|
||||
}
|
||||
|
||||
/* Print the inverter subckt definition */
|
||||
print_spice_subckt_definition(fp, module_manager, module_id);
|
||||
|
||||
/* Find the input and output ports:
|
||||
* we do NOT support global ports here,
|
||||
* it should be handled in another type of inverter subckt (power-gated)
|
||||
*/
|
||||
std::vector<CircuitPortId> input_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_INPUT, true);
|
||||
std::vector<CircuitPortId> output_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, true);
|
||||
|
||||
/* Make sure:
|
||||
* There is only 1 input port and 1 output port,
|
||||
* each size of which is 1
|
||||
*/
|
||||
VTR_ASSERT( (1 == input_ports.size()) && (1 == circuit_lib.port_size(input_ports[0])) );
|
||||
VTR_ASSERT( (1 == output_ports.size()) && (1 == circuit_lib.port_size(output_ports[0])) );
|
||||
|
||||
int status = CMD_EXEC_SUCCESS;
|
||||
|
||||
/* Buffers must have >= 2 stages */
|
||||
VTR_ASSERT(2 <= circuit_lib.buffer_num_levels(circuit_model));
|
||||
|
||||
/* Build the array denoting width of inverters per stage */
|
||||
std::vector<float> buffer_widths(circuit_lib.buffer_num_levels(circuit_model), 1);
|
||||
for (size_t level = 0; level < circuit_lib.buffer_num_levels(circuit_model); ++level) {
|
||||
buffer_widths[level] = circuit_lib.buffer_size(circuit_model)
|
||||
* std::pow(circuit_lib.buffer_f_per_stage(circuit_model), level);
|
||||
}
|
||||
|
||||
for (size_t level = 0; level < circuit_lib.buffer_num_levels(circuit_model); ++level) {
|
||||
std::string input_port_name = circuit_lib.port_prefix(input_ports[0]);
|
||||
std::string output_port_name = circuit_lib.port_prefix(output_ports[0]);
|
||||
|
||||
/* Special for first stage: output port should be an intermediate node
|
||||
* Special for rest of stages: input port should be the output of previous stage
|
||||
*/
|
||||
if (0 == level) {
|
||||
output_port_name += std::string("_level") + std::to_string(level);
|
||||
} else {
|
||||
VTR_ASSERT(0 < level);
|
||||
input_port_name += std::string("_level") + std::to_string(level - 1);
|
||||
}
|
||||
|
||||
/* Consider use size/bin to compact layout:
|
||||
* Try to size transistors to the max width for each bin
|
||||
* The last bin may not reach the max width
|
||||
*/
|
||||
float regular_pmos_bin_width = tech_lib.transistor_model_max_width(tech_model, TECH_LIB_TRANSISTOR_PMOS);
|
||||
float total_pmos_width = buffer_widths[level]
|
||||
* tech_lib.model_pn_ratio(tech_model)
|
||||
* tech_lib.transistor_model_min_width(tech_model, TECH_LIB_TRANSISTOR_PMOS);
|
||||
int num_pmos_bins = std::ceil(total_pmos_width / regular_pmos_bin_width);
|
||||
float last_pmos_bin_width = std::fmod(total_pmos_width, regular_pmos_bin_width);
|
||||
|
||||
for (int ibin = 0; ibin < num_pmos_bins; ++ibin) {
|
||||
float curr_bin_width = regular_pmos_bin_width;
|
||||
/* For last bin, we need an irregular width */
|
||||
if ((ibin == num_pmos_bins - 1)
|
||||
&& (0. != last_pmos_bin_width)) {
|
||||
curr_bin_width = last_pmos_bin_width;
|
||||
}
|
||||
|
||||
std::string name_postfix = std::string("level") + std::to_string(level) + std::string("_bin") + std::to_string(ibin);
|
||||
|
||||
status = print_spice_regular_inverter_pmos_modeling(fp,
|
||||
name_postfix,
|
||||
circuit_lib.port_prefix(input_ports[0]),
|
||||
circuit_lib.port_prefix(output_ports[0]),
|
||||
tech_lib,
|
||||
tech_model,
|
||||
curr_bin_width);
|
||||
if (CMD_EXEC_FATAL_ERROR == status) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
/* Consider use size/bin to compact layout:
|
||||
* Try to size transistors to the max width for each bin
|
||||
* The last bin may not reach the max width
|
||||
*/
|
||||
float regular_nmos_bin_width = tech_lib.transistor_model_max_width(tech_model, TECH_LIB_TRANSISTOR_NMOS);
|
||||
float total_nmos_width = buffer_widths[level]
|
||||
* tech_lib.transistor_model_min_width(tech_model, TECH_LIB_TRANSISTOR_NMOS);
|
||||
int num_nmos_bins = std::ceil(total_nmos_width / regular_nmos_bin_width);
|
||||
float last_nmos_bin_width = std::fmod(total_nmos_width, regular_nmos_bin_width);
|
||||
|
||||
for (int ibin = 0; ibin < num_nmos_bins; ++ibin) {
|
||||
float curr_bin_width = regular_nmos_bin_width;
|
||||
/* For last bin, we need an irregular width */
|
||||
if ((ibin == num_nmos_bins - 1)
|
||||
&& (0. != last_nmos_bin_width)) {
|
||||
curr_bin_width = last_nmos_bin_width;
|
||||
}
|
||||
|
||||
std::string name_postfix = std::string("level") + std::to_string(level) + std::string("_bin") + std::to_string(ibin);
|
||||
|
||||
status = print_spice_regular_inverter_nmos_modeling(fp,
|
||||
name_postfix,
|
||||
circuit_lib.port_prefix(input_ports[0]),
|
||||
circuit_lib.port_prefix(output_ports[0]),
|
||||
tech_lib,
|
||||
tech_model,
|
||||
curr_bin_width);
|
||||
if (CMD_EXEC_FATAL_ERROR == status) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
print_spice_subckt_end(fp, module_manager.module_name(module_id));
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Generate the SPICE subckt for an buffer
|
||||
* which consists of multiple stage of inverters
|
||||
*******************************************************************/
|
||||
static
|
||||
int print_spice_buffer_subckt(std::fstream& fp,
|
||||
const ModuleManager& module_manager,
|
||||
const ModuleId& module_id,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
const CircuitModelId& circuit_model,
|
||||
const TechnologyLibrary& tech_lib,
|
||||
const TechnologyModelId& tech_model) {
|
||||
int status = CMD_EXEC_SUCCESS;
|
||||
if (true == circuit_lib.is_power_gated(circuit_model)) {
|
||||
status = print_spice_powergated_buffer_subckt(fp,
|
||||
module_manager, module_id,
|
||||
circuit_lib, circuit_model,
|
||||
tech_lib, tech_model);
|
||||
} else {
|
||||
VTR_ASSERT_SAFE(false == circuit_lib.is_power_gated(circuit_model));
|
||||
status = print_spice_regular_buffer_subckt(fp,
|
||||
module_manager, module_id,
|
||||
circuit_lib, circuit_model,
|
||||
tech_lib, tech_model);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Generate the SPICE netlist for essential gates:
|
||||
* - inverters and their templates
|
||||
* - buffers and their templates
|
||||
* - pass-transistor or transmission gates
|
||||
* - logic gates
|
||||
***********************************************/
|
||||
*******************************************************************/
|
||||
int print_spice_essential_gates(NetlistManager& netlist_manager,
|
||||
const ModuleManager& module_manager,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
|
@ -385,15 +1010,17 @@ int print_spice_essential_gates(NetlistManager& netlist_manager,
|
|||
check_file_stream(spice_fname.c_str(), fp);
|
||||
|
||||
/* Create file */
|
||||
VTR_LOG("Generating SPICE netlist '%s' for transistor wrappers...",
|
||||
VTR_LOG("Generating SPICE netlist '%s' for essential gates...",
|
||||
spice_fname.c_str());
|
||||
|
||||
print_spice_file_header(fp, std::string("Essential gates"));
|
||||
|
||||
int status = CMD_EXEC_SUCCESS;
|
||||
|
||||
/* Iterate over the circuit models */
|
||||
for (const CircuitModelId& circuit_model : circuit_lib.models()) {
|
||||
/* Bypass models require extern netlists */
|
||||
if (true == circuit_lib.model_circuit_netlist(circuit_model).empty()) {
|
||||
if (!circuit_lib.model_circuit_netlist(circuit_model).empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -429,6 +1056,10 @@ int print_spice_essential_gates(NetlistManager& netlist_manager,
|
|||
tech_lib, tech_model);
|
||||
} else {
|
||||
VTR_ASSERT(CIRCUIT_MODEL_BUF_BUF == circuit_lib.buffer_type(circuit_model));
|
||||
status = print_spice_buffer_subckt(fp,
|
||||
module_manager, module_id,
|
||||
circuit_lib, circuit_model,
|
||||
tech_lib, tech_model);
|
||||
}
|
||||
|
||||
if (CMD_EXEC_FATAL_ERROR == status) {
|
||||
|
|
|
@ -37,10 +37,10 @@ repack #--verbose
|
|||
|
||||
# Build the bitstream
|
||||
# - Output the fabric-independent bitstream to a file
|
||||
build_architecture_bitstream --verbose --write_file fabric_indepenent_bitstream.xml
|
||||
build_architecture_bitstream --verbose --write_file fabric_independent_bitstream.xml
|
||||
|
||||
# Build fabric-dependent bitstream
|
||||
build_fabric_bitstream --verbose
|
||||
build_fabric_bitstream --verbose --file fabric_bitstream.xml --format xml
|
||||
|
||||
# Write the Verilog netlist for FPGA fabric
|
||||
# - Enable the use of explicit port mapping in Verilog netlist
|
||||
|
|
|
@ -37,10 +37,10 @@ repack #--verbose
|
|||
|
||||
# Build the bitstream
|
||||
# - Output the fabric-independent bitstream to a file
|
||||
build_architecture_bitstream --verbose --write_file fabric_indepenent_bitstream.xml
|
||||
build_architecture_bitstream --verbose --write_file fabric_independent_bitstream.xml
|
||||
|
||||
# Build fabric-dependent bitstream
|
||||
build_fabric_bitstream --verbose
|
||||
build_fabric_bitstream --verbose --file fabric_bitstream.xml --format xml
|
||||
|
||||
# Write the Verilog netlist for FPGA fabric
|
||||
# - Enable the use of explicit port mapping in Verilog netlist
|
||||
|
|
|
@ -37,10 +37,10 @@ repack #--verbose
|
|||
|
||||
# Build the bitstream
|
||||
# - Output the fabric-independent bitstream to a file
|
||||
build_architecture_bitstream --verbose --write_file fabric_indepenent_bitstream.xml
|
||||
build_architecture_bitstream --verbose --write_file fabric_independent_bitstream.xml
|
||||
|
||||
# Build fabric-dependent bitstream
|
||||
build_fabric_bitstream --verbose
|
||||
build_fabric_bitstream --verbose --file fabric_bitstream.xml --format xml
|
||||
|
||||
# Write the Verilog netlist for FPGA fabric
|
||||
# - Enable the use of explicit port mapping in Verilog netlist
|
||||
|
|
|
@ -37,10 +37,10 @@ repack #--verbose
|
|||
|
||||
# Build the bitstream
|
||||
# - Output the fabric-independent bitstream to a file
|
||||
build_architecture_bitstream --verbose --write_file fabric_indepenent_bitstream.xml
|
||||
build_architecture_bitstream --verbose --write_file fabric_independent_bitstream.xml
|
||||
|
||||
# Build fabric-dependent bitstream
|
||||
build_fabric_bitstream --verbose
|
||||
build_fabric_bitstream --verbose --file fabric_bitstream.xml --format xml
|
||||
|
||||
# Write the Verilog netlist for FPGA fabric
|
||||
# - Enable the use of explicit port mapping in Verilog netlist
|
||||
|
|
|
@ -37,10 +37,10 @@ repack #--verbose
|
|||
|
||||
# Build the bitstream
|
||||
# - Output the fabric-independent bitstream to a file
|
||||
build_architecture_bitstream --verbose --write_file fabric_indepenent_bitstream.xml
|
||||
build_architecture_bitstream --verbose --write_file fabric_independent_bitstream.xml
|
||||
|
||||
# Build fabric-dependent bitstream
|
||||
build_fabric_bitstream --verbose
|
||||
build_fabric_bitstream --verbose --file fabric_bitstream.xml --format xml
|
||||
|
||||
# Write the Verilog netlist for FPGA fabric
|
||||
# - Enable the use of explicit port mapping in Verilog netlist
|
||||
|
|
|
@ -37,10 +37,10 @@ repack #--verbose
|
|||
|
||||
# Build the bitstream
|
||||
# - Output the fabric-independent bitstream to a file
|
||||
build_architecture_bitstream --verbose --write_file fabric_indepenent_bitstream.xml
|
||||
build_architecture_bitstream --verbose --write_file fabric_independent_bitstream.xml
|
||||
|
||||
# Build fabric-dependent bitstream
|
||||
build_fabric_bitstream --verbose
|
||||
build_fabric_bitstream --verbose --file fabric_bitstream.xml --format xml
|
||||
|
||||
# Write the Verilog netlist for FPGA fabric
|
||||
# - Enable the use of explicit port mapping in Verilog netlist
|
||||
|
|
|
@ -35,10 +35,10 @@ repack #--verbose
|
|||
|
||||
# Build the bitstream
|
||||
# - Output the fabric-independent bitstream to a file
|
||||
build_architecture_bitstream --verbose --write_file fabric_indepenent_bitstream.xml
|
||||
build_architecture_bitstream --verbose --write_file fabric_independent_bitstream.xml
|
||||
|
||||
# Build fabric-dependent bitstream
|
||||
build_fabric_bitstream --verbose
|
||||
build_fabric_bitstream --verbose --file fabric_bitstream.txt
|
||||
|
||||
# Finish and exit OpenFPGA
|
||||
exit
|
||||
|
|
|
@ -40,10 +40,10 @@ repack #--verbose
|
|||
|
||||
# Build the bitstream
|
||||
# - Output the fabric-independent bitstream to a file
|
||||
build_architecture_bitstream --verbose --write_file fabric_indepenent_bitstream.xml
|
||||
build_architecture_bitstream --verbose --write_file fabric_independent_bitstream.xml
|
||||
|
||||
# Build fabric-dependent bitstream
|
||||
build_fabric_bitstream --verbose
|
||||
build_fabric_bitstream --verbose --file fabric_bitstream.xml --format xml
|
||||
|
||||
# Write the Verilog netlist for FPGA fabric
|
||||
# - Enable the use of explicit port mapping in Verilog netlist
|
||||
|
|
|
@ -40,10 +40,10 @@ repack #--verbose
|
|||
|
||||
# Build the bitstream
|
||||
# - Output the fabric-independent bitstream to a file
|
||||
build_architecture_bitstream --verbose --write_file fabric_indepenent_bitstream.xml
|
||||
build_architecture_bitstream --verbose --write_file fabric_independent_bitstream.xml
|
||||
|
||||
# Build fabric-dependent bitstream
|
||||
build_fabric_bitstream --verbose
|
||||
build_fabric_bitstream --verbose --file fabric_bitstream.xml --format xml
|
||||
|
||||
# Write the Verilog netlist for FPGA fabric
|
||||
# - Enable the use of explicit port mapping in Verilog netlist
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
# Run VPR for the 'and' design
|
||||
#--write_rr_graph example_rr_graph.xml
|
||||
vpr ${VPR_ARCH_FILE} ${VPR_TESTBENCH_BLIF} --clock_modeling route
|
||||
|
||||
# Read OpenFPGA architecture definition
|
||||
read_openfpga_arch -f ${OPENFPGA_ARCH_FILE}
|
||||
|
||||
# Read OpenFPGA simulation settings
|
||||
read_openfpga_simulation_setting -f ${OPENFPGA_SIM_SETTING_FILE}
|
||||
|
||||
# Annotate the OpenFPGA architecture to VPR data base
|
||||
# to debug use --verbose options
|
||||
link_openfpga_arch --activity_file ${ACTIVITY_FILE} --sort_gsb_chan_node_in_edges
|
||||
|
||||
# Check and correct any naming conflicts in the BLIF netlist
|
||||
check_netlist_naming_conflict --fix --report ./netlist_renaming.xml
|
||||
|
||||
# Build the module graph
|
||||
# - Enabled compression on routing architecture modules
|
||||
# - Enable pin duplication on grid modules
|
||||
build_fabric --compress_routing #--verbose
|
||||
|
||||
# Write the fabric hierarchy of module graph to a file
|
||||
# This is used by hierarchical PnR flows
|
||||
write_fabric_hierarchy --file ./fabric_hierarchy.txt
|
||||
|
||||
# Write the Verilog netlist for FPGA fabric
|
||||
# - Enable the use of explicit port mapping in Verilog netlist
|
||||
write_fabric_spice --file ./SPICE --verbose
|
||||
|
||||
# Finish and exit OpenFPGA
|
||||
exit
|
||||
|
||||
# Note :
|
||||
# To run verification at the end of the flow maintain source in ./SRC directory
|
|
@ -37,10 +37,10 @@ repack #--verbose
|
|||
|
||||
# Build the bitstream
|
||||
# - Output the fabric-independent bitstream to a file
|
||||
build_architecture_bitstream --verbose --write_file fabric_indepenent_bitstream.xml
|
||||
build_architecture_bitstream --verbose --write_file fabric_independent_bitstream.xml
|
||||
|
||||
# Build fabric-dependent bitstream
|
||||
build_fabric_bitstream --verbose
|
||||
build_fabric_bitstream --verbose --file fabric_bitstream --format xml
|
||||
|
||||
# Write the Verilog testbench for FPGA fabric
|
||||
# - We suggest the use of same output directory as fabric Verilog netlists
|
||||
|
|
|
@ -37,10 +37,10 @@ repack #--verbose
|
|||
|
||||
# Build the bitstream
|
||||
# - Output the fabric-independent bitstream to a file
|
||||
build_architecture_bitstream --verbose --write_file fabric_indepenent_bitstream.xml
|
||||
build_architecture_bitstream --verbose --write_file fabric_independent_bitstream.xml
|
||||
|
||||
# Build fabric-dependent bitstream
|
||||
build_fabric_bitstream --verbose
|
||||
build_fabric_bitstream --verbose --file fabric_bitstream.xml --format xml
|
||||
|
||||
# Write the Verilog netlist for FPGA fabric
|
||||
# - Enable the use of explicit port mapping in Verilog netlist
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
|
||||
# Configuration file for running experiments
|
||||
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
|
||||
# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs
|
||||
# Each job execute fpga_flow script on combination of architecture & benchmark
|
||||
# timeout_each_job is timeout for each job
|
||||
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
|
||||
|
||||
[GENERAL]
|
||||
run_engine=openfpga_shell
|
||||
openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/OpenFPGAShellScripts/example_script.openfpga
|
||||
power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml
|
||||
power_analysis = true
|
||||
spice_output=false
|
||||
verilog_output=true
|
||||
timeout_each_job = 20*60
|
||||
fpga_flow=vpr_blif
|
||||
openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k6_frac_N10_adder_register_scan_chain_depop50_40nm_openfpga.xml
|
||||
openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml
|
||||
external_fabric_key_file=
|
||||
|
||||
[ARCHITECTURES]
|
||||
arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_register_scan_chain_depop50_40nm.xml
|
||||
|
||||
[BENCHMARKS]
|
||||
bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.blif
|
||||
|
||||
[SYNTHESIS_PARAM]
|
||||
bench0_top = and2
|
||||
bench0_act = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.act
|
||||
bench0_verilog = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v
|
||||
bench0_chan_width = 300
|
||||
|
||||
[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH]
|
||||
end_flow_with_test=
|
||||
vpr_fpga_verilog_formal_verification_top_netlist=
|
|
@ -0,0 +1,33 @@
|
|||
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
|
||||
# Configuration file for running experiments
|
||||
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
|
||||
# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs
|
||||
# Each job execute fpga_flow script on combination of architecture & benchmark
|
||||
# timeout_each_job is timeout for each job
|
||||
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
|
||||
|
||||
[GENERAL]
|
||||
run_engine=openfpga_shell
|
||||
openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/OpenFPGAShellScripts/generate_spice_example_script.openfpga
|
||||
power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml
|
||||
power_analysis = true
|
||||
spice_output=false
|
||||
verilog_output=true
|
||||
timeout_each_job = 20*60
|
||||
fpga_flow=vpr_blif
|
||||
openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k6_frac_N10_40nm_openfpga.xml
|
||||
openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml
|
||||
external_fabric_key_file=
|
||||
|
||||
[ARCHITECTURES]
|
||||
arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k6_frac_N10_tileable_40nm.xml
|
||||
|
||||
[BENCHMARKS]
|
||||
bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.blif
|
||||
|
||||
[SYNTHESIS_PARAM]
|
||||
bench0_top = and2
|
||||
bench0_act = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.act
|
||||
bench0_verilog = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v
|
||||
|
||||
[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH]
|
Loading…
Reference in New Issue