Merge pull request #118 from LNIS-Projects/dev

Remove the restrictions on requiring two outputs for configurable memory circuits
This commit is contained in:
Laboratory for Nano Integrated Systems (LNIS) 2020-11-06 13:25:29 -07:00 committed by GitHub
commit 520e54d7ab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 154 additions and 59 deletions

View File

@ -143,7 +143,8 @@ A circuit model may consist of a number of ports. The port list is mandatory in
.. option:: <port type="<string>" prefix="<string>" lib_name="<string>" size="<int>"
default_val="<int>" circuit_model_name="<string>" mode_select="<bool>"
is_global="<bool>" is_set="<bool>" is_reset="<bool>" is_config_enable="<bool>"/>
is_global="<bool>" is_set="<bool>" is_reset="<bool>"
is_config_enable="<bool>" is_io="<bool>" is_data_io="<bool>"/>
Define the attributes for a port of a circuit model.
@ -169,10 +170,14 @@ A circuit model may consist of a number of ports. The port list is mandatory in
.. note:: ``circuit_model_name`` is only valid when the type of this port is ``sram``.
- ``io="true|false"`` Specify if this port should be treated as an I/O port of an FPGA fabric. When this is enabled, this port of each circuit model instanciated in FPGA will be added as an I/O of an FPGA.
- ``is_io="true|false"`` Specify if this port should be treated as an I/O port of an FPGA fabric. When this is enabled, this port of each circuit model instanciated in FPGA will be added as an I/O of an FPGA.
.. note:: global ``output`` ports must be ``io`` ports
- ``is_data_io="true|false"`` Specify if this port should be treated as a mappable FPGA I/O port for users' implementation. When this is enabled, I/Os of user's implementation, e.g., ``.input`` and ``.output`` in ``.blif`` netlist, can be mapped to the port through VPR.
.. note:: Any I/O model must have at least 1 port that is defined as data I/O!
- ``mode_select="true|false"`` Specify if this port controls the mode switching in a configurable logic block. This is due to that a configurable logic block can operate in different modes, which is controlled by SRAM bits.
.. note:: ``mode_select`` is only valid when the type of this port is ``sram``.

View File

@ -832,7 +832,7 @@ Template
- ``type="ccff|ff"`` Specify the type of a flip-flop. ``ff`` is a regular flip-flop while ``ccff`` denotes a configuration-chain flip-flop
.. note:: A flip-flop should have three types of ports, ``input``, ``output`` and ``clock``.
.. note:: A flip-flop should at least have three types of ports, ``input``, ``output`` and ``clock``.
.. note:: If the user provides a customized Verilog/SPICE netlist, the bandwidth of ports should be defined to the same as the Verilog/SPICE netlist.
@ -891,7 +891,8 @@ The code describing this FF is:
<circuit_model type="ccff" name="ccff" prefix="ccff" verilog_netlist="ccff.v" spice_netlist="ccff.sp">
<port type="input" prefix="D" size="1"/>
<port type="output" prefix="Q" size="2"/>
<port type="output" prefix="Q" size="1"/>
<port type="output" prefix="Qb" size="1"/>
<port type="clock" prefix="CK" size="1" is_global="true"/>
</circuit_model>
@ -1053,7 +1054,7 @@ The code describing this I/O-Pad is:
<input_buffer exist="true" circuit_model_name="INVTX1"/>
<output_buffer exist="true" circuit_model_name="INVTX1"/>
<pass_gate_logic circuit_model_name="TGATE"/>
<port type="inout" prefix="pad" size="1"/>
<port type="inout" prefix="pad" size="1" is_global="true" is_io="true" is_data_io="true"/>
<port type="sram" prefix="en" size="1" mode_select="true" circuit_model_name="ccff" default_val="1"/>
<port type="input" prefix="outpad" size="1"/>
<port type="output" prefix="inpad" size="1"/>

View File

@ -299,10 +299,11 @@ size_t check_ccff_circuit_model_ports(const CircuitLibrary& circuit_lib,
1, 1, true);
/* Check if we have output */
/* Check if we have 1 or 2 outputs */
size_t num_output_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, true).size();
num_err += check_one_circuit_model_port_type_and_size_required(circuit_lib, circuit_model,
CIRCUIT_MODEL_PORT_OUTPUT,
2, 1, false);
num_output_ports, 1, false);
return num_err;
}

View File

