add frame-based memory module builder
This commit is contained in:
parent
3a26bb5eef
commit
8864920460
|
@ -76,8 +76,9 @@ int build_fabric(OpenfpgaContext& openfpga_ctx,
|
||||||
VTR_LOG("\n");
|
VTR_LOG("\n");
|
||||||
|
|
||||||
openfpga_ctx.mutable_module_graph() = build_device_module_graph(openfpga_ctx.mutable_io_location_map(),
|
openfpga_ctx.mutable_module_graph() = build_device_module_graph(openfpga_ctx.mutable_io_location_map(),
|
||||||
g_vpr_ctx.device(),
|
openfpga_ctx.mutable_decoder_lib(),
|
||||||
const_cast<const OpenfpgaContext&>(openfpga_ctx),
|
const_cast<const OpenfpgaContext&>(openfpga_ctx),
|
||||||
|
g_vpr_ctx.device(),
|
||||||
cmd_context.option_enable(cmd, opt_compress_routing),
|
cmd_context.option_enable(cmd, opt_compress_routing),
|
||||||
cmd_context.option_enable(cmd, opt_duplicate_grid_pin),
|
cmd_context.option_enable(cmd, opt_duplicate_grid_pin),
|
||||||
cmd_context.option_enable(cmd, opt_verbose));
|
cmd_context.option_enable(cmd, opt_verbose));
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include "vpr_placement_annotation.h"
|
#include "vpr_placement_annotation.h"
|
||||||
#include "vpr_routing_annotation.h"
|
#include "vpr_routing_annotation.h"
|
||||||
#include "mux_library.h"
|
#include "mux_library.h"
|
||||||
|
#include "decoder_library.h"
|
||||||
#include "tile_direct.h"
|
#include "tile_direct.h"
|
||||||
#include "module_manager.h"
|
#include "module_manager.h"
|
||||||
#include "netlist_manager.h"
|
#include "netlist_manager.h"
|
||||||
|
@ -55,6 +56,7 @@ class OpenfpgaContext : public Context {
|
||||||
const openfpga::VprRoutingAnnotation& vpr_routing_annotation() const { return vpr_routing_annotation_; }
|
const openfpga::VprRoutingAnnotation& vpr_routing_annotation() const { return vpr_routing_annotation_; }
|
||||||
const openfpga::DeviceRRGSB& device_rr_gsb() const { return device_rr_gsb_; }
|
const openfpga::DeviceRRGSB& device_rr_gsb() const { return device_rr_gsb_; }
|
||||||
const openfpga::MuxLibrary& mux_lib() const { return mux_lib_; }
|
const openfpga::MuxLibrary& mux_lib() const { return mux_lib_; }
|
||||||
|
const openfpga::DecoderLibrary& decoder_lib() const { return decoder_lib_; }
|
||||||
const openfpga::TileDirect& tile_direct() const { return tile_direct_; }
|
const openfpga::TileDirect& tile_direct() const { return tile_direct_; }
|
||||||
const openfpga::ModuleManager& module_graph() const { return module_graph_; }
|
const openfpga::ModuleManager& module_graph() const { return module_graph_; }
|
||||||
const openfpga::FlowManager& flow_manager() const { return flow_manager_; }
|
const openfpga::FlowManager& flow_manager() const { return flow_manager_; }
|
||||||
|
@ -72,6 +74,7 @@ class OpenfpgaContext : public Context {
|
||||||
openfpga::VprRoutingAnnotation& mutable_vpr_routing_annotation() { return vpr_routing_annotation_; }
|
openfpga::VprRoutingAnnotation& mutable_vpr_routing_annotation() { return vpr_routing_annotation_; }
|
||||||
openfpga::DeviceRRGSB& mutable_device_rr_gsb() { return device_rr_gsb_; }
|
openfpga::DeviceRRGSB& mutable_device_rr_gsb() { return device_rr_gsb_; }
|
||||||
openfpga::MuxLibrary& mutable_mux_lib() { return mux_lib_; }
|
openfpga::MuxLibrary& mutable_mux_lib() { return mux_lib_; }
|
||||||
|
openfpga::DecoderLibrary& mutable_decoder_lib() { return decoder_lib_; }
|
||||||
openfpga::TileDirect& mutable_tile_direct() { return tile_direct_; }
|
openfpga::TileDirect& mutable_tile_direct() { return tile_direct_; }
|
||||||
openfpga::ModuleManager& mutable_module_graph() { return module_graph_; }
|
openfpga::ModuleManager& mutable_module_graph() { return module_graph_; }
|
||||||
openfpga::FlowManager& mutable_flow_manager() { return flow_manager_; }
|
openfpga::FlowManager& mutable_flow_manager() { return flow_manager_; }
|
||||||
|
@ -105,6 +108,9 @@ class OpenfpgaContext : public Context {
|
||||||
/* Library of physical implmentation of routing multiplexers */
|
/* Library of physical implmentation of routing multiplexers */
|
||||||
openfpga::MuxLibrary mux_lib_;
|
openfpga::MuxLibrary mux_lib_;
|
||||||
|
|
||||||
|
/* Library of physical implmentation of decoders */
|
||||||
|
openfpga::DecoderLibrary decoder_lib_;
|
||||||
|
|
||||||
/* Inner/inter-column/row tile direct connections */
|
/* Inner/inter-column/row tile direct connections */
|
||||||
openfpga::TileDirect tile_direct_;
|
openfpga::TileDirect tile_direct_;
|
||||||
|
|
||||||
|
|
|
@ -142,6 +142,20 @@ std::string generate_mux_local_decoder_subckt_name(const size_t& addr_size,
|
||||||
return subckt_name;
|
return subckt_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/************************************************
|
||||||
|
* Generate the module name of a decoder
|
||||||
|
* for frame-based memories
|
||||||
|
***********************************************/
|
||||||
|
std::string generate_frame_memory_decoder_subckt_name(const size_t& addr_size,
|
||||||
|
const size_t& data_size) {
|
||||||
|
std::string subckt_name = "frame_decoder";
|
||||||
|
subckt_name += std::to_string(addr_size);
|
||||||
|
subckt_name += "to";
|
||||||
|
subckt_name += std::to_string(data_size);
|
||||||
|
|
||||||
|
return subckt_name;
|
||||||
|
}
|
||||||
|
|
||||||
/************************************************
|
/************************************************
|
||||||
* Generate the module name of a routing track wire
|
* Generate the module name of a routing track wire
|
||||||
***********************************************/
|
***********************************************/
|
||||||
|
|
|
@ -50,6 +50,9 @@ std::string generate_mux_branch_subckt_name(const CircuitLibrary& circuit_lib,
|
||||||
std::string generate_mux_local_decoder_subckt_name(const size_t& addr_size,
|
std::string generate_mux_local_decoder_subckt_name(const size_t& addr_size,
|
||||||
const size_t& data_size);
|
const size_t& data_size);
|
||||||
|
|
||||||
|
std::string generate_frame_memory_decoder_subckt_name(const size_t& addr_size,
|
||||||
|
const size_t& data_size);
|
||||||
|
|
||||||
std::string generate_segment_wire_subckt_name(const std::string& wire_model_name,
|
std::string generate_segment_wire_subckt_name(const std::string& wire_model_name,
|
||||||
const size_t& segment_id);
|
const size_t& segment_id);
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,12 @@ constexpr char* GRID_MUX_INSTANCE_PREFIX = "mux_";
|
||||||
constexpr char* SWITCH_BLOCK_MUX_INSTANCE_PREFIX = "mux_";
|
constexpr char* SWITCH_BLOCK_MUX_INSTANCE_PREFIX = "mux_";
|
||||||
constexpr char* CONNECTION_BLOCK_MUX_INSTANCE_PREFIX = "mux_";
|
constexpr char* CONNECTION_BLOCK_MUX_INSTANCE_PREFIX = "mux_";
|
||||||
|
|
||||||
|
/* Decoder naming constant strings */
|
||||||
|
constexpr char* DECODER_ENABLE_PORT_NAME = "enable";
|
||||||
|
constexpr char* DECODER_ADDRESS_PORT_NAME = "address";
|
||||||
|
constexpr char* DECODER_DATA_PORT_NAME = "data";
|
||||||
|
constexpr char* DECODER_DATA_INV_PORT_NAME = "data_inv";
|
||||||
|
|
||||||
/* Inverted port naming */
|
/* Inverted port naming */
|
||||||
constexpr char* INV_PORT_POSTFIX = "_inv";
|
constexpr char* INV_PORT_POSTFIX = "_inv";
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "vtr_assert.h"
|
#include "vtr_assert.h"
|
||||||
#include "vtr_time.h"
|
#include "vtr_time.h"
|
||||||
|
|
||||||
|
#include "openfpga_reserved_words.h"
|
||||||
#include "openfpga_naming.h"
|
#include "openfpga_naming.h"
|
||||||
#include "decoder_library_utils.h"
|
#include "decoder_library_utils.h"
|
||||||
#include "module_manager_utils.h"
|
#include "module_manager_utils.h"
|
||||||
|
@ -18,6 +19,61 @@
|
||||||
/* begin namespace openfpga */
|
/* begin namespace openfpga */
|
||||||
namespace openfpga {
|
namespace openfpga {
|
||||||
|
|
||||||
|
/***************************************************************************************
|
||||||
|
* Create a module for a decoder with a given output size
|
||||||
|
*
|
||||||
|
* Data input
|
||||||
|
* | | ... |
|
||||||
|
* v v v
|
||||||
|
* +-----------+
|
||||||
|
* / \
|
||||||
|
* enable-->/ Decoder \
|
||||||
|
* +-----------------+
|
||||||
|
* | | | ... | | |
|
||||||
|
* v v v v v v
|
||||||
|
* Data Outputs
|
||||||
|
*
|
||||||
|
* The outputs are assumes to be one-hot codes (at most only one '1' exist)
|
||||||
|
* Considering this fact, there are only num_of_outputs conditions to be encoded.
|
||||||
|
* Therefore, the number of inputs is ceil(log(num_of_outputs)/log(2))
|
||||||
|
***************************************************************************************/
|
||||||
|
ModuleId build_frame_memory_decoder_module(ModuleManager& module_manager,
|
||||||
|
const DecoderLibrary& decoder_lib,
|
||||||
|
const DecoderId& decoder) {
|
||||||
|
/* Get the number of inputs */
|
||||||
|
size_t addr_size = decoder_lib.addr_size(decoder);
|
||||||
|
size_t data_size = decoder_lib.data_size(decoder);
|
||||||
|
|
||||||
|
/* Create a name for the local encoder */
|
||||||
|
std::string module_name = generate_frame_memory_decoder_subckt_name(addr_size, data_size);
|
||||||
|
|
||||||
|
/* Create a Verilog Module based on the circuit model, and add to module manager */
|
||||||
|
ModuleId module_id = module_manager.add_module(module_name);
|
||||||
|
VTR_ASSERT(true == module_manager.valid_module_id(module_id));
|
||||||
|
|
||||||
|
/* Add enable port */
|
||||||
|
BasicPort en_port(std::string(DECODER_ENABLE_PORT_NAME), 1);
|
||||||
|
module_manager.add_port(module_id, en_port, ModuleManager::MODULE_INPUT_PORT);
|
||||||
|
/* Add each input port */
|
||||||
|
BasicPort addr_port(std::string(DECODER_ADDRESS_PORT_NAME), addr_size);
|
||||||
|
module_manager.add_port(module_id, addr_port, ModuleManager::MODULE_INPUT_PORT);
|
||||||
|
/* Add each output port */
|
||||||
|
BasicPort data_port(std::string(DECODER_DATA_PORT_NAME), data_size);
|
||||||
|
module_manager.add_port(module_id, data_port, ModuleManager::MODULE_OUTPUT_PORT);
|
||||||
|
|
||||||
|
/* Data port is registered. It should be outputted as
|
||||||
|
* output reg [lsb:msb] data
|
||||||
|
*/
|
||||||
|
module_manager.set_port_is_register(module_id, data_port.get_name(), true);
|
||||||
|
/* Add data_in port */
|
||||||
|
if (true == decoder_lib.use_data_inv_port(decoder)) {
|
||||||
|
BasicPort data_inv_port(std::string(DECODER_DATA_INV_PORT_NAME), data_size);
|
||||||
|
module_manager.add_port(module_id, data_inv_port, ModuleManager::MODULE_OUTPUT_PORT);
|
||||||
|
}
|
||||||
|
|
||||||
|
return module_id;
|
||||||
|
}
|
||||||
|
|
||||||
/***************************************************************************************
|
/***************************************************************************************
|
||||||
* Create a module for a decoder with a given output size
|
* Create a module for a decoder with a given output size
|
||||||
*
|
*
|
||||||
|
@ -44,7 +100,7 @@ void build_mux_local_decoder_module(ModuleManager& module_manager,
|
||||||
size_t addr_size = decoder_lib.addr_size(decoder);
|
size_t addr_size = decoder_lib.addr_size(decoder);
|
||||||
size_t data_size = decoder_lib.data_size(decoder);
|
size_t data_size = decoder_lib.data_size(decoder);
|
||||||
|
|
||||||
/* TODO: create a name for the local encoder */
|
/* Create a name for the local encoder */
|
||||||
std::string module_name = generate_mux_local_decoder_subckt_name(addr_size, data_size);
|
std::string module_name = generate_mux_local_decoder_subckt_name(addr_size, data_size);
|
||||||
|
|
||||||
/* Create a Verilog Module based on the circuit model, and add to module manager */
|
/* Create a Verilog Module based on the circuit model, and add to module manager */
|
||||||
|
@ -67,7 +123,6 @@ void build_mux_local_decoder_module(ModuleManager& module_manager,
|
||||||
module_manager.add_port(module_id, data_inv_port, ModuleManager::MODULE_OUTPUT_PORT);
|
module_manager.add_port(module_id, data_inv_port, ModuleManager::MODULE_OUTPUT_PORT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************************
|
/***************************************************************************************
|
||||||
* This function will generate all the unique Verilog modules of local decoders for
|
* This function will generate all the unique Verilog modules of local decoders for
|
||||||
* the multiplexers used in a FPGA fabric
|
* the multiplexers used in a FPGA fabric
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
* Include header files that are required by function declaration
|
* Include header files that are required by function declaration
|
||||||
*******************************************************************/
|
*******************************************************************/
|
||||||
#include "module_manager.h"
|
#include "module_manager.h"
|
||||||
|
#include "decoder_library.h"
|
||||||
#include "mux_library.h"
|
#include "mux_library.h"
|
||||||
#include "circuit_library.h"
|
#include "circuit_library.h"
|
||||||
|
|
||||||
|
@ -15,6 +16,10 @@
|
||||||
/* begin namespace openfpga */
|
/* begin namespace openfpga */
|
||||||
namespace openfpga {
|
namespace openfpga {
|
||||||
|
|
||||||
|
ModuleId build_frame_memory_decoder_module(ModuleManager& module_manager,
|
||||||
|
const DecoderLibrary& decoder_lib,
|
||||||
|
const DecoderId& decoder);
|
||||||
|
|
||||||
void build_mux_local_decoder_modules(ModuleManager& module_manager,
|
void build_mux_local_decoder_modules(ModuleManager& module_manager,
|
||||||
const MuxLibrary& mux_lib,
|
const MuxLibrary& mux_lib,
|
||||||
const CircuitLibrary& circuit_lib);
|
const CircuitLibrary& circuit_lib);
|
||||||
|
|
|
@ -27,8 +27,9 @@ namespace openfpga {
|
||||||
* for a FPGA fabric
|
* for a FPGA fabric
|
||||||
*******************************************************************/
|
*******************************************************************/
|
||||||
ModuleManager build_device_module_graph(IoLocationMap& io_location_map,
|
ModuleManager build_device_module_graph(IoLocationMap& io_location_map,
|
||||||
const DeviceContext& vpr_device_ctx,
|
DecoderLibrary& decoder_lib,
|
||||||
const OpenfpgaContext& openfpga_ctx,
|
const OpenfpgaContext& openfpga_ctx,
|
||||||
|
const DeviceContext& vpr_device_ctx,
|
||||||
const bool& compress_routing,
|
const bool& compress_routing,
|
||||||
const bool& duplicate_grid_pin,
|
const bool& duplicate_grid_pin,
|
||||||
const bool& verbose) {
|
const bool& verbose) {
|
||||||
|
@ -66,7 +67,9 @@ ModuleManager build_device_module_graph(IoLocationMap& io_location_map,
|
||||||
build_wire_modules(module_manager, openfpga_ctx.arch().circuit_lib);
|
build_wire_modules(module_manager, openfpga_ctx.arch().circuit_lib);
|
||||||
|
|
||||||
/* Build memory modules */
|
/* Build memory modules */
|
||||||
build_memory_modules(module_manager, openfpga_ctx.mux_lib(),
|
build_memory_modules(module_manager,
|
||||||
|
decoder_lib,
|
||||||
|
openfpga_ctx.mux_lib(),
|
||||||
openfpga_ctx.arch().circuit_lib,
|
openfpga_ctx.arch().circuit_lib,
|
||||||
openfpga_ctx.arch().config_protocol.type());
|
openfpga_ctx.arch().config_protocol.type());
|
||||||
|
|
||||||
|
|
|
@ -15,8 +15,9 @@
|
||||||
namespace openfpga {
|
namespace openfpga {
|
||||||
|
|
||||||
ModuleManager build_device_module_graph(IoLocationMap& io_location_map,
|
ModuleManager build_device_module_graph(IoLocationMap& io_location_map,
|
||||||
const DeviceContext& vpr_device_ctx,
|
DecoderLibrary& decoder_lib,
|
||||||
const OpenfpgaContext& openfpga_ctx,
|
const OpenfpgaContext& openfpga_ctx,
|
||||||
|
const DeviceContext& vpr_device_ctx,
|
||||||
const bool& compress_routing,
|
const bool& compress_routing,
|
||||||
const bool& duplicate_grid_pin,
|
const bool& duplicate_grid_pin,
|
||||||
const bool& verbose);
|
const bool& verbose);
|
||||||
|
|
|
@ -15,12 +15,14 @@
|
||||||
#include "mux_graph.h"
|
#include "mux_graph.h"
|
||||||
#include "module_manager.h"
|
#include "module_manager.h"
|
||||||
#include "circuit_library_utils.h"
|
#include "circuit_library_utils.h"
|
||||||
|
#include "decoder_library_utils.h"
|
||||||
#include "module_manager_utils.h"
|
#include "module_manager_utils.h"
|
||||||
#include "mux_utils.h"
|
#include "mux_utils.h"
|
||||||
|
|
||||||
#include "openfpga_reserved_words.h"
|
#include "openfpga_reserved_words.h"
|
||||||
#include "openfpga_naming.h"
|
#include "openfpga_naming.h"
|
||||||
|
|
||||||
|
#include "build_decoder_modules.h"
|
||||||
#include "build_memory_modules.h"
|
#include "build_memory_modules.h"
|
||||||
|
|
||||||
/* begin namespace openfpga */
|
/* begin namespace openfpga */
|
||||||
|
@ -553,6 +555,178 @@ void build_memory_bank_module(ModuleManager& module_manager,
|
||||||
add_module_global_ports_from_child_modules(module_manager, mem_module);
|
add_module_global_ports_from_child_modules(module_manager, mem_module);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
* Frame-based Memory organization
|
||||||
|
*
|
||||||
|
* EN Address Data
|
||||||
|
* | | |
|
||||||
|
* v v v
|
||||||
|
* +------------------------------------+
|
||||||
|
* | Address Decoder |
|
||||||
|
* +------------------------------------+
|
||||||
|
* | | |
|
||||||
|
* v v v
|
||||||
|
* +-------+ +-------+ +-------+
|
||||||
|
* | SRAM | | SRAM | ... | SRAM |
|
||||||
|
* | [0] | | [1] | | [N-1] |
|
||||||
|
* +-------+ +-------+ +-------+
|
||||||
|
* | | ... |
|
||||||
|
* v v v
|
||||||
|
* +------------------------------------+
|
||||||
|
* | Multiplexer Configuration port |
|
||||||
|
*
|
||||||
|
********************************************************************/
|
||||||
|
static
|
||||||
|
void build_frame_memory_module(ModuleManager& module_manager,
|
||||||
|
DecoderLibrary& frame_decoder_lib,
|
||||||
|
const CircuitLibrary& circuit_lib,
|
||||||
|
const std::string& module_name,
|
||||||
|
const CircuitModelId& sram_model,
|
||||||
|
const size_t& num_mems) {
|
||||||
|
|
||||||
|
/* Get the global ports required by the SRAM */
|
||||||
|
std::vector<enum e_circuit_model_port_type> global_port_types;
|
||||||
|
global_port_types.push_back(CIRCUIT_MODEL_PORT_CLOCK);
|
||||||
|
global_port_types.push_back(CIRCUIT_MODEL_PORT_INPUT);
|
||||||
|
std::vector<CircuitPortId> sram_global_ports = circuit_lib.model_global_ports_by_type(sram_model, global_port_types, true, false);
|
||||||
|
/* Get the input ports from the SRAM */
|
||||||
|
std::vector<CircuitPortId> sram_input_ports = circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_INPUT, true);
|
||||||
|
/* A SRAM cell with BL/WL should not have any input */
|
||||||
|
VTR_ASSERT( 0 == sram_input_ports.size() );
|
||||||
|
|
||||||
|
/* Get the output ports from the SRAM */
|
||||||
|
std::vector<CircuitPortId> sram_output_ports = circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_OUTPUT, true);
|
||||||
|
|
||||||
|
/* Get the BL/WL ports from the SRAM
|
||||||
|
* Here, we consider that the WL port will be EN signal of a SRAM
|
||||||
|
* and the BL port will be the data_in signal of a SRAM
|
||||||
|
*/
|
||||||
|
std::vector<CircuitPortId> sram_bl_ports = circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_BL, true);
|
||||||
|
std::vector<CircuitPortId> sram_blb_ports = circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_BLB, true);
|
||||||
|
std::vector<CircuitPortId> sram_wl_ports = circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_WL, true);
|
||||||
|
std::vector<CircuitPortId> sram_wlb_ports = circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_WLB, true);
|
||||||
|
|
||||||
|
/* We do NOT expect any BLB port here!!!
|
||||||
|
* TODO: to suppor this, we need an inverter circuit model to be specified by users !!!
|
||||||
|
*/
|
||||||
|
VTR_ASSERT(1 == sram_bl_ports.size());
|
||||||
|
VTR_ASSERT(1 == circuit_lib.port_size(sram_bl_ports[0]));
|
||||||
|
VTR_ASSERT(1 == sram_wl_ports.size());
|
||||||
|
VTR_ASSERT(1 == circuit_lib.port_size(sram_wl_ports[0]));
|
||||||
|
VTR_ASSERT(0 == sram_blb_ports.size());
|
||||||
|
|
||||||
|
/* Create a module and add to the module manager */
|
||||||
|
ModuleId mem_module = module_manager.add_module(module_name);
|
||||||
|
VTR_ASSERT(true == module_manager.valid_module_id(mem_module));
|
||||||
|
|
||||||
|
/* Find the specification of the decoder:
|
||||||
|
* Size of address port and data input
|
||||||
|
*/
|
||||||
|
size_t addr_size = find_mux_local_decoder_addr_size(num_mems);
|
||||||
|
/* Data input should match the WL (data_in) of a SRAM */
|
||||||
|
size_t data_size = num_mems * circuit_lib.port_size(sram_bl_ports[0]);
|
||||||
|
bool use_data_inv = (0 < sram_blb_ports.size());
|
||||||
|
|
||||||
|
/* Search the decoder library
|
||||||
|
* If we find one, we use the module.
|
||||||
|
* Otherwise, we create one and add it to the decoder library
|
||||||
|
*/
|
||||||
|
DecoderId decoder_id = frame_decoder_lib.find_decoder(addr_size, data_size, true, true, use_data_inv);
|
||||||
|
if (DecoderId::INVALID() == decoder_id) {
|
||||||
|
decoder_id = frame_decoder_lib.add_decoder(addr_size, data_size, true, true, use_data_inv);
|
||||||
|
}
|
||||||
|
VTR_ASSERT(DecoderId::INVALID() != decoder_id);
|
||||||
|
|
||||||
|
/* Create a module if not existed yet */
|
||||||
|
std::string decoder_module_name = generate_frame_memory_decoder_subckt_name(addr_size, data_size);
|
||||||
|
ModuleId decoder_module = module_manager.find_module(decoder_module_name);
|
||||||
|
if (ModuleId::INVALID() == decoder_module) {
|
||||||
|
decoder_module = build_frame_memory_decoder_module(module_manager,
|
||||||
|
frame_decoder_lib,
|
||||||
|
decoder_id);
|
||||||
|
}
|
||||||
|
VTR_ASSERT(ModuleId::INVALID() != decoder_module);
|
||||||
|
|
||||||
|
/* Add module ports */
|
||||||
|
/* Input: Enable port */
|
||||||
|
BasicPort en_port(std::string(DECODER_ENABLE_PORT_NAME), 1);
|
||||||
|
ModulePortId mem_en_port = module_manager.add_port(mem_module, en_port, ModuleManager::MODULE_INPUT_PORT);
|
||||||
|
|
||||||
|
/* Input: Address port */
|
||||||
|
BasicPort addr_port(std::string(DECODER_ADDRESS_PORT_NAME), addr_size);
|
||||||
|
ModulePortId mem_addr_port = module_manager.add_port(mem_module, addr_port, ModuleManager::MODULE_INPUT_PORT);
|
||||||
|
|
||||||
|
/* Input: Data port */
|
||||||
|
BasicPort data_port(std::string(DECODER_DATA_PORT_NAME), data_size);
|
||||||
|
ModulePortId mem_data_port = module_manager.add_port(mem_module, data_port, ModuleManager::MODULE_INPUT_PORT);
|
||||||
|
|
||||||
|
/* Add each output port: port width should match the number of memories */
|
||||||
|
for (const auto& port : sram_output_ports) {
|
||||||
|
BasicPort output_port(circuit_lib.port_prefix(port), num_mems * circuit_lib.port_size(port));
|
||||||
|
module_manager.add_port(mem_module, output_port, ModuleManager::MODULE_OUTPUT_PORT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Instanciate the decoder module here */
|
||||||
|
VTR_ASSERT(0 == module_manager.num_instance(mem_module, decoder_module));
|
||||||
|
module_manager.add_child_module(mem_module, decoder_module);
|
||||||
|
|
||||||
|
/* Find the sram module in the module manager */
|
||||||
|
ModuleId sram_mem_module = module_manager.find_module(circuit_lib.model_name(sram_model));
|
||||||
|
|
||||||
|
/* Build module nets */
|
||||||
|
/* Wire enable port to decoder enable port */
|
||||||
|
ModulePortId decoder_en_port = module_manager.find_module_port(decoder_module, std::string(DECODER_ENABLE_PORT_NAME));
|
||||||
|
add_module_bus_nets(module_manager, mem_module,
|
||||||
|
mem_module, 0, mem_en_port,
|
||||||
|
decoder_module, 0, decoder_en_port);
|
||||||
|
|
||||||
|
/* Wire address port to decoder address port */
|
||||||
|
ModulePortId decoder_addr_port = module_manager.find_module_port(decoder_module, std::string(DECODER_ADDRESS_PORT_NAME));
|
||||||
|
add_module_bus_nets(module_manager, mem_module,
|
||||||
|
mem_module, 0, mem_addr_port,
|
||||||
|
decoder_module, 0, decoder_addr_port);
|
||||||
|
|
||||||
|
/* Instanciate each submodule */
|
||||||
|
for (size_t i = 0; i < num_mems; ++i) {
|
||||||
|
/* Memory seed module instanciation */
|
||||||
|
size_t sram_instance = module_manager.num_instance(mem_module, sram_mem_module);
|
||||||
|
module_manager.add_child_module(mem_module, sram_mem_module);
|
||||||
|
|
||||||
|
/* Wire data_in port to SRAM BL port */
|
||||||
|
ModulePortId sram_bl_port = module_manager.find_module_port(sram_mem_module, circuit_lib.port_lib_name(sram_bl_ports[0]));
|
||||||
|
add_module_bus_nets(module_manager, mem_module,
|
||||||
|
mem_module, 0, mem_data_port,
|
||||||
|
sram_mem_module, sram_instance, sram_bl_port);
|
||||||
|
|
||||||
|
/* Wire decoder data_out port to sram WL ports */
|
||||||
|
ModulePortId sram_wl_port = module_manager.find_module_port(sram_mem_module, circuit_lib.port_lib_name(sram_wl_ports[0]));
|
||||||
|
ModulePortId decoder_data_port = module_manager.find_module_port(decoder_module, std::string(DECODER_DATA_PORT_NAME));
|
||||||
|
ModuleNetId wl_net = module_manager.create_module_net(mem_module);
|
||||||
|
/* Source node of the input net is the input of memory module */
|
||||||
|
module_manager.add_module_net_source(mem_module, wl_net, decoder_module, 0, decoder_data_port, sram_instance);
|
||||||
|
module_manager.add_module_net_sink(mem_module, wl_net, sram_mem_module, sram_instance, sram_wl_port, 0);
|
||||||
|
|
||||||
|
/* Optional: Wire decoder data_out inverted port to sram WLB ports */
|
||||||
|
if (true == use_data_inv) {
|
||||||
|
ModulePortId sram_wlb_port = module_manager.find_module_port(sram_mem_module, circuit_lib.port_lib_name(sram_wlb_ports[0]));
|
||||||
|
ModulePortId decoder_data_inv_port = module_manager.find_module_port(decoder_module, std::string(DECODER_DATA_INV_PORT_NAME));
|
||||||
|
ModuleNetId wlb_net = module_manager.create_module_net(mem_module);
|
||||||
|
/* Source node of the input net is the input of memory module */
|
||||||
|
module_manager.add_module_net_source(mem_module, wlb_net, decoder_module, 0, decoder_data_inv_port, sram_instance);
|
||||||
|
module_manager.add_module_net_sink(mem_module, wlb_net, sram_mem_module, sram_instance, sram_wlb_port, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wire inputs of parent module to outputs of child modules */
|
||||||
|
add_module_output_nets_to_mem_modules(module_manager, mem_module, circuit_lib, sram_output_ports, sram_mem_module, i, sram_instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add global ports to the pb_module:
|
||||||
|
* This is a much easier job after adding sub modules (instances),
|
||||||
|
* we just need to find all the global ports from the child modules and build a list of it
|
||||||
|
*/
|
||||||
|
add_module_global_ports_from_child_modules(module_manager, mem_module);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
* Generate Verilog modules for the memories that are used
|
* Generate Verilog modules for the memories that are used
|
||||||
|
@ -566,6 +740,7 @@ void build_memory_bank_module(ModuleManager& module_manager,
|
||||||
********************************************************************/
|
********************************************************************/
|
||||||
static
|
static
|
||||||
void build_memory_module(ModuleManager& module_manager,
|
void build_memory_module(ModuleManager& module_manager,
|
||||||
|
DecoderLibrary& arch_decoder_lib,
|
||||||
const CircuitLibrary& circuit_lib,
|
const CircuitLibrary& circuit_lib,
|
||||||
const e_config_protocol_type& sram_orgz_type,
|
const e_config_protocol_type& sram_orgz_type,
|
||||||
const std::string& module_name,
|
const std::string& module_name,
|
||||||
|
@ -584,8 +759,13 @@ void build_memory_module(ModuleManager& module_manager,
|
||||||
build_memory_bank_module(module_manager, circuit_lib,
|
build_memory_bank_module(module_manager, circuit_lib,
|
||||||
module_name, sram_model, num_mems);
|
module_name, sram_model, num_mems);
|
||||||
break;
|
break;
|
||||||
|
case CONFIG_MEM_FRAME_BASED:
|
||||||
|
build_frame_memory_module(module_manager, arch_decoder_lib, circuit_lib,
|
||||||
|
module_name, sram_model, num_mems);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
VTR_LOGF_ERROR(__FILE__, __LINE__, "Invalid SRAM organization!\n");
|
VTR_LOGF_ERROR(__FILE__, __LINE__,
|
||||||
|
"Invalid configurable memory organization!\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -606,6 +786,7 @@ void build_memory_module(ModuleManager& module_manager,
|
||||||
********************************************************************/
|
********************************************************************/
|
||||||
static
|
static
|
||||||
void build_mux_memory_module(ModuleManager& module_manager,
|
void build_mux_memory_module(ModuleManager& module_manager,
|
||||||
|
DecoderLibrary& arch_decoder_lib,
|
||||||
const CircuitLibrary& circuit_lib,
|
const CircuitLibrary& circuit_lib,
|
||||||
const e_config_protocol_type& sram_orgz_type,
|
const e_config_protocol_type& sram_orgz_type,
|
||||||
const CircuitModelId& mux_model,
|
const CircuitModelId& mux_model,
|
||||||
|
@ -626,7 +807,8 @@ void build_mux_memory_module(ModuleManager& module_manager,
|
||||||
std::vector<CircuitModelId> sram_models = find_circuit_sram_models(circuit_lib, mux_model);
|
std::vector<CircuitModelId> sram_models = find_circuit_sram_models(circuit_lib, mux_model);
|
||||||
VTR_ASSERT( 1 == sram_models.size() );
|
VTR_ASSERT( 1 == sram_models.size() );
|
||||||
|
|
||||||
build_memory_module(module_manager, circuit_lib, sram_orgz_type, module_name, sram_models[0], num_config_bits);
|
build_memory_module(module_manager, arch_decoder_lib,
|
||||||
|
circuit_lib, sram_orgz_type, module_name, sram_models[0], num_config_bits);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CIRCUIT_MODEL_DESIGN_RRAM:
|
case CIRCUIT_MODEL_DESIGN_RRAM:
|
||||||
|
@ -659,6 +841,7 @@ void build_mux_memory_module(ModuleManager& module_manager,
|
||||||
* memory-bank organization for the memories.
|
* memory-bank organization for the memories.
|
||||||
********************************************************************/
|
********************************************************************/
|
||||||
void build_memory_modules(ModuleManager& module_manager,
|
void build_memory_modules(ModuleManager& module_manager,
|
||||||
|
DecoderLibrary& arch_decoder_lib,
|
||||||
const MuxLibrary& mux_lib,
|
const MuxLibrary& mux_lib,
|
||||||
const CircuitLibrary& circuit_lib,
|
const CircuitLibrary& circuit_lib,
|
||||||
const e_config_protocol_type& sram_orgz_type) {
|
const e_config_protocol_type& sram_orgz_type) {
|
||||||
|
@ -676,7 +859,8 @@ void build_memory_modules(ModuleManager& module_manager,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* Create a Verilog module for the memories used by the multiplexer */
|
/* Create a Verilog module for the memories used by the multiplexer */
|
||||||
build_mux_memory_module(module_manager, circuit_lib, sram_orgz_type, mux_model, mux_graph);
|
build_mux_memory_module(module_manager, arch_decoder_lib,
|
||||||
|
circuit_lib, sram_orgz_type, mux_model, mux_graph);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create the memory circuits for non-MUX circuit models.
|
/* Create the memory circuits for non-MUX circuit models.
|
||||||
|
@ -708,7 +892,8 @@ void build_memory_modules(ModuleManager& module_manager,
|
||||||
std::string module_name = generate_memory_module_name(circuit_lib, model, sram_models[0], std::string(MEMORY_MODULE_POSTFIX));
|
std::string module_name = generate_memory_module_name(circuit_lib, model, sram_models[0], std::string(MEMORY_MODULE_POSTFIX));
|
||||||
|
|
||||||
/* Create a Verilog module for the memories used by the circuit model */
|
/* Create a Verilog module for the memories used by the circuit model */
|
||||||
build_memory_module(module_manager, circuit_lib, sram_orgz_type, module_name, sram_models[0], num_mems);
|
build_memory_module(module_manager, arch_decoder_lib,
|
||||||
|
circuit_lib, sram_orgz_type, module_name, sram_models[0], num_mems);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
/********************************************************************
|
/********************************************************************
|
||||||
* Include header files that are required by function declaration
|
* Include header files that are required by function declaration
|
||||||
*******************************************************************/
|
*******************************************************************/
|
||||||
|
#include "decoder_library.h"
|
||||||
#include "circuit_library.h"
|
#include "circuit_library.h"
|
||||||
#include "mux_library.h"
|
#include "mux_library.h"
|
||||||
#include "module_manager.h"
|
#include "module_manager.h"
|
||||||
|
@ -16,6 +17,7 @@
|
||||||
namespace openfpga {
|
namespace openfpga {
|
||||||
|
|
||||||
void build_memory_modules(ModuleManager& module_manager,
|
void build_memory_modules(ModuleManager& module_manager,
|
||||||
|
DecoderLibrary& arch_decoder_lib,
|
||||||
const MuxLibrary& mux_lib,
|
const MuxLibrary& mux_lib,
|
||||||
const CircuitLibrary& circuit_lib,
|
const CircuitLibrary& circuit_lib,
|
||||||
const e_config_protocol_type& sram_orgz_type);
|
const e_config_protocol_type& sram_orgz_type);
|
||||||
|
|
|
@ -1227,6 +1227,66 @@ size_t find_module_num_config_bits_from_child_modules(ModuleManager& module_mana
|
||||||
return num_config_bits;
|
return num_config_bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Add a bus of nets to a module (cur_module_id)
|
||||||
|
* Note:
|
||||||
|
* - both src and des module should exist in the module manager
|
||||||
|
* - src_module should be the cur_module or a child of it
|
||||||
|
* - des_module should be the cur_module or a child of it
|
||||||
|
* - src_instance should be valid and des_instance should be valid as well
|
||||||
|
* - src port size should match the des port size
|
||||||
|
*******************************************************************/
|
||||||
|
void add_module_bus_nets(ModuleManager& module_manager,
|
||||||
|
const ModuleId& cur_module_id,
|
||||||
|
const ModuleId& src_module_id,
|
||||||
|
const size_t& src_instance_id,
|
||||||
|
const ModulePortId& src_module_port_id,
|
||||||
|
const ModuleId& des_module_id,
|
||||||
|
const size_t& des_instance_id,
|
||||||
|
const ModulePortId& des_module_port_id) {
|
||||||
|
|
||||||
|
VTR_ASSERT(true == module_manager.valid_module_id(cur_module_id));
|
||||||
|
VTR_ASSERT(true == module_manager.valid_module_id(src_module_id));
|
||||||
|
VTR_ASSERT(true == module_manager.valid_module_id(des_module_id));
|
||||||
|
|
||||||
|
VTR_ASSERT(true == module_manager.valid_module_port_id(src_module_id, src_module_port_id));
|
||||||
|
VTR_ASSERT(true == module_manager.valid_module_port_id(des_module_id, des_module_port_id));
|
||||||
|
|
||||||
|
if (src_module_id == cur_module_id) {
|
||||||
|
VTR_ASSERT(0 == src_instance_id);
|
||||||
|
} else {
|
||||||
|
VTR_ASSERT(src_instance_id < module_manager.num_instance(cur_module_id, src_module_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (des_module_id == cur_module_id) {
|
||||||
|
VTR_ASSERT(0 == des_instance_id);
|
||||||
|
} else {
|
||||||
|
VTR_ASSERT(des_instance_id < module_manager.num_instance(cur_module_id, des_module_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
const BasicPort& src_port = module_manager.module_port(src_module_id, src_module_port_id);
|
||||||
|
const BasicPort& des_port = module_manager.module_port(des_module_id, des_module_port_id);
|
||||||
|
|
||||||
|
if (src_port.get_width() != des_port.get_width()) {
|
||||||
|
VTR_LOGF_ERROR(__FILE__, __LINE__,
|
||||||
|
"Unmatched port size: src_port is %lu while des_port is %lu!\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create a net for each pin */
|
||||||
|
for (size_t pin_id = 0; pin_id < src_port.pins().size(); ++pin_id) {
|
||||||
|
ModuleNetId net = module_manager.module_instance_port_net(cur_module_id,
|
||||||
|
src_module_id, src_instance_id,
|
||||||
|
src_module_port_id, src_port.pins()[pin_id]);
|
||||||
|
if (ModuleNetId::INVALID() == net) {
|
||||||
|
net = module_manager.create_module_net(cur_module_id);
|
||||||
|
}
|
||||||
|
/* Configure the net source */
|
||||||
|
module_manager.add_module_net_source(cur_module_id, net, src_module_id, src_instance_id, src_module_port_id, src_port.pins()[pin_id]);
|
||||||
|
/* Configure the net sink */
|
||||||
|
module_manager.add_module_net_sink(cur_module_id, net, des_module_id, des_instance_id, des_module_port_id, des_port.pins()[pin_id]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/********************************************************************
|
/********************************************************************
|
||||||
* TODO:
|
* TODO:
|
||||||
|
|
|
@ -129,6 +129,15 @@ size_t find_module_num_config_bits_from_child_modules(ModuleManager& module_mana
|
||||||
const CircuitModelId& sram_model,
|
const CircuitModelId& sram_model,
|
||||||
const e_config_protocol_type& sram_orgz_type);
|
const e_config_protocol_type& sram_orgz_type);
|
||||||
|
|
||||||
|
void add_module_bus_nets(ModuleManager& module_manager,
|
||||||
|
const ModuleId& cur_module_id,
|
||||||
|
const ModuleId& src_module_id,
|
||||||
|
const size_t& src_instance_id,
|
||||||
|
const ModulePortId& src_module_port_id,
|
||||||
|
const ModuleId& des_module_id,
|
||||||
|
const size_t& des_instance_id,
|
||||||
|
const ModulePortId& des_module_port_id);
|
||||||
|
|
||||||
} /* end namespace openfpga */
|
} /* end namespace openfpga */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue