added fabric bitstream generator and fixed critical bugs in top module graph
This commit is contained in:
parent
f116351831
commit
2b06cfc3cf
|
@ -64,6 +64,29 @@ ConfigBlockId BitstreamManager::bit_parent_block(const ConfigBitId& bit_id) cons
|
|||
return bit_parent_block_ids_[bit_id];
|
||||
}
|
||||
|
||||
/* Find the child block in a bitstream manager with a given name */
|
||||
ConfigBlockId BitstreamManager::find_child_block(const ConfigBlockId& block_id,
|
||||
const std::string& child_block_name) const {
|
||||
/* Ensure the input ids are valid */
|
||||
VTR_ASSERT(true == valid_block_id(block_id));
|
||||
|
||||
std::vector<ConfigBlockId> candidates;
|
||||
|
||||
for (const ConfigBlockId& child : block_children(block_id)) {
|
||||
if (0 == child_block_name.compare(block_name(child))) {
|
||||
candidates.push_back(child);
|
||||
}
|
||||
}
|
||||
|
||||
/* We should have 0 or 1 candidate! */
|
||||
VTR_ASSERT(0 == candidates.size() || 1 == candidates.size());
|
||||
if (0 == candidates.size()) {
|
||||
/* Not found, return an invalid value */
|
||||
return ConfigBlockId::INVALID();
|
||||
}
|
||||
return candidates[0];
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Public Mutators
|
||||
******************************************************************************/
|
||||
|
|
|
@ -73,6 +73,9 @@ class BitstreamManager {
|
|||
/* Find the parent block of a bit */
|
||||
ConfigBlockId bit_parent_block(const ConfigBitId& bit_id) const;
|
||||
|
||||
/* Find the child block in a bitstream manager with a given name */
|
||||
ConfigBlockId find_child_block(const ConfigBlockId& block_id, const std::string& child_block_name) const;
|
||||
|
||||
public: /* Public Mutators */
|
||||
/* Add a new configuration bit to the bitstream manager */
|
||||
ConfigBitId add_bit(const bool& bit_value);
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "mux_library_builder.h"
|
||||
#include "build_module_graph.h"
|
||||
#include "build_device_bitstream.h"
|
||||
#include "build_fabric_bitstream.h"
|
||||
#include "bitstream_writer.h"
|
||||
|
||||
#include "spice_api.h"
|
||||
|
@ -87,14 +88,20 @@ void vpr_fpga_x2p_tool_suites(t_vpr_setup vpr_setup,
|
|||
|
||||
/* Build bitstream database if needed */
|
||||
BitstreamManager bitstream_manager;
|
||||
std::vector<ConfigBitId> fabric_bitstream;
|
||||
if ( (TRUE == vpr_setup.FPGA_SPICE_Opts.BitstreamGenOpts.gen_bitstream)
|
||||
|| (TRUE == vpr_setup.FPGA_SPICE_Opts.SpiceOpts.do_spice)
|
||||
|| (TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.dump_syn_verilog)) {
|
||||
|
||||
/* Build fabric independent bitstream */
|
||||
bitstream_manager = build_device_bitstream(vpr_setup, Arch, module_manager,
|
||||
Arch.spice->circuit_lib, mux_lib,
|
||||
device_size, grids,
|
||||
rr_switches, rr_node, device_rr_gsb);
|
||||
|
||||
/* Build fabric dependent bitstream */
|
||||
fabric_bitstream = build_fabric_dependent_bitstream(bitstream_manager, module_manager);
|
||||
|
||||
/* Write bitstream to files */
|
||||
std::string bitstream_file_path;
|
||||
|
||||
|
|
|
@ -760,6 +760,9 @@ std::string generate_grid_block_module_name(const std::string& prefix,
|
|||
|
||||
/*********************************************************************
|
||||
* Generate the instance name for a configurable memory module in a Switch Block
|
||||
* To keep a unique name in each module and also consider unique routing modules,
|
||||
* please do NOT include any coordinates in the naming!!!
|
||||
* Consider only relative coordinate, such as side!
|
||||
********************************************************************/
|
||||
std::string generate_sb_memory_instance_name(const std::string& prefix,
|
||||
const e_side& sb_side,
|
||||
|
@ -775,16 +778,18 @@ std::string generate_sb_memory_instance_name(const std::string& prefix,
|
|||
|
||||
/*********************************************************************
|
||||
* Generate the instance name for a configurable memory module in a Connection Block
|
||||
* To keep a unique name in each module and also consider unique routing modules,
|
||||
* please do NOT include any coordinates in the naming!!!
|
||||
* Consider only relative coordinate, such as side!
|
||||
********************************************************************/
|
||||
std::string generate_cb_memory_instance_name(const std::string& prefix,
|
||||
const std::vector<std::vector<t_grid_tile>>& grids,
|
||||
const vtr::Point<size_t>& coordinate,
|
||||
const e_side& cb_side,
|
||||
const size_t& pin_id,
|
||||
const std::string& postfix) {
|
||||
std::string instance_name(prefix);
|
||||
|
||||
instance_name += generate_grid_side_port_name(grids, coordinate, cb_side, pin_id);
|
||||
instance_name += Side(cb_side).to_string();
|
||||
instance_name += std::string("_ipin_") + std::to_string(pin_id);
|
||||
instance_name += postfix;
|
||||
|
||||
return instance_name;
|
||||
|
@ -793,12 +798,26 @@ std::string generate_cb_memory_instance_name(const std::string& prefix,
|
|||
/*********************************************************************
|
||||
* Generate the instance name for a configurable memory module in a
|
||||
* physical block of a grid
|
||||
* To guarentee a unique name for pb_graph pin,
|
||||
* the instance name includes the index of parent node
|
||||
* as well as the port name and pin index of this pin
|
||||
*
|
||||
* Exceptions:
|
||||
* For OUTPUT ports, due to hierarchical module organization,
|
||||
* their parent nodes will be uniquified
|
||||
* So, we should not add any index here
|
||||
********************************************************************/
|
||||
std::string generate_pb_memory_instance_name(const std::string& prefix,
|
||||
t_pb_graph_pin* pb_graph_pin,
|
||||
const std::string& postfix) {
|
||||
std::string instance_name(prefix);
|
||||
instance_name += std::string(pb_graph_pin->parent_node->pb_type->name);
|
||||
|
||||
if (IN_PORT == pb_graph_pin->port->type) {
|
||||
instance_name += std::string("_");
|
||||
instance_name += std::to_string(pb_graph_pin->parent_node->placement_index);
|
||||
}
|
||||
|
||||
instance_name += std::string("_");
|
||||
instance_name += std::string(pb_graph_pin->port->name);
|
||||
instance_name += std::string("_");
|
||||
|
|
|
@ -82,8 +82,6 @@ std::string generate_sb_memory_instance_name(const std::string& prefix,
|
|||
const std::string& postfix);
|
||||
|
||||
std::string generate_cb_memory_instance_name(const std::string& prefix,
|
||||
const std::vector<std::vector<t_grid_tile>>& grids,
|
||||
const vtr::Point<size_t>& coordinate,
|
||||
const e_side& cb_side,
|
||||
const size_t& pin_id,
|
||||
const std::string& postfix);
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
#include "build_device_bitstream.h"
|
||||
|
||||
/********************************************************************
|
||||
* Top-level function to build a bistream from the FPGA device
|
||||
* A top-level function to build a bistream from the FPGA device
|
||||
* 1. It will organize the bitstream w.r.t. the hierarchy of module graphs
|
||||
* describing the FPGA fabric
|
||||
* 2. It will decode configuration bits from routing multiplexers used in
|
||||
|
@ -56,7 +56,7 @@ BitstreamManager build_device_bitstream(const t_vpr_setup& vpr_setup,
|
|||
#endif
|
||||
|
||||
/* Bistream builder formally starts*/
|
||||
vpr_printf(TIO_MESSAGE_INFO, "\nStart building bitstream for FPGA fabric...\n");
|
||||
vpr_printf(TIO_MESSAGE_INFO, "\nStart building fabric-independent bitstream for FPGA...\n");
|
||||
|
||||
/* Bitstream manager to be built */
|
||||
BitstreamManager bitstream_manager;
|
||||
|
@ -81,7 +81,7 @@ BitstreamManager build_device_bitstream(const t_vpr_setup& vpr_setup,
|
|||
build_grid_bitstream(bitstream_manager, top_block, module_manager, circuit_lib, mux_lib, device_size, grids);
|
||||
|
||||
/* Create bitstream from routing architectures */
|
||||
build_routing_bitstream(bitstream_manager, top_block, module_manager, circuit_lib, mux_lib, grids, rr_switches, L_rr_node, L_device_rr_gsb);
|
||||
build_routing_bitstream(bitstream_manager, top_block, module_manager, circuit_lib, mux_lib, rr_switches, L_rr_node, L_device_rr_gsb);
|
||||
|
||||
/* End time count */
|
||||
clock_t t_end = clock();
|
||||
|
@ -93,3 +93,5 @@ BitstreamManager build_device_bitstream(const t_vpr_setup& vpr_setup,
|
|||
|
||||
return bitstream_manager;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,135 @@
|
|||
/********************************************************************
|
||||
* This file includes functions to build fabric dependent bitstream
|
||||
*******************************************************************/
|
||||
#include <time.h>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
|
||||
#include "vtr_assert.h"
|
||||
#include "util.h"
|
||||
#include "fpga_x2p_naming.h"
|
||||
|
||||
#include "bitstream_manager_utils.h"
|
||||
#include "build_fabric_bitstream.h"
|
||||
|
||||
/********************************************************************
|
||||
* This function will walk through all the configurable children under a module
|
||||
* in a recursive way, following a Depth-First Search (DFS) strategy
|
||||
* For each configuration child, we use its instance name as a key to spot the
|
||||
* configuration bits in bitstream manager.
|
||||
* Note that it is guarentee that the instance name in module manager is
|
||||
* consistent with the block names in bitstream manager
|
||||
* We use this link to reorganize the bitstream in the sequence of memories as we stored
|
||||
* in the configurable_children) and configurable_child_instances() of each module of module manager
|
||||
*******************************************************************/
|
||||
static
|
||||
void rec_build_module_fabric_dependent_bitstream(const BitstreamManager& bitstream_manager,
|
||||
const ConfigBlockId& parent_block,
|
||||
const ModuleManager& module_manager,
|
||||
const ModuleId& parent_module,
|
||||
std::vector<ConfigBitId>& fabric_bitstream) {
|
||||
|
||||
/* Depth-first search: if we have any children in the parent_block,
|
||||
* we dive to the next level first!
|
||||
*/
|
||||
if (0 < bitstream_manager.block_children(parent_block).size()) {
|
||||
for (size_t child_id = 0; child_id < module_manager.configurable_children(parent_module).size(); ++child_id) {
|
||||
ModuleId child_module = module_manager.configurable_children(parent_module)[child_id];
|
||||
size_t child_instance = module_manager.configurable_child_instances(parent_module)[child_id];
|
||||
/* Get the instance name and ensure it is not empty */
|
||||
std::string instance_name = module_manager.instance_name(parent_module, child_module, child_instance);
|
||||
|
||||
/* Find the child block that matches the instance name! */
|
||||
ConfigBlockId child_block = bitstream_manager.find_child_block(parent_block, instance_name);
|
||||
/* We must have one valid block id! */
|
||||
if (true != bitstream_manager.valid_block_id(child_block))
|
||||
VTR_ASSERT(true == bitstream_manager.valid_block_id(child_block));
|
||||
|
||||
/* Go recursively */
|
||||
rec_build_module_fabric_dependent_bitstream(bitstream_manager, child_block,
|
||||
module_manager, child_module,
|
||||
fabric_bitstream);
|
||||
}
|
||||
/* Ensure that there should be no configuration bits in the parent block */
|
||||
VTR_ASSERT(0 == bitstream_manager.block_bits(parent_block).size());
|
||||
}
|
||||
|
||||
/* Note that, reach here, it means that this is a leaf node.
|
||||
* We add the configuration bits to the fabric_bitstream,
|
||||
* And then, we can return
|
||||
*/
|
||||
for (const ConfigBitId& config_bit : bitstream_manager.block_bits(parent_block)) {
|
||||
fabric_bitstream.push_back(config_bit);
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* A top-level function re-organizes the bitstream for a specific
|
||||
* FPGA fabric, where configuration bits are organized in the sequence
|
||||
* that can be directly loaded to the FPGA configuration protocol.
|
||||
* Support:
|
||||
* 1. Configuration chain
|
||||
* 2. Memory decoders
|
||||
* This function does NOT modify the bitstream database
|
||||
* Instead, it builds a vector of ids for configuration bits in bitstream manager
|
||||
*
|
||||
* This function can be called ONLY after the function build_device_bitstream()
|
||||
* Note that this function does NOT decode bitstreams from circuit implementation
|
||||
* It was done in the function build_device_bitstream()
|
||||
*******************************************************************/
|
||||
std::vector<ConfigBitId> build_fabric_dependent_bitstream(const BitstreamManager& bitstream_manager,
|
||||
const ModuleManager& module_manager) {
|
||||
std::vector<ConfigBitId> fabric_bitstream;
|
||||
|
||||
vpr_printf(TIO_MESSAGE_INFO, "\nBuilding fabric dependent bitstream...\n");
|
||||
|
||||
/* Start time count */
|
||||
clock_t t_start = clock();
|
||||
|
||||
/* Get the top module name in module manager, which is our starting point */
|
||||
std::string top_module_name = generate_fpga_top_module_name();
|
||||
ModuleId top_module = module_manager.find_module(top_module_name);
|
||||
VTR_ASSERT(true == module_manager.valid_module_id(top_module));
|
||||
|
||||
/* Find the top block in bitstream manager, which has not parents */
|
||||
std::vector<ConfigBlockId> top_block = find_bitstream_manager_top_blocks(bitstream_manager);
|
||||
/* Make sure we have only 1 top block and its name matches the top module */
|
||||
VTR_ASSERT(1 == top_block.size());
|
||||
VTR_ASSERT(0 == top_module_name.compare(bitstream_manager.block_name(top_block[0])));
|
||||
|
||||
rec_build_module_fabric_dependent_bitstream(bitstream_manager, top_block[0],
|
||||
module_manager, top_module,
|
||||
fabric_bitstream);
|
||||
|
||||
/* Time-consuming sanity check: Uncomment these codes only for debugging!!!
|
||||
* Check which configuration bits are not touched
|
||||
*/
|
||||
/*
|
||||
for (const ConfigBitId& config_bit : bitstream_manager.bits()) {
|
||||
std::vector<ConfigBitId>::iterator it = std::find(fabric_bitstream.begin(), fabric_bitstream.end(), config_bit);
|
||||
if (it == fabric_bitstream.end()) {
|
||||
std::vector<ConfigBlockId> block_hierarchy = find_bitstream_manager_block_hierarchy(bitstream_manager, bitstream_manager.bit_parent_block(config_bit));
|
||||
std::string block_hierarchy_name;
|
||||
for (const ConfigBlockId& temp_block : block_hierarchy) {
|
||||
block_hierarchy_name += std::string("/") + bitstream_manager.block_name(temp_block);
|
||||
}
|
||||
vpr_printf(TIO_MESSAGE_INFO,
|
||||
"bit (parent_block = %s) is not touched!\n",
|
||||
block_hierarchy_name.c_str());
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/* Ensure our fabric bitstream is in the same size as device bistream */
|
||||
VTR_ASSERT(bitstream_manager.bits().size() == fabric_bitstream.size());
|
||||
|
||||
/* End time count */
|
||||
clock_t t_end = clock();
|
||||
|
||||
float run_time_sec = (float)(t_end - t_start) / CLOCKS_PER_SEC;
|
||||
vpr_printf(TIO_MESSAGE_INFO,
|
||||
"Building fabric dependent bitstream took %g seconds\n",
|
||||
run_time_sec);
|
||||
|
||||
return fabric_bitstream;
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
#ifndef BUILD_FABRIC_BITSTREAM_H
|
||||
#define BUILD_FABRIC_BITSTREAM_H
|
||||
|
||||
#include <vector>
|
||||
#include "bitstream_manager.h"
|
||||
#include "module_manager.h"
|
||||
|
||||
std::vector<ConfigBitId> build_fabric_dependent_bitstream(const BitstreamManager& bitstream_manager,
|
||||
const ModuleManager& module_manager);
|
||||
|
||||
#endif
|
|
@ -236,7 +236,6 @@ void build_connection_block_interc_bitstream(BitstreamManager& bitstream_manager
|
|||
const ModuleManager& module_manager,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
const MuxLibrary& mux_lib,
|
||||
const std::vector<std::vector<t_grid_tile>>& grids,
|
||||
const std::vector<t_switch_inf>& rr_switches,
|
||||
t_rr_node* L_rr_node,
|
||||
const RRGSB& rr_gsb,
|
||||
|
@ -248,8 +247,7 @@ void build_connection_block_interc_bitstream(BitstreamManager& bitstream_manager
|
|||
/* No bitstream generation required by a special direct connection*/
|
||||
} else if (1 < src_rr_node->fan_in) {
|
||||
/* Create the block denoting the memory instances that drives this node in Switch Block */
|
||||
vtr::Point<size_t> ipin_coord(src_rr_node->xlow, src_rr_node->ylow);
|
||||
std::string mem_block_name = generate_cb_memory_instance_name(CONNECTION_BLOCK_MEM_INSTANCE_PREFIX, grids, ipin_coord, rr_gsb.get_ipin_node_grid_side(cb_ipin_side, ipin_index), src_rr_node->ptc_num, std::string(""));
|
||||
std::string mem_block_name = generate_cb_memory_instance_name(CONNECTION_BLOCK_MEM_INSTANCE_PREFIX, rr_gsb.get_ipin_node_grid_side(cb_ipin_side, ipin_index), src_rr_node->ptc_num, std::string(""));
|
||||
ConfigBlockId mux_mem_block = bitstream_manager.add_block(mem_block_name);
|
||||
bitstream_manager.add_child_block(cb_configurable_block, mux_mem_block);
|
||||
/* This is a routing multiplexer! Generate bitstream */
|
||||
|
@ -276,7 +274,6 @@ void build_connection_block_bitstream(BitstreamManager& bitstream_manager,
|
|||
const ModuleManager& module_manager,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
const MuxLibrary& mux_lib,
|
||||
const std::vector<std::vector<t_grid_tile>>& grids,
|
||||
const std::vector<t_switch_inf>& rr_switches,
|
||||
t_rr_node* L_rr_node,
|
||||
const RRGSB& rr_gsb,
|
||||
|
@ -291,7 +288,7 @@ void build_connection_block_bitstream(BitstreamManager& bitstream_manager,
|
|||
for (size_t inode = 0; inode < rr_gsb.get_num_ipin_nodes(cb_ipin_side); ++inode) {
|
||||
build_connection_block_interc_bitstream(bitstream_manager, cb_configurable_block,
|
||||
module_manager, circuit_lib, mux_lib,
|
||||
grids, rr_switches, L_rr_node,
|
||||
rr_switches, L_rr_node,
|
||||
rr_gsb,
|
||||
cb_ipin_side, inode);
|
||||
}
|
||||
|
@ -307,7 +304,6 @@ void build_connection_block_bitstreams(BitstreamManager& bitstream_manager,
|
|||
const ModuleManager& module_manager,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
const MuxLibrary& mux_lib,
|
||||
const std::vector<std::vector<t_grid_tile>>& grids,
|
||||
const std::vector<t_switch_inf>& rr_switches,
|
||||
t_rr_node* L_rr_node,
|
||||
const DeviceRRGSB& L_device_rr_gsb,
|
||||
|
@ -333,7 +329,7 @@ void build_connection_block_bitstreams(BitstreamManager& bitstream_manager,
|
|||
bitstream_manager.add_child_block(top_configurable_block, cb_configurable_block);
|
||||
|
||||
build_connection_block_bitstream(bitstream_manager, cb_configurable_block, module_manager,
|
||||
circuit_lib, mux_lib, grids, rr_switches, L_rr_node,
|
||||
circuit_lib, mux_lib, rr_switches, L_rr_node,
|
||||
rr_gsb, cb_type);
|
||||
}
|
||||
}
|
||||
|
@ -350,7 +346,6 @@ void build_routing_bitstream(BitstreamManager& bitstream_manager,
|
|||
const ModuleManager& module_manager,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
const MuxLibrary& mux_lib,
|
||||
const std::vector<std::vector<t_grid_tile>>& grids,
|
||||
const std::vector<t_switch_inf>& rr_switches,
|
||||
t_rr_node* L_rr_node,
|
||||
const DeviceRRGSB& L_device_rr_gsb) {
|
||||
|
@ -384,13 +379,13 @@ void build_routing_bitstream(BitstreamManager& bitstream_manager,
|
|||
vpr_printf(TIO_MESSAGE_INFO,"Generating bitstream for X-directionConnection blocks ...\n");
|
||||
|
||||
build_connection_block_bitstreams(bitstream_manager, top_configurable_block, module_manager,
|
||||
circuit_lib, mux_lib, grids, rr_switches, L_rr_node,
|
||||
circuit_lib, mux_lib, rr_switches, L_rr_node,
|
||||
L_device_rr_gsb, CHANX);
|
||||
|
||||
vpr_printf(TIO_MESSAGE_INFO,"Generating bitstream for Y-directionConnection blocks ...\n");
|
||||
|
||||
build_connection_block_bitstreams(bitstream_manager, top_configurable_block, module_manager,
|
||||
circuit_lib, mux_lib, grids, rr_switches, L_rr_node,
|
||||
circuit_lib, mux_lib, rr_switches, L_rr_node,
|
||||
L_device_rr_gsb, CHANY);
|
||||
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@ void build_routing_bitstream(BitstreamManager& bitstream_manager,
|
|||
const ModuleManager& module_manager,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
const MuxLibrary& mux_lib,
|
||||
const std::vector<std::vector<t_grid_tile>>& grids,
|
||||
const std::vector<t_switch_inf>& rr_switches,
|
||||
t_rr_node* L_rr_node,
|
||||
const DeviceRRGSB& L_device_rr_gsb);
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
* which are the leaf circuit model in the circuit library
|
||||
*******************************************************************/
|
||||
#include <vector>
|
||||
#include <ctime>
|
||||
#include "util.h"
|
||||
#include "vtr_assert.h"
|
||||
|
||||
|
@ -240,10 +241,23 @@ void build_constant_generator_module(ModuleManager& module_manager,
|
|||
* 2. GND
|
||||
********************************************************************/
|
||||
void build_constant_generator_modules(ModuleManager& module_manager) {
|
||||
/* Start time count */
|
||||
clock_t t_start = clock();
|
||||
|
||||
vpr_printf(TIO_MESSAGE_INFO,
|
||||
"Building modules for constant generator...");
|
||||
|
||||
/* VDD */
|
||||
build_constant_generator_module(module_manager, 1);
|
||||
|
||||
/* GND */
|
||||
build_constant_generator_module(module_manager, 0);
|
||||
|
||||
/* End time count */
|
||||
clock_t t_end = clock();
|
||||
|
||||
float run_time_sec = (float)(t_end - t_start) / CLOCKS_PER_SEC;
|
||||
vpr_printf(TIO_MESSAGE_INFO,
|
||||
"took %g seconds\n",
|
||||
run_time_sec);
|
||||
}
|
||||
|
|
|
@ -564,6 +564,8 @@ void add_module_pb_graph_pin_interc(ModuleManager& module_manager,
|
|||
*/
|
||||
std::string mux_mem_instance_name = generate_pb_memory_instance_name(GRID_MEM_INSTANCE_PREFIX, des_pb_graph_pin, std::string(""));
|
||||
module_manager.set_child_instance_name(pb_module, mux_mem_module, mux_mem_instance, mux_mem_instance_name);
|
||||
/* Add this MUX as a configurable child to the pb_module */
|
||||
module_manager.add_configurable_child(pb_module, mux_mem_module, mux_mem_instance);
|
||||
|
||||
/* Add nets to connect SRAM ports of the MUX to the SRAM port of memory module */
|
||||
add_module_nets_between_logic_and_memory_sram_bus(module_manager, pb_module,
|
||||
|
|
|
@ -775,8 +775,7 @@ void build_connection_block_mux_module(ModuleManager& module_manager,
|
|||
/* Give an instance name: this name should be consistent with the block name given in bitstream manager,
|
||||
* If you want to bind the bitstream generation to modules
|
||||
*/
|
||||
vtr::Point<size_t> ipin_coord(cur_rr_node->xlow, cur_rr_node->ylow);
|
||||
std::string mem_instance_name = generate_cb_memory_instance_name(CONNECTION_BLOCK_MEM_INSTANCE_PREFIX, grids, ipin_coord, rr_gsb.get_ipin_node_grid_side(cb_ipin_side, ipin_index), cur_rr_node->ptc_num, std::string(""));
|
||||
std::string mem_instance_name = generate_cb_memory_instance_name(CONNECTION_BLOCK_MEM_INSTANCE_PREFIX, rr_gsb.get_ipin_node_grid_side(cb_ipin_side, ipin_index), cur_rr_node->ptc_num, std::string(""));
|
||||
module_manager.set_child_instance_name(cb_module, mem_module, mem_instance_id, mem_instance_name);
|
||||
|
||||
/* Add nets to connect regular and mode-select SRAM ports to the SRAM port of memory module */
|
||||
|
|
|
@ -310,6 +310,7 @@ std::vector<std::vector<size_t>> add_top_module_connection_block_instances(Modul
|
|||
/* If we use compact routing hierarchy, we should instanciate the unique module of SB */
|
||||
if (true == compact_routing_hierarchy) {
|
||||
DeviceCoordinator cb_coord(ix, iy);
|
||||
/* Note: use GSB coordinate when inquire for unique modules!!! */
|
||||
const RRGSB& unique_mirror = L_device_rr_gsb.get_cb_unique_module(cb_type, cb_coord);
|
||||
cb_coordinate.set_x(unique_mirror.get_cb_x(cb_type));
|
||||
cb_coordinate.set_y(unique_mirror.get_cb_y(cb_type));
|
||||
|
@ -324,10 +325,10 @@ std::vector<std::vector<size_t>> add_top_module_connection_block_instances(Modul
|
|||
/* Set an unique name to the instance
|
||||
* Note: it is your risk to gurantee the name is unique!
|
||||
*/
|
||||
std::string cb_instance_name = generate_connection_block_module_name(cb_type, vtr::Point<size_t>(rr_gsb.get_cb_x(cb_type), rr_gsb.get_cb_y(cb_type)));
|
||||
module_manager.set_child_instance_name(top_module, cb_module,
|
||||
cb_instance_ids[rr_gsb.get_cb_x(cb_type)][rr_gsb.get_cb_y(cb_type)],
|
||||
generate_connection_block_module_name(cb_type, vtr::Point<size_t>(rr_gsb.get_cb_x(cb_type), rr_gsb.get_cb_y(cb_type))));
|
||||
|
||||
cb_instance_name);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -39,7 +39,8 @@ void organize_top_module_tile_cb_modules(ModuleManager& module_manager,
|
|||
vtr::Point<size_t> cb_coord(rr_gsb.get_cb_x(cb_type), rr_gsb.get_cb_y(cb_type));
|
||||
/* If we use compact routing hierarchy, we should instanciate the unique module of SB */
|
||||
if (true == compact_routing_hierarchy) {
|
||||
const RRGSB& unique_mirror = L_device_rr_gsb.get_cb_unique_module(cb_type, DeviceCoordinator(cb_coord.x(), cb_coord.y()));
|
||||
/* Note: use GSB coordinate when inquire for unique modules!!! */
|
||||
const RRGSB& unique_mirror = L_device_rr_gsb.get_cb_unique_module(cb_type, DeviceCoordinator(rr_gsb.get_x(), rr_gsb.get_y()));
|
||||
cb_coord.set_x(unique_mirror.get_cb_x(cb_type));
|
||||
cb_coord.set_y(unique_mirror.get_cb_y(cb_type));
|
||||
}
|
||||
|
@ -54,7 +55,8 @@ void organize_top_module_tile_cb_modules(ModuleManager& module_manager,
|
|||
if (0 < find_module_num_config_bits(module_manager, cb_module,
|
||||
circuit_lib, sram_model,
|
||||
sram_orgz_type)) {
|
||||
module_manager.add_configurable_child(top_module, cb_module, cb_instance_ids[cb_coord.x()][cb_coord.y()]);
|
||||
/* Note that use the original CB coodinate for instance id searching ! */
|
||||
module_manager.add_configurable_child(top_module, cb_module, cb_instance_ids[rr_gsb.get_cb_x(cb_type)][rr_gsb.get_cb_y(cb_type)]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -107,7 +109,7 @@ void organize_top_module_tile_memory_modules(ModuleManager& module_manager,
|
|||
if (0 < find_module_num_config_bits(module_manager, sb_module,
|
||||
circuit_lib, sram_model,
|
||||
sram_orgz_type)) {
|
||||
module_manager.add_configurable_child(top_module, sb_module, sb_instance_ids[sb_coord.x()][sb_coord.y()]);
|
||||
module_manager.add_configurable_child(top_module, sb_module, sb_instance_ids[rr_gsb.get_sb_x()][rr_gsb.get_sb_y()]);
|
||||
}
|
||||
|
||||
/* Try to find and add CBX and CBY */
|
||||
|
@ -126,6 +128,16 @@ void organize_top_module_tile_memory_modules(ModuleManager& module_manager,
|
|||
|
||||
/* Find the module name for this type of grid */
|
||||
t_type_ptr grid_type = grids[tile_coord.x()][tile_coord.y()].type;
|
||||
|
||||
/* Skip EMPTY Grid */
|
||||
if (EMPTY_TYPE == grid_type) {
|
||||
return;
|
||||
}
|
||||
/* Skip height>1 Grid, which should already been processed when offset=0 */
|
||||
if (0 < grids[tile_coord.x()][tile_coord.y()].offset) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string grid_module_name_prefix(grid_verilog_file_name_prefix);
|
||||
std::string grid_module_name = generate_grid_block_module_name(grid_module_name_prefix, std::string(grid_type->name), IO_TYPE == grid_type, tile_border_side);
|
||||
ModuleId grid_module = module_manager.find_module(grid_module_name);
|
||||
|
@ -232,10 +244,26 @@ void organize_top_module_memory_modules(ModuleManager& module_manager,
|
|||
io_coords[RIGHT].push_back(vtr::Point<size_t>(device_size.x() - 1, iy));
|
||||
}
|
||||
|
||||
/* TOP side I/Os */
|
||||
/* TOP side I/Os
|
||||
* Special case for TOP side: We need tile at ix = 0, which has a SB!!!
|
||||
*
|
||||
* TOP-LEFT CORNER of FPGA fabric
|
||||
*
|
||||
* +--------+ +-------+
|
||||
* | EMPTY | | EMPTY |
|
||||
* | Grid | | CBX |
|
||||
* | [0][x] | | |
|
||||
* +--------+ +-------+
|
||||
* +--------+ +--------+
|
||||
* | EMPTY | | SB |
|
||||
* | CBX | | [0][x] |
|
||||
* +--------+ +--------+
|
||||
*
|
||||
*/
|
||||
for (size_t ix = device_size.x() - 2; ix >= 1; --ix) {
|
||||
io_coords[TOP].push_back(vtr::Point<size_t>(ix, device_size.y() - 1));
|
||||
}
|
||||
io_coords[TOP].push_back(vtr::Point<size_t>(0, device_size.y() - 1));
|
||||
|
||||
/* LEFT side I/Os */
|
||||
for (size_t iy = device_size.y() - 2; iy >= 1; --iy) {
|
||||
|
|
Loading…
Reference in New Issue