diff --git a/.travis/basic_reg_test.sh b/.travis/basic_reg_test.sh index 6c9e1c04d..d067b4599 100755 --- a/.travis/basic_reg_test.sh +++ b/.travis/basic_reg_test.sh @@ -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" diff --git a/.travis/verilog_reg_test.sh b/.travis/verilog_reg_test.sh index e5c6bbd40..18ffe91e5 100755 --- a/.travis/verilog_reg_test.sh +++ b/.travis/verilog_reg_test.sh @@ -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 diff --git a/docs/source/manual/arch_lang/technology_library.rst b/docs/source/manual/arch_lang/technology_library.rst index 08b6c62d9..4d1c5f2a0 100644 --- a/docs/source/manual/arch_lang/technology_library.rst +++ b/docs/source/manual/arch_lang/technology_library.rst @@ -13,8 +13,8 @@ General organization is as follows. - - + + @@ -71,15 +71,19 @@ A device model represents a transistor/RRAM model available in users' technology - ``pn_ratio=""`` 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:: +.. option:: Specify device-level parameters for transistors - ``name=""`` specify the name of the p/n type transistor, which can be found in the manual of the technology provider. - - ``chan_length=""`` specify the channel length of *p/n* type transistor. + - ``chan_length=""`` specify the channel length of a *p/n* type transistor. - - ``min_width=""`` 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=""`` 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=""`` 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=""`` specify the variation name defined in the ```` diff --git a/docs/source/manual/fpga_bitstream/fabric_dependent_bitstream.rst b/docs/source/manual/fpga_bitstream/fabric_dependent_bitstream.rst index 280768c1a..f8505f71c 100644 --- a/docs/source/manual/fpga_bitstream/fabric_dependent_bitstream.rst +++ b/docs/source/manual/fpga_bitstream/fabric_dependent_bitstream.rst @@ -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
. + 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 + + + + + + ... + + + +.. option:: frame_based + + Multiple lines will be included, each of which is organized as
. + For example + + .. code-block:: xml + + + + ... + + +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 ````, 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 + + + + + + + + + + +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 + + + + + + + + + + + + + +.. option:: frame_based + + - ``frame``: frame address information + + A quick example: + + .. code-block:: xml + + + + + + + + + + + diff --git a/docs/source/manual/openfpga_shell/openfpga_commands/fpga_bitstream_commands.rst b/docs/source/manual/openfpga_shell/openfpga_commands/fpga_bitstream_commands.rst index 731f99f94..8ec6c8614 100644 --- a/docs/source/manual/openfpga_shell/openfpga_commands/fpga_bitstream_commands.rst +++ b/docs/source/manual/openfpga_shell/openfpga_commands/fpga_bitstream_commands.rst @@ -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 diff --git a/docs/source/manual/openfpga_shell/openfpga_commands/setup_commands.rst b/docs/source/manual/openfpga_shell/openfpga_commands/setup_commands.rst index aa0018476..2d628117a 100644 --- a/docs/source/manual/openfpga_shell/openfpga_commands/setup_commands.rst +++ b/docs/source/manual/openfpga_shell/openfpga_commands/setup_commands.rst @@ -109,6 +109,10 @@ build_fabric - ``--write_fabric_key `` 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 diff --git a/libopenfpga/libarchopenfpga/src/read_xml_technology_library.cpp b/libopenfpga/libarchopenfpga/src/read_xml_technology_library.cpp index f2f082116..e2871a638 100644 --- a/libopenfpga/libarchopenfpga/src/read_xml_technology_library.cpp +++ b/libopenfpga/libarchopenfpga/src/read_xml_technology_library.cpp @@ -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()); diff --git a/libopenfpga/libarchopenfpga/src/technology_library.cpp b/libopenfpga/libarchopenfpga/src/technology_library.cpp index 3f8e8e7f9..aa97abe80 100644 --- a/libopenfpga/libarchopenfpga/src/technology_library.cpp +++ b/libopenfpga/libarchopenfpga/src/technology_library.cpp @@ -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::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 */ diff --git a/libopenfpga/libarchopenfpga/src/technology_library.h b/libopenfpga/libarchopenfpga/src/technology_library.h index a38acade3..ba90eff1d 100644 --- a/libopenfpga/libarchopenfpga/src/technology_library.h +++ b/libopenfpga/libarchopenfpga/src/technology_library.h @@ -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> 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> 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() diff --git a/libopenfpga/libarchopenfpga/src/write_xml_circuit_library.cpp b/libopenfpga/libarchopenfpga/src/write_xml_circuit_library.cpp index 88fc0d3b2..5dd69ca8e 100644 --- a/libopenfpga/libarchopenfpga/src/write_xml_circuit_library.cpp +++ b/libopenfpga/libarchopenfpga/src/write_xml_circuit_library.cpp @@ -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" << "" << "\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 */ diff --git a/libopenfpga/libarchopenfpga/src/write_xml_technology_library.cpp b/libopenfpga/libarchopenfpga/src/write_xml_technology_library.cpp index 6f3f6fe0d..bf15bbe32 100644 --- a/libopenfpga/libarchopenfpga/src/write_xml_technology_library.cpp +++ b/libopenfpga/libarchopenfpga/src/write_xml_technology_library.cpp @@ -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()); } diff --git a/libopenfpga/libfpgabitstream/src/bitstream_manager.cpp b/libopenfpga/libfpgabitstream/src/bitstream_manager.cpp index eb62222fb..3d5052989 100644 --- a/libopenfpga/libfpgabitstream/src/bitstream_manager.cpp +++ b/libopenfpga/libfpgabitstream/src/bitstream_manager.cpp @@ -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); } } diff --git a/libopenfpga/libfpgabitstream/src/bitstream_manager.h b/libopenfpga/libfpgabitstream/src/bitstream_manager.h index 84c3ec97c..32575c5db 100644 --- a/libopenfpga/libfpgabitstream/src/bitstream_manager.h +++ b/libopenfpga/libfpgabitstream/src/bitstream_manager.h @@ -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 invalid_bit_ids_; /* value of a bit in the Bitstream */ vtr::vector bit_values_; + vtr::vector bit_parent_blocks_; }; } /* end namespace openfpga */ diff --git a/openfpga/src/base/openfpga_bitstream.cpp b/openfpga/src/base/openfpga_bitstream.cpp index 3fbffc45d..4707601d0 100644 --- a/openfpga/src/base/openfpga_bitstream.cpp +++ b/openfpga/src/base/openfpga_bitstream.cpp @@ -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 */ diff --git a/openfpga/src/base/openfpga_bitstream_command.cpp b/openfpga/src/base/openfpga_bitstream_command.cpp index 1a337e9d0..c9f2a407a 100644 --- a/openfpga/src/base/openfpga_bitstream_command.cpp +++ b/openfpga/src/base/openfpga_bitstream_command.cpp @@ -85,6 +85,10 @@ ShellCommandId add_openfpga_fabric_bitstream_command(openfpga::Shell #include @@ -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 { diff --git a/openfpga/src/fpga_bitstream/fabric_bitstream_writer.h b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.h similarity index 92% rename from openfpga/src/fpga_bitstream/fabric_bitstream_writer.h rename to openfpga/src/fpga_bitstream/write_text_fabric_bitstream.h index bcf5466b7..3a2d9a594 100644 --- a/openfpga/src/fpga_bitstream/fabric_bitstream_writer.h +++ b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.h @@ -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 diff --git a/openfpga/src/fpga_bitstream/write_xml_fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/write_xml_fabric_bitstream.cpp new file mode 100644 index 000000000..2e6660c49 --- /dev/null +++ b/openfpga/src/fpga_bitstream/write_xml_fabric_bitstream.cpp @@ -0,0 +1,194 @@ +/******************************************************************** + * This file includes functions that output a fabric-dependent + * bitstream database to files in XML format + *******************************************************************/ +#include +#include +#include + +/* 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 << std::endl; +} + +/******************************************************************** + * Write a configuration bit into a plain text file + * General format + * + * + * + * + * + * ... + * + * 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 : + * + * + * - Frame-based configuration protocol : + * + * + * 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 << "\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 block_hierarchy = find_bitstream_manager_block_hierarchy(bitstream_manager, config_block); + write_tab_to_file(fp, 1); + fp << "\n"; + size_t hierarchy_counter = 0; + for (const ConfigBlockId& temp_block : block_hierarchy) { + write_tab_to_file(fp, 2); + fp << "\n"; + hierarchy_counter++; + } + write_tab_to_file(fp, 1); + fp << "\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 << "\n"; + + write_tab_to_file(fp, 1); + fp << "\n"; + break; + } + case CONFIG_MEM_FRAME_BASED: { + write_tab_to_file(fp, 1); + fp << "\n"; + break; + } + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid configuration protocol type!\n"); + return 1; + } + + fp << "\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 */ diff --git a/openfpga/src/fpga_bitstream/write_xml_fabric_bitstream.h b/openfpga/src/fpga_bitstream/write_xml_fabric_bitstream.h new file mode 100644 index 000000000..66786c54f --- /dev/null +++ b/openfpga/src/fpga_bitstream/write_xml_fabric_bitstream.h @@ -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 +#include +#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 diff --git a/openfpga/src/fpga_spice/spice_essential_gates.cpp b/openfpga/src/fpga_spice/spice_essential_gates.cpp index b5836a4b3..7fd144f33 100644 --- a/openfpga/src/fpga_spice/spice_essential_gates.cpp +++ b/openfpga/src/fpga_spice/spice_essential_gates.cpp @@ -5,6 +5,7 @@ * logic gates etc. ***********************************************/ #include +#include #include /* 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|| * - * | - * ... + * + * ... + * * | * - * +-o|| @@ -138,7 +281,9 @@ int print_spice_transistor_wrapper(NetlistManager& netlist_manager, * | - * +--|| * - - * ... + * + * ... + * * | * - * 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|| + * - - + * | | + * + * ... + * + * | | + * - - + * +-o|| +-o|| + * | - | - + * | | | | + * in-->+ +-- ... ---+---->+---> out + * | | | | + * | - | - + * +--|| +--|| + * - - + * | | + * + * ... + * + * | | + * - - + * 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 input_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_INPUT, true); + std::vector 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 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 input_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_INPUT, true); + std::vector 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 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) { diff --git a/openfpga_flow/OpenFPGAShellScripts/configuration_chain_example_script.openfpga b/openfpga_flow/OpenFPGAShellScripts/configuration_chain_example_script.openfpga index 33891b72d..acfb78142 100644 --- a/openfpga_flow/OpenFPGAShellScripts/configuration_chain_example_script.openfpga +++ b/openfpga_flow/OpenFPGAShellScripts/configuration_chain_example_script.openfpga @@ -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 diff --git a/openfpga_flow/OpenFPGAShellScripts/duplicated_grid_pin_example_script.openfpga b/openfpga_flow/OpenFPGAShellScripts/duplicated_grid_pin_example_script.openfpga index 97f540116..d4f80dd6f 100644 --- a/openfpga_flow/OpenFPGAShellScripts/duplicated_grid_pin_example_script.openfpga +++ b/openfpga_flow/OpenFPGAShellScripts/duplicated_grid_pin_example_script.openfpga @@ -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 diff --git a/openfpga_flow/OpenFPGAShellScripts/example_script.openfpga b/openfpga_flow/OpenFPGAShellScripts/example_script.openfpga index 97f540116..d4f80dd6f 100644 --- a/openfpga_flow/OpenFPGAShellScripts/example_script.openfpga +++ b/openfpga_flow/OpenFPGAShellScripts/example_script.openfpga @@ -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 diff --git a/openfpga_flow/OpenFPGAShellScripts/fast_configuration_example_script.openfpga b/openfpga_flow/OpenFPGAShellScripts/fast_configuration_example_script.openfpga index d6800e2f1..b6bcfc507 100644 --- a/openfpga_flow/OpenFPGAShellScripts/fast_configuration_example_script.openfpga +++ b/openfpga_flow/OpenFPGAShellScripts/fast_configuration_example_script.openfpga @@ -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 diff --git a/openfpga_flow/OpenFPGAShellScripts/flatten_routing_example_script.openfpga b/openfpga_flow/OpenFPGAShellScripts/flatten_routing_example_script.openfpga index e5cb63413..1718dd353 100644 --- a/openfpga_flow/OpenFPGAShellScripts/flatten_routing_example_script.openfpga +++ b/openfpga_flow/OpenFPGAShellScripts/flatten_routing_example_script.openfpga @@ -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 diff --git a/openfpga_flow/OpenFPGAShellScripts/full_testbench_example_script.openfpga b/openfpga_flow/OpenFPGAShellScripts/full_testbench_example_script.openfpga index 97f540116..d4f80dd6f 100644 --- a/openfpga_flow/OpenFPGAShellScripts/full_testbench_example_script.openfpga +++ b/openfpga_flow/OpenFPGAShellScripts/full_testbench_example_script.openfpga @@ -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 diff --git a/openfpga_flow/OpenFPGAShellScripts/generate_bitstream_example_script.openfpga b/openfpga_flow/OpenFPGAShellScripts/generate_bitstream_example_script.openfpga index e7c934513..a4f897a48 100644 --- a/openfpga_flow/OpenFPGAShellScripts/generate_bitstream_example_script.openfpga +++ b/openfpga_flow/OpenFPGAShellScripts/generate_bitstream_example_script.openfpga @@ -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 diff --git a/openfpga_flow/OpenFPGAShellScripts/generate_secure_fabric_example_script.openfpga b/openfpga_flow/OpenFPGAShellScripts/generate_secure_fabric_example_script.openfpga index d98e9b74d..fa79ff941 100644 --- a/openfpga_flow/OpenFPGAShellScripts/generate_secure_fabric_example_script.openfpga +++ b/openfpga_flow/OpenFPGAShellScripts/generate_secure_fabric_example_script.openfpga @@ -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 diff --git a/openfpga_flow/OpenFPGAShellScripts/generate_secure_fabric_from_key_example_script.openfpga b/openfpga_flow/OpenFPGAShellScripts/generate_secure_fabric_from_key_example_script.openfpga index 47b3edce3..e80c3b1f3 100644 --- a/openfpga_flow/OpenFPGAShellScripts/generate_secure_fabric_from_key_example_script.openfpga +++ b/openfpga_flow/OpenFPGAShellScripts/generate_secure_fabric_from_key_example_script.openfpga @@ -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 diff --git a/openfpga_flow/OpenFPGAShellScripts/generate_spice_example_script.openfpga b/openfpga_flow/OpenFPGAShellScripts/generate_spice_example_script.openfpga new file mode 100644 index 000000000..3b50edbc8 --- /dev/null +++ b/openfpga_flow/OpenFPGAShellScripts/generate_spice_example_script.openfpga @@ -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 diff --git a/openfpga_flow/OpenFPGAShellScripts/generate_testbench_example_script.openfpga b/openfpga_flow/OpenFPGAShellScripts/generate_testbench_example_script.openfpga index a0e09687f..cdc9c7984 100644 --- a/openfpga_flow/OpenFPGAShellScripts/generate_testbench_example_script.openfpga +++ b/openfpga_flow/OpenFPGAShellScripts/generate_testbench_example_script.openfpga @@ -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 diff --git a/openfpga_flow/OpenFPGAShellScripts/implicit_verilog_example_script.openfpga b/openfpga_flow/OpenFPGAShellScripts/implicit_verilog_example_script.openfpga index ed7ccf1de..79acd1d67 100644 --- a/openfpga_flow/OpenFPGAShellScripts/implicit_verilog_example_script.openfpga +++ b/openfpga_flow/OpenFPGAShellScripts/implicit_verilog_example_script.openfpga @@ -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 diff --git a/openfpga_flow/tasks/depopulate_crossbar/config/task.conf b/openfpga_flow/tasks/depopulate_crossbar/config/task.conf new file mode 100644 index 000000000..e33af50c7 --- /dev/null +++ b/openfpga_flow/tasks/depopulate_crossbar/config/task.conf @@ -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= diff --git a/openfpga_flow/tasks/generate_spice/config/task.conf b/openfpga_flow/tasks/generate_spice/config/task.conf new file mode 100644 index 000000000..05e093c3f --- /dev/null +++ b/openfpga_flow/tasks/generate_spice/config/task.conf @@ -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]