@ -152,10 +152,6 @@ BitstreamManager build_device_bitstream(const VprContext& vpr_ctx,
/* Bitstream manager to be built */
BitstreamManager bitstream_manager;
/* Assign the SRAM model applied to the FPGA fabric */
CircuitModelId sram_model = openfpga_ctx.arch().config_protocol.memory_model();
VTR_ASSERT(true == openfpga_ctx.arch().circuit_lib.valid_model_id(sram_model));
/* Create the top-level block for bitstream
* This is related to the top-level module of fpga
*/

View File

@ -181,6 +181,7 @@ void fpga_verilog_testbench(const ModuleManager &module_manager,
if (true == options.print_formal_verification_top_netlist()) {
std::string formal_verification_top_netlist_file_path = src_dir_path + netlist_name + std::string(FORMAL_VERIFICATION_VERILOG_FILE_POSTFIX);
print_verilog_preconfig_top_module(module_manager, bitstream_manager,
config_protocol,
circuit_lib, global_ports,
atom_ctx, place_ctx, io_location_map,
netlist_annotation,

View File

@ -189,7 +189,8 @@ namespace openfpga
static void print_verilog_preconfig_top_module_assign_bitstream(std::fstream &fp,
const ModuleManager &module_manager,
const ModuleId &top_module,
const BitstreamManager &bitstream_manager)
const BitstreamManager &bitstream_manager,
const bool& output_datab_bits)
{
/* Validate the file stream */
valid_file_stream(fp);
@ -231,44 +232,46 @@ namespace openfpga
print_verilog_wire_constant_values(fp, config_data_port, config_data_values);
}
fp << "initial begin" << std::endl;
if (true == output_datab_bits) {
fp << "initial begin" << std::endl;
for (const ConfigBlockId &config_block_id : bitstream_manager.blocks())
{
/* We only cares blocks with configuration bits */
if (0 == bitstream_manager.block_bits(config_block_id).size())
{
continue;
}
/* Build the hierarchical path of the configuration bit in modules */
std::vector<ConfigBlockId> block_hierarchy = find_bitstream_manager_block_hierarchy(bitstream_manager, config_block_id);
/* Drop the first block, which is the top module, it should be replaced by the instance name here */
/* Ensure that this is the module we want to drop! */
VTR_ASSERT(0 == module_manager.module_name(top_module).compare(bitstream_manager.block_name(block_hierarchy[0])));
block_hierarchy.erase(block_hierarchy.begin());
/* Build the full hierarchy path */
std::string bit_hierarchy_path(FORMAL_VERIFICATION_TOP_MODULE_UUT_NAME);
for (const ConfigBlockId &temp_block : block_hierarchy)
for (const ConfigBlockId &config_block_id : bitstream_manager.blocks())
{
/* We only cares blocks with configuration bits */
if (0 == bitstream_manager.block_bits(config_block_id).size())
{
continue;
}
/* Build the hierarchical path of the configuration bit in modules */
std::vector<ConfigBlockId> block_hierarchy = find_bitstream_manager_block_hierarchy(bitstream_manager, config_block_id);
/* Drop the first block, which is the top module, it should be replaced by the instance name here */
/* Ensure that this is the module we want to drop! */
VTR_ASSERT(0 == module_manager.module_name(top_module).compare(bitstream_manager.block_name(block_hierarchy[0])));
block_hierarchy.erase(block_hierarchy.begin());
/* Build the full hierarchy path */
std::string bit_hierarchy_path(FORMAL_VERIFICATION_TOP_MODULE_UUT_NAME);
for (const ConfigBlockId &temp_block : block_hierarchy)
{
bit_hierarchy_path += std::string(".");
bit_hierarchy_path += bitstream_manager.block_name(temp_block);
}
bit_hierarchy_path += std::string(".");
bit_hierarchy_path += bitstream_manager.block_name(temp_block);
}
bit_hierarchy_path += std::string(".");
/* Find the bit index in the parent block */
BasicPort config_datab_port(bit_hierarchy_path + generate_configurable_memory_inverted_data_out_name(),
bitstream_manager.block_bits(config_block_id).size());
/* Find the bit index in the parent block */
BasicPort config_datab_port(bit_hierarchy_path + generate_configurable_memory_inverted_data_out_name(),
bitstream_manager.block_bits(config_block_id).size());
std::vector<size_t> config_datab_values;
for (const ConfigBitId config_bit : bitstream_manager.block_bits(config_block_id))
{
config_datab_values.push_back(!bitstream_manager.bit_value(config_bit));
std::vector<size_t> config_datab_values;
for (const ConfigBitId config_bit : bitstream_manager.block_bits(config_block_id))
{
config_datab_values.push_back(!bitstream_manager.bit_value(config_bit));
}
print_verilog_force_wire_constant_values(fp, config_datab_port, config_datab_values);
}
print_verilog_force_wire_constant_values(fp, config_datab_port, config_datab_values);
fp << "end" << std::endl;
}
fp << "end" << std::endl;
print_verilog_comment(fp, std::string("----- End assign bitstream to configuration memories -----"));
}
@ -279,7 +282,8 @@ namespace openfpga
static void print_verilog_preconfig_top_module_deposit_bitstream(std::fstream &fp,
const ModuleManager &module_manager,
const ModuleId &top_module,
const BitstreamManager &bitstream_manager)
const BitstreamManager &bitstream_manager,
const bool& output_datab_bits)
{
/* Validate the file stream */
valid_file_stream(fp);
@ -314,9 +318,6 @@ namespace openfpga
BasicPort config_data_port(bit_hierarchy_path + generate_configurable_memory_data_out_name(),
bitstream_manager.block_bits(config_block_id).size());
BasicPort config_datab_port(bit_hierarchy_path + generate_configurable_memory_inverted_data_out_name(),
bitstream_manager.block_bits(config_block_id).size());
/* Wire it to the configuration bit: access both data out and data outb ports */
std::vector<size_t> config_data_values;
for (const ConfigBitId config_bit : bitstream_manager.block_bits(config_block_id))
@ -325,6 +326,15 @@ namespace openfpga
}
print_verilog_deposit_wire_constant_values(fp, config_data_port, config_data_values);
/* Skip datab ports if specified */
if (false == output_datab_bits) {
continue;
}
BasicPort config_datab_port(bit_hierarchy_path + generate_configurable_memory_inverted_data_out_name(),
bitstream_manager.block_bits(config_block_id).size());
std::vector<size_t> config_datab_values;
for (const ConfigBitId config_bit : bitstream_manager.block_bits(config_block_id))
{
@ -347,19 +357,37 @@ namespace openfpga
static void print_verilog_preconfig_top_module_load_bitstream(std::fstream &fp,
const ModuleManager &module_manager,
const ModuleId &top_module,
const CircuitLibrary& circuit_lib,
const CircuitModelId& mem_model,
const BitstreamManager &bitstream_manager)
{
/* Skip the datab port if there is only 1 output port in memory model
* Currently, it assumes that the data output port is always defined while datab is optional
* If we see only 1 port, we assume datab is not defined by default.
* TODO: this switch could be smarter: it should identify if only data or datab
* ports are defined.
*/
bool output_datab_bits = true;
if (1 == circuit_lib.model_ports_by_type(mem_model, CIRCUIT_MODEL_PORT_OUTPUT).size()) {
output_datab_bits = false;
}
print_verilog_comment(fp, std::string("----- Begin load bitstream to configuration memories -----"));
print_verilog_preprocessing_flag(fp, std::string(ICARUS_SIMULATOR_FLAG));
/* Use assign syntax for Icarus simulator */
print_verilog_preconfig_top_module_assign_bitstream(fp, module_manager, top_module, bitstream_manager);
print_verilog_preconfig_top_module_assign_bitstream(fp, module_manager, top_module,
bitstream_manager,
output_datab_bits);
fp << "`else" << std::endl;
/* Use assign syntax for Icarus simulator */
print_verilog_preconfig_top_module_deposit_bitstream(fp, module_manager, top_module, bitstream_manager);
print_verilog_preconfig_top_module_deposit_bitstream(fp, module_manager, top_module,
bitstream_manager,
output_datab_bits);
print_verilog_endif(fp);
@ -400,6 +428,7 @@ namespace openfpga
*******************************************************************/
void print_verilog_preconfig_top_module(const ModuleManager &module_manager,
const BitstreamManager &bitstream_manager,
const ConfigProtocol &config_protocol,
const CircuitLibrary &circuit_lib,
const std::vector<CircuitPortId> &global_ports,
const AtomContext &atom_ctx,
@ -457,8 +486,13 @@ namespace openfpga
std::string(FORMAL_VERIFICATION_TOP_MODULE_PORT_POSTFIX),
(size_t)VERILOG_DEFAULT_SIGNAL_INIT_VALUE);
/* Assign the SRAM model applied to the FPGA fabric */
CircuitModelId sram_model = config_protocol.memory_model();
VTR_ASSERT(true == circuit_lib.valid_model_id(sram_model));
/* Assign FPGA internal SRAM/Memory ports to bitstream values */
print_verilog_preconfig_top_module_load_bitstream(fp, module_manager, top_module,
circuit_lib, sram_model,
bitstream_manager);
/* Testbench ends*/

View File

@ -11,6 +11,7 @@
#include "module_manager.h"
#include "bitstream_manager.h"
#include "io_location_map.h"
#include "config_protocol.h"
#include "vpr_netlist_annotation.h"
/********************************************************************
@ -22,6 +23,7 @@ namespace openfpga {
void print_verilog_preconfig_top_module(const ModuleManager& module_manager,
const BitstreamManager& bitstream_manager,
const ConfigProtocol &config_protocol,
const CircuitLibrary& circuit_lib,
const std::vector<CircuitPortId>& global_ports,
const AtomContext& atom_ctx,

View File

@ -776,7 +776,7 @@ void add_module_nets_between_logic_and_memory_sram_bus(ModuleManager& module_man
/* Do wiring only when we have sramb ports */
if ( (false == logic_module_sramb_port_ids.empty())
|| (ModulePortId::INVALID() == mem_module_sramb_port_id) ) {
&& (ModulePortId::INVALID() != mem_module_sramb_port_id) ) {
add_module_nets_between_logic_and_memory_sram_ports(module_manager, parent_module,
logic_module, logic_instance_id,
memory_module, memory_instance_id,

View File

@ -172,16 +172,15 @@
<port type="output" prefix="lut3_out" size="2" lut_frac_level="3" lut_output_mask="0,1"/>
<port type="output" prefix="lut4_out" size="1" lut_output_mask="0"/>
<port type="sram" prefix="sram" size="16"/>
<port type="sram" prefix="mode" size="1" mode_select="true" circuit_model_name="DFF" default_val="1"/>
<port type="sram" prefix="mode" size="1" mode_select="true" circuit_model_name="DFFQ" default_val="1"/>
</circuit_model>
<!--Scan-chain DFF subckt ports should be defined as <D> <Q> <Qb> <CLK> <RESET> <SET> -->
<circuit_model type="ccff" name="DFF" prefix="DFF" verilog_netlist="${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/verilog/dff.v">
<circuit_model type="ccff" name="DFFQ" prefix="DFFQ" verilog_netlist="${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/verilog/dff.v">
<design_technology type="cmos"/>
<input_buffer exist="true" circuit_model_name="sky130_fd_sc_hd__inv_1"/>
<output_buffer exist="true" circuit_model_name="sky130_fd_sc_hd__inv_1"/>
<port type="input" prefix="D" size="1"/>
<port type="output" prefix="Q" size="1"/>
<port type="output" prefix="QN" size="1"/>
<port type="clock" prefix="prog_clk" lib_name="CK" size="1" is_global="true" default_val="0" is_prog="true"/>
</circuit_model>
<circuit_model type="iopad" name="EMBEDDED_IO" prefix="EMBEDDED_IO" is_default="true" verilog_netlist="${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/verilog/gpio.v">
@ -193,11 +192,11 @@
<port type="output" prefix="SOC_DIR" lib_name="SOC_DIR" size="1" is_global="true" is_io="true"/>
<port type="output" prefix="inpad" lib_name="FPGA_IN" size="1"/>
<port type="input" prefix="outpad" lib_name="FPGA_OUT" size="1"/>
<port type="sram" prefix="en" lib_name="FPGA_DIR" size="1" mode_select="true" circuit_model_name="DFF" default_val="1"/>
<port type="sram" prefix="en" lib_name="FPGA_DIR" size="1" mode_select="true" circuit_model_name="DFFQ" default_val="1"/>
</circuit_model>
</circuit_library>
<configuration_protocol>
<organization type="scan_chain" circuit_model_name="DFF" num_regions="1"/>
<organization type="scan_chain" circuit_model_name="DFFQ" num_regions="1"/>
</configuration_protocol>
<connection_block>
<switch name="ipin_cblock" circuit_model_name="mux_tree_tapbuf"/>

View File

@ -153,17 +153,16 @@
<port type="output" prefix="lut5_out" size="2" lut_frac_level="5" lut_output_mask="0,1"/>
<port type="output" prefix="lut6_out" size="1" lut_output_mask="0"/>
<port type="sram" prefix="sram" size="64"/>
<port type="sram" prefix="mode" size="1" mode_select="true" circuit_model_name="DFFR" default_val="1"/>
<port type="sram" prefix="mode" size="1" mode_select="true" circuit_model_name="DFFRQ" default_val="1"/>
</circuit_model>
<!--Scan-chain DFF subckt ports should be defined as <D> <Q> <Qb> <CLK> <RESET> <SET> -->
<circuit_model type="ccff" name="DFFR" prefix="DFFR" spice_netlist="${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/spice/dff.sp" verilog_netlist="${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/verilog/dff.v">
<circuit_model type="ccff" name="DFFRQ" prefix="DFFRQ" spice_netlist="${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/spice/dff.sp" verilog_netlist="${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/verilog/dff.v">
<design_technology type="cmos"/>
<input_buffer exist="true" circuit_model_name="INVTX1"/>
<output_buffer exist="true" circuit_model_name="INVTX1"/>
<port type="input" prefix="pReset" lib_name="RST" size="1" is_global="true" default_val="0" is_reset="true" is_prog="true"/>
<port type="input" prefix="D" size="1"/>
<port type="output" prefix="Q" size="1"/>
<port type="output" prefix="QN" size="1"/>
<port type="clock" prefix="prog_clk" lib_name="CK" size="1" is_global="true" default_val="0" is_prog="true"/>
</circuit_model>
<circuit_model type="iopad" name="GPIO" prefix="GPIO" spice_netlist="${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/spice/gpio.sp" verilog_netlist="${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/verilog/gpio.v">
@ -171,13 +170,13 @@
<input_buffer exist="true" circuit_model_name="INVTX1"/>
<output_buffer exist="true" circuit_model_name="INVTX1"/>
<port type="inout" prefix="PAD" size="1" is_global="true" is_io="true" is_data_io="true"/>
<port type="sram" prefix="DIR" size="1" mode_select="true" circuit_model_name="DFFR" default_val="1"/>
<port type="sram" prefix="DIR" size="1" mode_select="true" circuit_model_name="DFFRQ" default_val="1"/>
<port type="input" prefix="outpad" lib_name="A" size="1"/>
<port type="output" prefix="inpad" lib_name="Y" size="1"/>
</circuit_model>
</circuit_library>
<configuration_protocol>
<organization type="scan_chain" circuit_model_name="DFFR"/>
<organization type="scan_chain" circuit_model_name="DFFRQ"/>
</configuration_protocol>
<connection_block>
<switch name="ipin_cblock" circuit_model_name="mux_tree_tapbuf"/>

View File

@ -4,6 +4,31 @@
// Coder : Xifan TANG
//-----------------------------------------------------
//-----------------------------------------------------
// Function : A native D-type flip-flop with single output
//-----------------------------------------------------
module DFFQ (
input CK, // Clock Input
input D, // Data Input
output Q // Q output
);
//------------Internal Variables--------
reg q_reg;
//-------------Code Starts Here---------
always @ (posedge CK) begin
q_reg <= D;
end
// Wire q_reg to Q
`ifndef ENABLE_FORMAL_VERIFICATION
assign Q = q_reg;
`else
assign Q = 1'bZ;
`endif
endmodule //End Of Module
//-----------------------------------------------------
// Function : A native D-type flip-flop
//-----------------------------------------------------
@ -32,6 +57,38 @@ end
endmodule //End Of Module
//-----------------------------------------------------
// Function : D-type flip-flop with
// - single output
// - asynchronous active high reset
//-----------------------------------------------------
module DFFRQ (
input RST, // Reset input
input CK, // Clock Input
input D, // Data Input
output Q // Q output
);
//------------Internal Variables--------
reg q_reg;
//-------------Code Starts Here---------
always @ ( posedge CK or posedge RST)
if (RST) begin
q_reg <= 1'b0;
end else begin
q_reg <= D;
end
// Wire q_reg to Q
`ifndef ENABLE_FORMAL_VERIFICATION
assign Q = q_reg;
`else
assign Q = 1'bZ;
`endif
endmodule //End Of Module
//-----------------------------------------------------
// Function : D-type flip-flop with
// - asynchronous active high reset