debugging LUT bitstream generation

This commit is contained in:
tangxifan 2020-02-25 23:29:16 -07:00
parent 4024ed63cb
commit 075264e3e3
2 changed files with 113 additions and 5 deletions

View File

@ -2,6 +2,7 @@
* This file includes functions that are used for building bitstreams
* for grids (CLBs, heterogenerous blocks, I/Os, etc.)
*******************************************************************/
#include <cmath>
#include <string>
/* Headers from vtrutil library */
@ -22,9 +23,9 @@
#include "openfpga_naming.h"
#include "mux_bitstream_constants.h"
#include "pb_type_utils.h"
#include "lut_utils.h"
#include "build_mux_bitstream.h"
//#include "build_lut_bitstream.h"
#include "build_grid_bitstream.h"
/* begin namespace openfpga */
@ -335,6 +336,112 @@ void build_physical_block_interc_bitstream(BitstreamManager& bitstream_manager,
}
}
/********************************************************************
* Generate bitstream for a LUT and add it to bitstream manager
* This function supports both single-output and fracturable LUTs
*******************************************************************/
static
void build_lut_bitstream(BitstreamManager& bitstream_manager,
const ConfigBlockId& parent_configurable_block,
const VprDeviceAnnotation& device_annotation,
const ModuleManager& module_manager,
const CircuitLibrary& circuit_lib,
const MuxLibrary& mux_lib,
const PhysicalPb& physical_pb,
const PhysicalPbId& lut_pb_id,
t_pb_type* lut_pb_type) {
/* Ensure a valid physical pritimive pb */
if (nullptr == lut_pb_type) {
VTR_LOGF_ERROR(__FILE__, __LINE__,
"Invalid lut_pb_type!\n");
exit(1);
}
CircuitModelId lut_model = device_annotation.pb_type_circuit_model(lut_pb_type);
VTR_ASSERT(CircuitModelId::INVALID() != lut_model);
VTR_ASSERT(CIRCUIT_MODEL_LUT == circuit_lib.model_type(lut_model));
/* Find the input ports for LUT size, this is used to decode the LUT memory bits! */
std::vector<CircuitPortId> model_input_ports = circuit_lib.model_ports_by_type(lut_model, CIRCUIT_MODEL_PORT_INPUT, true);
VTR_ASSERT(1 == model_input_ports.size());
size_t lut_size = circuit_lib.port_size(model_input_ports[0]);
/* Find SRAM ports for truth tables and mode-selection */
std::vector<CircuitPortId> lut_regular_sram_ports = find_circuit_regular_sram_ports(circuit_lib, lut_model);
std::vector<CircuitPortId> lut_mode_select_ports = find_circuit_mode_select_sram_ports(circuit_lib, lut_model);
/* We should always 1 regular sram port, where truth table is loaded to */
VTR_ASSERT(1 == lut_regular_sram_ports.size());
/* We may have a port for mode select or not. This depends on if the LUT is fracturable or not */
VTR_ASSERT( (0 == lut_mode_select_ports.size())
|| (1 == lut_mode_select_ports.size()) );
std::vector<bool> lut_bitstream;
/* Generate bitstream for the LUT */
if (false == physical_pb.valid_pb_id(lut_pb_id)) {
/* An empty pb means that this is an unused LUT,
* we give an empty truth table, which are full of default values (defined by users)
*/
for (size_t i = 0; i < circuit_lib.port_size(lut_regular_sram_ports[0]); ++i) {
VTR_ASSERT( (0 == circuit_lib.port_default_value(lut_regular_sram_ports[0]))
|| (1 == circuit_lib.port_default_value(lut_regular_sram_ports[0])) );
lut_bitstream.push_back(1 == circuit_lib.port_default_value(lut_regular_sram_ports[0]));
}
} else {
VTR_ASSERT(true == physical_pb.valid_pb_id(lut_pb_id));
/* Find MUX graph correlated to the LUT */
MuxId lut_mux_id = mux_lib.mux_graph(lut_model, (size_t)pow(2., lut_size));
const MuxGraph& mux_graph = mux_lib.mux_graph(lut_mux_id);
/* Ensure the LUT MUX has the expected input and SRAM port sizes */
VTR_ASSERT(mux_graph.num_memory_bits() == lut_size);
VTR_ASSERT(mux_graph.num_inputs() == (size_t)pow(2., lut_size));
/* Generate LUT bitstream */
lut_bitstream = build_frac_lut_bitstream(circuit_lib, mux_graph,
device_annotation,
physical_pb.truth_tables(lut_pb_id),
circuit_lib.port_default_value(lut_regular_sram_ports[0]));
}
/* Generate bitstream for mode-select ports */
if (0 != lut_mode_select_ports.size()) {
std::vector<bool> mode_select_bitstream;
/* TODO: Xifan Tang: find out why some lut_pb has no mode bits!!!
* I suspect that wire LUTs are not mapped to any pb
*/
if ( (true == physical_pb.valid_pb_id(lut_pb_id))
&& (0 != physical_pb.mode_bits(lut_pb_id).size()) ) {
mode_select_bitstream = generate_mode_select_bitstream(physical_pb.mode_bits(lut_pb_id));
} else { /* get default mode_bits */
mode_select_bitstream = generate_mode_select_bitstream(device_annotation.pb_type_mode_bits(lut_pb_type));
}
/* Conjunct the mode-select bitstream to the lut bitstream */
for (const bool& bit : mode_select_bitstream) {
lut_bitstream.push_back(bit);
}
}
/* Ensure the length of bitstream matches the side of memory circuits */
std::vector<CircuitModelId> sram_models = find_circuit_sram_models(circuit_lib, lut_model);
VTR_ASSERT(1 == sram_models.size());
std::string mem_block_name = generate_memory_module_name(circuit_lib, lut_model, sram_models[0], std::string(MEMORY_MODULE_POSTFIX));
ModuleId mem_module = module_manager.find_module(mem_block_name);
VTR_ASSERT (true == module_manager.valid_module_id(mem_module));
ModulePortId mem_out_port_id = module_manager.find_module_port(mem_module, generate_configuration_chain_data_out_name());
VTR_ASSERT(lut_bitstream.size() == module_manager.module_port(mem_module, mem_out_port_id).get_width());
/* Create a block for the bitstream which corresponds to the memory module associated to the LUT */
ConfigBlockId mem_block = bitstream_manager.add_block(mem_block_name);
bitstream_manager.add_child_block(parent_configurable_block, mem_block);
/* Add the bitstream to the bitstream manager */
for (const bool& bit : lut_bitstream) {
ConfigBitId config_bit = bitstream_manager.add_bit(bit);
/* Link the memory bits to the mux mem block */
bitstream_manager.add_bit_to_block(mem_block, config_bit);
}
}
/********************************************************************
* This function generates bitstream for a physical block, which is
* a child block of a grid
@ -400,9 +507,10 @@ void rec_build_physical_block_bitstream(BitstreamManager& bitstream_manager,
/* Special case for LUT !!!
* Mapped logical block information is stored in child_pbs of this pb!!!
*/
//build_lut_bitstream(bitstream_manager, pb_configurable_block,
// module_manager, circuit_lib, mux_lib,
// physical_pb, pb_id, physical_pb_type);
build_lut_bitstream(bitstream_manager, pb_configurable_block,
device_annotation,
module_manager, circuit_lib, mux_lib,
physical_pb, pb_id, physical_pb_type);
break;
case CIRCUIT_MODEL_FF:
case CIRCUIT_MODEL_HARDLOGIC:

View File

@ -236,7 +236,7 @@ void rec_update_physical_pb_from_operating_pb(PhysicalPb& phy_pb,
VTR_ASSERT(true == phy_pb.valid_pb_id(physical_pb));
/* Set the mode bits */
phy_pb.set_mode_bits(physical_pb, device_annotation.pb_type_mode_bits(physical_pb_graph_node->pb_type));
phy_pb.set_mode_bits(physical_pb, device_annotation.pb_type_mode_bits(pb_type));
/* Find mapped atom block and add to this physical pb */
AtomBlockId atom_blk = atom_ctx.nlist.find_block(op_pb->name);