Init support overwriting bitstream
This commit is contained in:
parent
f142c73a11
commit
2ef362d53d
|
@ -78,6 +78,12 @@ ShellCommandId add_build_arch_bitstream_command_template(
|
|||
shell_cmd.add_option("no_time_stamp", false,
|
||||
"Do not print time stamp in output files");
|
||||
|
||||
/* Add an option '--overwrite_bitstream_file' */
|
||||
CommandOptionId opt_overwrite_file =
|
||||
shell_cmd.add_option("overwrite_bitstream_file", false,
|
||||
"file path to read to overwrite bitstream bits");
|
||||
shell_cmd.set_option_require_value(opt_overwrite_file, openfpga::OPT_STRING);
|
||||
|
||||
/* Add an option '--verbose' */
|
||||
shell_cmd.add_option("verbose", false, "Enable verbose output");
|
||||
|
||||
|
|
|
@ -38,13 +38,17 @@ int fpga_bitstream_template(T& openfpga_ctx, const Command& cmd,
|
|||
CommandOptionId opt_no_time_stamp = cmd.option("no_time_stamp");
|
||||
CommandOptionId opt_write_file = cmd.option("write_file");
|
||||
CommandOptionId opt_read_file = cmd.option("read_file");
|
||||
CommandOptionId opt_overwrite_bitstream_file =
|
||||
cmd.option("overwrite_bitstream_file");
|
||||
|
||||
if (true == cmd_context.option_enable(cmd, opt_read_file)) {
|
||||
openfpga_ctx.mutable_bitstream_manager() = read_xml_architecture_bitstream(
|
||||
cmd_context.option_value(cmd, opt_read_file).c_str());
|
||||
} else {
|
||||
openfpga_ctx.mutable_bitstream_manager() = build_device_bitstream(
|
||||
g_vpr_ctx, openfpga_ctx, cmd_context.option_enable(cmd, opt_verbose));
|
||||
g_vpr_ctx, openfpga_ctx,
|
||||
cmd_context.option_value(cmd, opt_overwrite_bitstream_file),
|
||||
cmd_context.option_enable(cmd, opt_verbose));
|
||||
}
|
||||
|
||||
if (true == cmd_context.option_enable(cmd, opt_write_file)) {
|
||||
|
|
|
@ -147,9 +147,9 @@ static size_t rec_estimate_device_bitstream_num_bits(
|
|||
* of the FPGA fabric that FPGA-X2P generates!
|
||||
* But it can be used to output a generic bitstream for VPR mapping FPGA
|
||||
*******************************************************************/
|
||||
BitstreamManager build_device_bitstream(const VprContext& vpr_ctx,
|
||||
const OpenfpgaContext& openfpga_ctx,
|
||||
const bool& verbose) {
|
||||
BitstreamManager build_device_bitstream(
|
||||
const VprContext& vpr_ctx, const OpenfpgaContext& openfpga_ctx,
|
||||
const std::string& overwrite_bitstream_file, const bool& verbose) {
|
||||
std::string timer_message =
|
||||
std::string("\nBuild fabric-independent bitstream for implementation '") +
|
||||
vpr_ctx.atom().nlist.netlist_name() + std::string("'\n");
|
||||
|
@ -218,7 +218,7 @@ BitstreamManager build_device_bitstream(const VprContext& vpr_ctx,
|
|||
openfpga_ctx.vpr_device_annotation(),
|
||||
openfpga_ctx.vpr_clustering_annotation(),
|
||||
openfpga_ctx.vpr_placement_annotation(),
|
||||
openfpga_ctx.vpr_bitstream_annotation(), verbose);
|
||||
openfpga_ctx.vpr_bitstream_annotation(), overwrite_bitstream_file, verbose);
|
||||
VTR_LOGV(verbose, "Done\n");
|
||||
|
||||
/* Create bitstream from routing architectures */
|
||||
|
|
|
@ -16,9 +16,9 @@
|
|||
/* begin namespace openfpga */
|
||||
namespace openfpga {
|
||||
|
||||
BitstreamManager build_device_bitstream(const VprContext& vpr_ctx,
|
||||
const OpenfpgaContext& openfpga_ctx,
|
||||
const bool& verbose);
|
||||
BitstreamManager build_device_bitstream(
|
||||
const VprContext& vpr_ctx, const OpenfpgaContext& openfpga_ctx,
|
||||
const std::string& overwrite_bitstream_file, const bool& verbose);
|
||||
|
||||
} /* end namespace openfpga */
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
* for grids (CLBs, heterogenerous blocks, I/Os, etc.)
|
||||
*******************************************************************/
|
||||
#include <cmath>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
/* Headers from vtrutil library */
|
||||
|
@ -29,6 +30,242 @@
|
|||
/* begin namespace openfpga */
|
||||
namespace openfpga {
|
||||
|
||||
struct OVERWRITE_BITS {
|
||||
OVERWRITE_BITS(bool i, int s, int e, uint64_t b)
|
||||
: incr(i), start(s), end(e), bits(b) {}
|
||||
bool incr = true;
|
||||
int start = -1;
|
||||
int end = -1;
|
||||
uint64_t bits = 0;
|
||||
};
|
||||
|
||||
std::string M_TOP_NAME = "";
|
||||
std::string M_BLOCK_GRID_NAME = "";
|
||||
std::map<std::string, std::map<std::string, std::vector<OVERWRITE_BITS>>*>
|
||||
M_OVERWRITE_GRID_BITS;
|
||||
std::map<std::string, std::vector<OVERWRITE_BITS>>* M_OVERWRITE_BITS = nullptr;
|
||||
|
||||
/********************************************************************
|
||||
* Track the fabric top name
|
||||
*******************************************************************/
|
||||
static void track_fabric_top_name(const std::string& top) {
|
||||
VTR_ASSERT(top.size());
|
||||
M_TOP_NAME = top;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Track the fabric grid name
|
||||
*******************************************************************/
|
||||
static void track_physical_block_grid(const std::string& block) {
|
||||
VTR_ASSERT(M_TOP_NAME.size());
|
||||
VTR_ASSERT(block.size());
|
||||
M_BLOCK_GRID_NAME = M_TOP_NAME + std::string(".") + block;
|
||||
if (M_OVERWRITE_GRID_BITS.find(M_BLOCK_GRID_NAME) !=
|
||||
M_OVERWRITE_GRID_BITS.end()) {
|
||||
M_OVERWRITE_BITS = M_OVERWRITE_GRID_BITS[M_BLOCK_GRID_NAME];
|
||||
} else {
|
||||
M_OVERWRITE_BITS = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Trim whitespace
|
||||
*******************************************************************/
|
||||
static void trim_white_space(std::string& line) {
|
||||
const auto begin = line.find_first_not_of(" \t\r\n");
|
||||
if (begin != std::string::npos) {
|
||||
const auto end = line.find_last_not_of(" \t\r\n");
|
||||
const auto count = end - begin + 1;
|
||||
line = line.substr(begin, count);
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Split the line by delimiter
|
||||
*******************************************************************/
|
||||
static std::vector<std::string> split_line_by(
|
||||
std::string line, const std::string& delimiter = " \t") {
|
||||
std::vector<std::string> results;
|
||||
size_t index = line.find_first_of(delimiter);
|
||||
trim_white_space(line);
|
||||
while (index != std::string::npos) {
|
||||
std::string result = line.substr(0, index);
|
||||
trim_white_space(result);
|
||||
results.push_back(result);
|
||||
line = line.substr(index + 1);
|
||||
trim_white_space(line);
|
||||
index = line.find_first_of(delimiter);
|
||||
}
|
||||
if (line.size()) {
|
||||
results.push_back(line);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Check if the string is all number
|
||||
*******************************************************************/
|
||||
static bool is_number(const std::string& s) {
|
||||
std::string::const_iterator it = s.begin();
|
||||
while (it != s.end() && std::isdigit(*it)) ++it;
|
||||
return !s.empty() && it == s.end();
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Convert string to uint64_t
|
||||
*******************************************************************/
|
||||
static uint64_t get_number(const std::string& s) {
|
||||
uint64_t value = 0;
|
||||
std::istringstream iss(s);
|
||||
iss >> value;
|
||||
return value;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Cleanup
|
||||
*******************************************************************/
|
||||
static void cleanup_overwrite() {
|
||||
for (auto& iter : M_OVERWRITE_GRID_BITS) {
|
||||
delete iter.second;
|
||||
}
|
||||
M_OVERWRITE_GRID_BITS.clear();
|
||||
M_OVERWRITE_BITS = nullptr;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Read the overwrite file
|
||||
*******************************************************************/
|
||||
static void read_overwrite_file(const std::string& filepath) {
|
||||
cleanup_overwrite();
|
||||
if (filepath.size()) {
|
||||
std::ifstream file(filepath.c_str());
|
||||
if (file.is_open()) {
|
||||
if (file.good()) {
|
||||
std::string line = "";
|
||||
while (std::getline(file, line)) {
|
||||
trim_white_space(line);
|
||||
if (line.size() && line[0] != '#') {
|
||||
std::vector<std::string> words = split_line_by(line);
|
||||
if (words.size() >= 3 && words[0].size() > 0 &&
|
||||
words[1].size() > 0) {
|
||||
// Prepare the pointer to fillup path and bits (speedup stuff)
|
||||
M_OVERWRITE_BITS = nullptr;
|
||||
if (M_OVERWRITE_GRID_BITS.find(words[0]) !=
|
||||
M_OVERWRITE_GRID_BITS.end()) {
|
||||
M_OVERWRITE_BITS = M_OVERWRITE_GRID_BITS.at(words[0]);
|
||||
}
|
||||
std::string path = std::string(".") + words[1];
|
||||
for (size_t i = 2; i < words.size(); i++) {
|
||||
std::vector<std::string> values = split_line_by(words[i], "=");
|
||||
bool incr = true;
|
||||
int start = -1;
|
||||
int end = -1;
|
||||
uint64_t value = 0;
|
||||
if (values.size() == 1) {
|
||||
if (is_number(values[0])) {
|
||||
value = get_number(values[0]);
|
||||
} else {
|
||||
// Bad
|
||||
continue;
|
||||
}
|
||||
} else if (values.size() == 2) {
|
||||
if (values[0].size() >= 3 && values[0][0] == '[' &&
|
||||
values[0][values[0].size() - 1] == ']') {
|
||||
line = values[0].substr(1, values[0].size() - 2);
|
||||
trim_white_space(line);
|
||||
std::vector<std::string> range = split_line_by(line, ":");
|
||||
if (range.size() == 1 && is_number(range[0])) {
|
||||
start = get_number(range[0]);
|
||||
end = start;
|
||||
} else if (range.size() == 2 && is_number(range[0]) &&
|
||||
is_number(range[1])) {
|
||||
end = (int)(get_number(range[0]));
|
||||
start = (int)(get_number(range[1]));
|
||||
incr = end >= start;
|
||||
} else {
|
||||
// Bad
|
||||
continue;
|
||||
}
|
||||
if (is_number(values[1])) {
|
||||
value = get_number(values[1]);
|
||||
} else {
|
||||
// Bad
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
// Bad
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
// Bad
|
||||
continue;
|
||||
}
|
||||
if ((start == -1 && end == -1) || (start >= 0 && end >= 0)) {
|
||||
if (M_OVERWRITE_BITS == nullptr) {
|
||||
M_OVERWRITE_BITS =
|
||||
new std::map<std::string, std::vector<OVERWRITE_BITS>>;
|
||||
M_OVERWRITE_GRID_BITS[words[0]] = M_OVERWRITE_BITS;
|
||||
}
|
||||
if (M_OVERWRITE_BITS->find(path) == M_OVERWRITE_BITS->end()) {
|
||||
(*M_OVERWRITE_BITS)[path] = {};
|
||||
}
|
||||
M_OVERWRITE_BITS->at(path).push_back(
|
||||
OVERWRITE_BITS(incr, start, end, value));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
}
|
||||
M_OVERWRITE_BITS = nullptr;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Overwrite the bits
|
||||
*******************************************************************/
|
||||
static void overwrite_bits(const std::string& path, std::vector<bool>& bits) {
|
||||
VTR_ASSERT(M_OVERWRITE_BITS != nullptr);
|
||||
if (M_OVERWRITE_BITS->find(path) != M_OVERWRITE_BITS->end()) {
|
||||
for (OVERWRITE_BITS& obits : M_OVERWRITE_BITS->at(path)) {
|
||||
if (obits.start == -1 && obits.end == -1) {
|
||||
for (int i = 0; i < int(bits.size()); i++) {
|
||||
if (obits.bits & (1 << i)) {
|
||||
bits[i] = true;
|
||||
} else {
|
||||
bits[i] = false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int i = 0;
|
||||
int start = obits.start;
|
||||
while (true) {
|
||||
if (start >= 0 && start < int(bits.size())) {
|
||||
if (obits.bits & (1 << i)) {
|
||||
bits[start] = true;
|
||||
} else {
|
||||
bits[start] = false;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
if (start == obits.end) {
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
if (obits.incr) {
|
||||
start++;
|
||||
} else {
|
||||
start--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Decode mode bits "01..." to a bitstream vector
|
||||
*******************************************************************/
|
||||
|
@ -55,7 +292,7 @@ static void build_primitive_bitstream(
|
|||
const ModuleManager& module_manager, const CircuitLibrary& circuit_lib,
|
||||
const VprDeviceAnnotation& device_annotation, const PhysicalPb& physical_pb,
|
||||
const PhysicalPbId& primitive_pb_id, t_pb_type* primitive_pb_type,
|
||||
const bool& verbose) {
|
||||
std::string config_instance_path, const bool& verbose) {
|
||||
/* Ensure a valid physical pritimive pb */
|
||||
if (nullptr == primitive_pb_type) {
|
||||
VTR_LOGF_ERROR(__FILE__, __LINE__, "Invalid primitive_pb_type!\n");
|
||||
|
@ -162,6 +399,11 @@ static void build_primitive_bitstream(
|
|||
bitstream_manager.block_name(parent_configurable_block).c_str());
|
||||
|
||||
/* Add the bitstream to the bitstream manager */
|
||||
if (M_OVERWRITE_BITS != nullptr) {
|
||||
std::string path = config_instance_path + std::string(".") +
|
||||
bitstream_manager.block_name(mem_block);
|
||||
overwrite_bits(path, mode_select_bitstream);
|
||||
}
|
||||
bitstream_manager.add_block_bits(mem_block, mode_select_bitstream);
|
||||
}
|
||||
|
||||
|
@ -185,7 +427,8 @@ static void build_physical_block_pin_interc_bitstream(
|
|||
const AtomContext& atom_ctx, const VprDeviceAnnotation& device_annotation,
|
||||
const VprBitstreamAnnotation& bitstream_annotation,
|
||||
const PhysicalPb& physical_pb, t_pb_graph_pin* des_pb_graph_pin,
|
||||
t_mode* physical_mode, const bool& verbose) {
|
||||
t_mode* physical_mode, std::string config_instance_path,
|
||||
const bool& verbose) {
|
||||
/* Identify the number of fan-in (Consider interconnection edges of only
|
||||
* selected mode) */
|
||||
t_interconnect* cur_interc =
|
||||
|
@ -329,6 +572,11 @@ static void build_physical_block_pin_interc_bitstream(
|
|||
bitstream_manager.block_name(parent_configurable_block).c_str());
|
||||
|
||||
/* Add the bistream to the bitstream manager */
|
||||
if (M_OVERWRITE_BITS != nullptr) {
|
||||
std::string path = config_instance_path + std::string(".") +
|
||||
bitstream_manager.block_name(mux_mem_block);
|
||||
overwrite_bits(path, mux_bitstream);
|
||||
}
|
||||
bitstream_manager.add_block_bits(mux_mem_block, mux_bitstream);
|
||||
/* Record path ids, input and output nets */
|
||||
bitstream_manager.add_path_id_to_block(mux_mem_block, mux_input_pin_id);
|
||||
|
@ -385,7 +633,7 @@ static void build_physical_block_interc_port_bitstream(
|
|||
const VprBitstreamAnnotation& bitstream_annotation,
|
||||
t_pb_graph_node* physical_pb_graph_node, const PhysicalPb& physical_pb,
|
||||
const e_circuit_pb_port_type& pb_port_type, t_mode* physical_mode,
|
||||
const bool& verbose) {
|
||||
std::string config_instance_path, const bool& verbose) {
|
||||
switch (pb_port_type) {
|
||||
case CIRCUIT_PB_PORT_INPUT:
|
||||
for (int iport = 0; iport < physical_pb_graph_node->num_input_ports;
|
||||
|
@ -398,7 +646,7 @@ static void build_physical_block_interc_port_bitstream(
|
|||
circuit_lib, mux_lib, atom_ctx, device_annotation,
|
||||
bitstream_annotation, physical_pb,
|
||||
&(physical_pb_graph_node->input_pins[iport][ipin]), physical_mode,
|
||||
verbose);
|
||||
config_instance_path, verbose);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -413,7 +661,7 @@ static void build_physical_block_interc_port_bitstream(
|
|||
circuit_lib, mux_lib, atom_ctx, device_annotation,
|
||||
bitstream_annotation, physical_pb,
|
||||
&(physical_pb_graph_node->output_pins[iport][ipin]), physical_mode,
|
||||
verbose);
|
||||
config_instance_path, verbose);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -428,7 +676,7 @@ static void build_physical_block_interc_port_bitstream(
|
|||
circuit_lib, mux_lib, atom_ctx, device_annotation,
|
||||
bitstream_annotation, physical_pb,
|
||||
&(physical_pb_graph_node->clock_pins[iport][ipin]), physical_mode,
|
||||
verbose);
|
||||
config_instance_path, verbose);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -451,7 +699,8 @@ static void build_physical_block_interc_bitstream(
|
|||
const AtomContext& atom_ctx, const VprDeviceAnnotation& device_annotation,
|
||||
const VprBitstreamAnnotation& bitstream_annotation,
|
||||
t_pb_graph_node* physical_pb_graph_node, const PhysicalPb& physical_pb,
|
||||
t_mode* physical_mode, const bool& verbose) {
|
||||
t_mode* physical_mode, std::string config_instance_path,
|
||||
const bool& verbose) {
|
||||
/* Check if the pb_graph node is valid or not */
|
||||
if (nullptr == physical_pb_graph_node) {
|
||||
VTR_LOGF_ERROR(__FILE__, __LINE__, "Invalid physical_pb_graph_node.\n");
|
||||
|
@ -472,7 +721,8 @@ static void build_physical_block_interc_bitstream(
|
|||
bitstream_manager, grouped_mem_inst_scoreboard, parent_configurable_block,
|
||||
module_manager, module_name_map, circuit_lib, mux_lib, atom_ctx,
|
||||
device_annotation, bitstream_annotation, physical_pb_graph_node,
|
||||
physical_pb, CIRCUIT_PB_PORT_OUTPUT, physical_mode, verbose);
|
||||
physical_pb, CIRCUIT_PB_PORT_OUTPUT, physical_mode, config_instance_path,
|
||||
verbose);
|
||||
|
||||
/* We check input_pins of child_pb_graph_node and its the input_edges
|
||||
* Iterate over the interconnections between inputs of physical_pb_graph_node
|
||||
|
@ -496,14 +746,14 @@ static void build_physical_block_interc_bitstream(
|
|||
parent_configurable_block, module_manager, module_name_map, circuit_lib,
|
||||
mux_lib, atom_ctx, device_annotation, bitstream_annotation,
|
||||
child_pb_graph_node, physical_pb, CIRCUIT_PB_PORT_INPUT, physical_mode,
|
||||
verbose);
|
||||
config_instance_path, verbose);
|
||||
/* For clock pins, we should do the same work */
|
||||
build_physical_block_interc_port_bitstream(
|
||||
bitstream_manager, grouped_mem_inst_scoreboard,
|
||||
parent_configurable_block, module_manager, module_name_map, circuit_lib,
|
||||
mux_lib, atom_ctx, device_annotation, bitstream_annotation,
|
||||
child_pb_graph_node, physical_pb, CIRCUIT_PB_PORT_CLOCK, physical_mode,
|
||||
verbose);
|
||||
config_instance_path, verbose);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -519,7 +769,8 @@ static void build_lut_bitstream(
|
|||
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, const bool& verbose) {
|
||||
const PhysicalPbId& lut_pb_id, t_pb_type* lut_pb_type,
|
||||
std::string config_instance_path, const bool& verbose) {
|
||||
/* Ensure a valid physical pritimive pb */
|
||||
if (nullptr == lut_pb_type) {
|
||||
VTR_LOGF_ERROR(__FILE__, __LINE__, "Invalid lut_pb_type!\n");
|
||||
|
@ -688,6 +939,11 @@ static void build_lut_bitstream(
|
|||
bitstream_manager.block_name(parent_configurable_block).c_str());
|
||||
|
||||
/* Add the bitstream to the bitstream manager */
|
||||
if (M_OVERWRITE_BITS != nullptr) {
|
||||
std::string path = config_instance_path + std::string(".") +
|
||||
bitstream_manager.block_name(mem_block);
|
||||
overwrite_bits(path, lut_bitstream);
|
||||
}
|
||||
bitstream_manager.add_block_bits(mem_block, lut_bitstream);
|
||||
}
|
||||
|
||||
|
@ -712,7 +968,7 @@ static void rec_build_physical_block_bitstream(
|
|||
const VprBitstreamAnnotation& bitstream_annotation, const e_side& border_side,
|
||||
const PhysicalPb& physical_pb, const PhysicalPbId& pb_id,
|
||||
t_pb_graph_node* physical_pb_graph_node, const size_t& pb_graph_node_index,
|
||||
const bool& verbose) {
|
||||
std::string config_instance_path, const bool& verbose) {
|
||||
/* Get the physical pb_type that is linked to the pb_graph node */
|
||||
t_pb_type* physical_pb_type = physical_pb_graph_node->pb_type;
|
||||
|
||||
|
@ -736,6 +992,7 @@ static void rec_build_physical_block_bitstream(
|
|||
* manager */
|
||||
std::string pb_block_name = generate_physical_block_instance_name(
|
||||
physical_pb_type, pb_graph_node_index);
|
||||
config_instance_path += (std::string(".") + pb_block_name);
|
||||
/* If there are no physical memory blocks under the current module, use the
|
||||
* previous module, which is the physical memory block */
|
||||
ConfigBlockId pb_configurable_block = parent_configurable_block;
|
||||
|
@ -773,7 +1030,7 @@ static void rec_build_physical_block_bitstream(
|
|||
child_pb,
|
||||
&(physical_pb_graph_node
|
||||
->child_pb_graph_nodes[physical_mode->index][ipb][jpb]),
|
||||
jpb, verbose);
|
||||
jpb, config_instance_path, verbose);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -788,10 +1045,10 @@ static void rec_build_physical_block_bitstream(
|
|||
/* Special case for LUT !!!
|
||||
* Mapped logical block information is stored in child_pbs of this pb!!!
|
||||
*/
|
||||
build_lut_bitstream(bitstream_manager, grouped_mem_inst_scoreboard,
|
||||
pb_configurable_block, device_annotation,
|
||||
module_manager, circuit_lib, mux_lib, physical_pb,
|
||||
pb_id, physical_pb_type, verbose);
|
||||
build_lut_bitstream(
|
||||
bitstream_manager, grouped_mem_inst_scoreboard, pb_configurable_block,
|
||||
device_annotation, module_manager, circuit_lib, mux_lib, physical_pb,
|
||||
pb_id, physical_pb_type, config_instance_path, verbose);
|
||||
break;
|
||||
case CIRCUIT_MODEL_FF:
|
||||
case CIRCUIT_MODEL_HARDLOGIC:
|
||||
|
@ -800,7 +1057,7 @@ static void rec_build_physical_block_bitstream(
|
|||
build_primitive_bitstream(
|
||||
bitstream_manager, grouped_mem_inst_scoreboard, pb_configurable_block,
|
||||
module_manager, circuit_lib, device_annotation, physical_pb, pb_id,
|
||||
physical_pb_type, verbose);
|
||||
physical_pb_type, config_instance_path, verbose);
|
||||
break;
|
||||
default:
|
||||
VTR_LOGF_ERROR(__FILE__, __LINE__,
|
||||
|
@ -817,7 +1074,7 @@ static void rec_build_physical_block_bitstream(
|
|||
bitstream_manager, grouped_mem_inst_scoreboard, pb_configurable_block,
|
||||
module_manager, module_name_map, circuit_lib, mux_lib, atom_ctx,
|
||||
device_annotation, bitstream_annotation, physical_pb_graph_node,
|
||||
physical_pb, physical_mode, verbose);
|
||||
physical_pb, physical_mode, config_instance_path, verbose);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
|
@ -866,7 +1123,7 @@ static void build_physical_block_bitstream(
|
|||
std::string grid_block_name = generate_grid_block_instance_name(
|
||||
grid_module_name_prefix, std::string(grid_type->name),
|
||||
is_io_type(grid_type), border_side, grid_coord_in_unique_tile);
|
||||
|
||||
track_physical_block_grid(grid_block_name);
|
||||
ConfigBlockId grid_configurable_block =
|
||||
bitstream_manager.add_block(grid_block_name);
|
||||
bitstream_manager.add_child_block(top_block, grid_configurable_block);
|
||||
|
@ -931,7 +1188,7 @@ static void build_physical_block_bitstream(
|
|||
grid_configurable_block, module_manager, module_name_map, circuit_lib,
|
||||
mux_lib, atom_ctx, device_annotation, bitstream_annotation,
|
||||
border_side, PhysicalPb(), PhysicalPbId::INVALID(),
|
||||
lb_type->pb_graph_head, z, verbose);
|
||||
lb_type->pb_graph_head, z, "", verbose);
|
||||
} else {
|
||||
const PhysicalPb& phy_pb = cluster_annotation.physical_pb(
|
||||
place_annotation.grid_blocks(grid_coord)[z]);
|
||||
|
@ -946,7 +1203,7 @@ static void build_physical_block_bitstream(
|
|||
bitstream_manager, grouped_mem_inst_scoreboard,
|
||||
grid_configurable_block, module_manager, module_name_map, circuit_lib,
|
||||
mux_lib, atom_ctx, device_annotation, bitstream_annotation,
|
||||
border_side, phy_pb, top_pb_id, pb_graph_head, z, verbose);
|
||||
border_side, phy_pb, top_pb_id, pb_graph_head, z, "", verbose);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -966,9 +1223,13 @@ void build_grid_bitstream(
|
|||
const AtomContext& atom_ctx, const VprDeviceAnnotation& device_annotation,
|
||||
const VprClusteringAnnotation& cluster_annotation,
|
||||
const VprPlacementAnnotation& place_annotation,
|
||||
const VprBitstreamAnnotation& bitstream_annotation, const bool& verbose) {
|
||||
const VprBitstreamAnnotation& bitstream_annotation,
|
||||
const std::string& overwrite_bitstream_file, const bool& verbose) {
|
||||
VTR_LOGV(verbose, "Generating bitstream for core grids...");
|
||||
|
||||
/* Read file that might want to overwrite the bitstream */
|
||||
read_overwrite_file(overwrite_bitstream_file);
|
||||
|
||||
/* Generate bitstream for the core logic block one by one */
|
||||
for (size_t ix = 1; ix < grids.width() - 1; ++ix) {
|
||||
for (size_t iy = 1; iy < grids.height() - 1; ++iy) {
|
||||
|
@ -1002,7 +1263,7 @@ void build_grid_bitstream(
|
|||
tile_inst_name.c_str(),
|
||||
bitstream_manager.block_name(top_block).c_str());
|
||||
}
|
||||
|
||||
track_fabric_top_name(bitstream_manager.block_name(top_block));
|
||||
build_physical_block_bitstream(
|
||||
bitstream_manager, parent_block, module_manager, module_name_map,
|
||||
fabric_tile, curr_tile, circuit_lib, mux_lib, atom_ctx,
|
||||
|
@ -1050,7 +1311,7 @@ void build_grid_bitstream(
|
|||
tile_inst_name.c_str(),
|
||||
bitstream_manager.block_name(parent_block).c_str());
|
||||
}
|
||||
|
||||
track_fabric_top_name(bitstream_manager.block_name(top_block));
|
||||
build_physical_block_bitstream(
|
||||
bitstream_manager, parent_block, module_manager, module_name_map,
|
||||
fabric_tile, curr_tile, circuit_lib, mux_lib, atom_ctx,
|
||||
|
@ -1058,6 +1319,7 @@ void build_grid_bitstream(
|
|||
bitstream_annotation, grids, layer, io_coordinate, io_side, verbose);
|
||||
}
|
||||
}
|
||||
cleanup_overwrite();
|
||||
VTR_LOGV(verbose, "Done\n");
|
||||
}
|
||||
|
||||
|
|
|
@ -34,7 +34,8 @@ void build_grid_bitstream(
|
|||
const AtomContext& atom_ctx, const VprDeviceAnnotation& device_annotation,
|
||||
const VprClusteringAnnotation& cluster_annotation,
|
||||
const VprPlacementAnnotation& place_annotation,
|
||||
const VprBitstreamAnnotation& bitstream_annotation, const bool& verbose);
|
||||
const VprBitstreamAnnotation& bitstream_annotation,
|
||||
const std::string& overwrite_bitstream_file, const bool& verbose);
|
||||
|
||||
} /* end namespace openfpga */
|
||||
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
# Run VPR for the 'and' design
|
||||
#--write_rr_graph example_rr_graph.xml
|
||||
vpr ${VPR_ARCH_FILE} ${VPR_TESTBENCH_BLIF} --clock_modeling route --device ${OPENFPGA_VPR_DEVICE_LAYOUT}
|
||||
|
||||
# Read OpenFPGA architecture definition
|
||||
read_openfpga_arch -f ${OPENFPGA_ARCH_FILE}
|
||||
|
||||
# Read OpenFPGA simulation settings
|
||||
read_openfpga_simulation_setting -f ${OPENFPGA_SIM_SETTING_FILE}
|
||||
|
||||
# Annotate the OpenFPGA architecture to VPR data base
|
||||
# to debug use --verbose options
|
||||
link_openfpga_arch --activity_file ${ACTIVITY_FILE} --sort_gsb_chan_node_in_edges
|
||||
|
||||
# Check and correct any naming conflicts in the BLIF netlist
|
||||
check_netlist_naming_conflict --fix --report ./netlist_renaming.xml
|
||||
|
||||
# Apply fix-up to Look-Up Table truth tables based on packing results
|
||||
lut_truth_table_fixup
|
||||
|
||||
# Build the module graph
|
||||
# - Enabled compression on routing architecture modules
|
||||
# - Enable pin duplication on grid modules
|
||||
build_fabric --compress_routing #--verbose
|
||||
|
||||
# Write the fabric hierarchy of module graph to a file
|
||||
# This is used by hierarchical PnR flows
|
||||
write_fabric_hierarchy --file ./fabric_hierarchy.txt
|
||||
|
||||
# Repack the netlist to physical pbs
|
||||
# This must be done before bitstream generator and testbench generation
|
||||
# Strongly recommend it is done after all the fix-up have been applied
|
||||
repack #--verbose
|
||||
|
||||
# Build the bitstream
|
||||
# - Output the fabric-independent bitstream to a file
|
||||
build_architecture_bitstream --verbose --write_file fabric_independent_bitstream.xml --overwrite_bitstream_file ../../../../config/overwrite_bitstream.txt
|
||||
|
||||
# Build fabric-dependent bitstream
|
||||
build_fabric_bitstream --verbose
|
||||
|
||||
# Write fabric-dependent bitstream
|
||||
write_fabric_bitstream --file fabric_bitstream.bit --format plain_text
|
||||
write_fabric_bitstream --file fabric_bitstream.xml --format xml
|
||||
|
||||
# Write the Verilog netlist for FPGA fabric
|
||||
# - Enable the use of explicit port mapping in Verilog netlist
|
||||
write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --print_user_defined_template --verbose
|
||||
|
||||
# Write the Verilog testbench for FPGA fabric
|
||||
# - We suggest the use of same output directory as fabric Verilog netlists
|
||||
# - Must specify the reference benchmark file if you want to output any testbenches
|
||||
# - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA
|
||||
# - Enable pre-configured top-level testbench which is a fast verification skipping programming phase
|
||||
# - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts
|
||||
write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init --bitstream fabric_bitstream.bit
|
||||
write_preconfigured_fabric_wrapper --embed_bitstream iverilog --file ./SRC --explicit_port_mapping
|
||||
write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping
|
||||
|
||||
# Write the SDC files for PnR backend
|
||||
# - Turn on every options here
|
||||
write_pnr_sdc --file ./SDC
|
||||
|
||||
# Write SDC to disable timing for configure ports
|
||||
write_sdc_disable_timing_configure_ports --file ./SDC/disable_configure_ports.sdc
|
||||
|
||||
# Write the SDC to run timing analysis for a mapped FPGA fabric
|
||||
write_analysis_sdc --file ./SDC_analysis
|
||||
|
||||
# Finish and exit OpenFPGA
|
||||
exit
|
||||
|
||||
# Note :
|
||||
# To run verification at the end of the flow maintain source in ./SRC directory
|
|
@ -15,6 +15,9 @@ echo -e "Testing bitstream generation for an 48x48 FPGA device";
|
|||
run-task fpga_bitstream/generate_bitstream/configuration_chain/device_48x48 $@
|
||||
run-task fpga_bitstream/generate_bitstream/ql_memory_bank_shift_register/device_48x48 $@
|
||||
|
||||
echo -e "Testing bitstream generation for an 4x4 FPGA device (overwrite IO tile bits)";
|
||||
run-task fpga_bitstream/generate_bitstream/configuration_chain/device_4x4_overwrite $@
|
||||
|
||||
echo -e "Testing bitstream generation for an 96x96 FPGA device";
|
||||
run-task fpga_bitstream/generate_bitstream/configuration_chain/device_96x96 $@
|
||||
run-task fpga_bitstream/generate_bitstream/ql_memory_bank_shift_register/device_72x72 $@
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
fpga_top.grid_io_left_0__1_ logical_tile_io_mode_io__7.logical_tile_io_mode_physical__iopad_0.GPIO_DFFR_mem 0
|
||||
fpga_top.grid_io_bottom_3__0_ logical_tile_io_mode_io__1.logical_tile_io_mode_physical__iopad_0.GPIO_DFFR_mem [0]=0
|
|
@ -0,0 +1,35 @@
|
|||
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
|
||||
# Configuration file for running experiments
|
||||
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
|
||||
# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs
|
||||
# Each job execute fpga_flow script on combination of architecture & benchmark
|
||||
# timeout_each_job is timeout for each job
|
||||
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
|
||||
|
||||
[GENERAL]
|
||||
run_engine=openfpga_shell
|
||||
power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml
|
||||
power_analysis = false
|
||||
spice_output=false
|
||||
verilog_output=true
|
||||
timeout_each_job = 20*60
|
||||
fpga_flow=vpr_blif
|
||||
|
||||
[OpenFPGA_SHELL]
|
||||
openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/fix_device_example_script_overwrite.openfpga
|
||||
openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_mem16K_40nm_openfpga.xml
|
||||
openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml
|
||||
openfpga_vpr_device_layout=4x4
|
||||
|
||||
[ARCHITECTURES]
|
||||
arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k6_frac_N10_tileable_thru_channel_adder_chain_wide_mem16K_40nm.xml
|
||||
|
||||
[BENCHMARKS]
|
||||
bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.blif
|
||||
|
||||
[SYNTHESIS_PARAM]
|
||||
bench0_top = and2
|
||||
bench0_act = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.act
|
||||
bench0_verilog = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v
|
||||
|
||||
[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH]
|
Loading…
Reference in New Issue