Add command to generate repack design constraints
This commit is contained in:
parent
0714ccf608
commit
ccfbb40d7d
|
@ -8,11 +8,47 @@
|
||||||
*******************************************************************/
|
*******************************************************************/
|
||||||
#include "openfpga_bitstream_template.h"
|
#include "openfpga_bitstream_template.h"
|
||||||
#include "openfpga_repack_template.h"
|
#include "openfpga_repack_template.h"
|
||||||
|
#include "openfpga_gen_repack_constraints_template.h"
|
||||||
#include "shell.h"
|
#include "shell.h"
|
||||||
|
|
||||||
/* begin namespace openfpga */
|
/* begin namespace openfpga */
|
||||||
namespace openfpga {
|
namespace openfpga {
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* - Add a command to Shell environment: gen_repack_constraints
|
||||||
|
* - Add associated options
|
||||||
|
* - Add command dependency
|
||||||
|
*******************************************************************/
|
||||||
|
template <class T>
|
||||||
|
ShellCommandId add_gen_repack_constraints_command_template(
|
||||||
|
openfpga::Shell<T>& shell, const ShellCommandClassId& cmd_class_id,
|
||||||
|
const std::vector<ShellCommandId>& dependent_cmds, const bool& hidden) {
|
||||||
|
Command shell_cmd("gen_repack_constraints");
|
||||||
|
|
||||||
|
/* Add an option '--pcf' */
|
||||||
|
CommandOptionId opt_pcf =
|
||||||
|
shell_cmd.add_option("pcf", false, "Path to the pcf file");
|
||||||
|
shell_cmd.set_option_require_value(opt_pcf,
|
||||||
|
openfpga::OPT_STRING);
|
||||||
|
|
||||||
|
/* Add an option '--file' */
|
||||||
|
CommandOptionId opt_file =
|
||||||
|
shell_cmd.add_option("file", false, "Path to the output file");
|
||||||
|
shell_cmd.set_option_require_value(opt_file,
|
||||||
|
openfpga::OPT_STRING);
|
||||||
|
|
||||||
|
/* Add command 'gen_repack_constraints' to the Shell */
|
||||||
|
ShellCommandId shell_cmd_id = shell.add_command(
|
||||||
|
shell_cmd, "Generate a repack design constraints file from a PCF file", hidden);
|
||||||
|
shell.set_command_class(shell_cmd_id, cmd_class_id);
|
||||||
|
shell.set_command_execute_function(shell_cmd_id, gen_repack_constraints_template<T>);
|
||||||
|
|
||||||
|
/* Add command dependency to the Shell */
|
||||||
|
shell.set_command_dependency(shell_cmd_id, dependent_cmds);
|
||||||
|
|
||||||
|
return shell_cmd_id;
|
||||||
|
}
|
||||||
|
|
||||||
/********************************************************************
|
/********************************************************************
|
||||||
* - Add a command to Shell environment: repack
|
* - Add a command to Shell environment: repack
|
||||||
* - Add associated options
|
* - Add associated options
|
||||||
|
@ -298,6 +334,10 @@ void add_bitstream_command_templates(openfpga::Shell<T>& shell,
|
||||||
ShellCommandClassId openfpga_bitstream_cmd_class =
|
ShellCommandClassId openfpga_bitstream_cmd_class =
|
||||||
shell.add_command_class("FPGA-Bitstream");
|
shell.add_command_class("FPGA-Bitstream");
|
||||||
|
|
||||||
|
/********************************
|
||||||
|
* Command 'gen_repack_constraints' */
|
||||||
|
add_gen_repack_constraints_command_template(shell, openfpga_bitstream_cmd_class, std::vector<ShellCommandId>(), hidden);
|
||||||
|
|
||||||
/********************************
|
/********************************
|
||||||
* Command 'repack'
|
* Command 'repack'
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -0,0 +1,127 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "command.h"
|
||||||
|
#include "command_context.h"
|
||||||
|
#include "command_exit_codes.h"
|
||||||
|
#include "openfpga_port.h"
|
||||||
|
#include "openfpga_port_parser.h"
|
||||||
|
#include "pcf_reader.h"
|
||||||
|
#include "repack_design_constraints.h"
|
||||||
|
#include "vtr_log.h"
|
||||||
|
#include "write_xml_repack_design_constraints.h"
|
||||||
|
#include "globals.h"
|
||||||
|
|
||||||
|
/* begin namespace openfpga */
|
||||||
|
namespace openfpga {
|
||||||
|
|
||||||
|
static inline RepackDesignConstraints gen_repack_constraints(openfpga::PcfData* pcf_data){
|
||||||
|
auto& cluster_ctx = g_vpr_ctx.clustering();
|
||||||
|
auto& atom_ctx = g_vpr_ctx.atom();
|
||||||
|
auto& clb_nlist = cluster_ctx.clb_nlist;
|
||||||
|
|
||||||
|
/* 1. Get unique pb_types, clock pins and clock nets from clb_nlist.blocks */
|
||||||
|
std::set<std::string> pb_type_names;
|
||||||
|
std::set<BasicPort> clock_pins;
|
||||||
|
std::set<std::string> clock_nets;
|
||||||
|
|
||||||
|
for (auto block_id : clb_nlist.blocks()) {
|
||||||
|
auto pb = clb_nlist.block_pb(block_id);
|
||||||
|
auto pb_type = pb->pb_graph_node->pb_type;
|
||||||
|
pb_type_names.insert(pb_type->name);
|
||||||
|
|
||||||
|
int port_index = 0;
|
||||||
|
for (int i = 0; i < pb_type->num_ports; i++) {
|
||||||
|
auto& port = pb_type->ports[i];
|
||||||
|
if(!port.is_clock)
|
||||||
|
continue;
|
||||||
|
for (int j = 0; j < port.num_pins; j++) {
|
||||||
|
auto& pin = pb->pb_graph_node->clock_pins[port_index][j];
|
||||||
|
std::string pin_name = std::string(port.name) + "[" + std::to_string(j) + "]";
|
||||||
|
openfpga::PortParser port_parser(pin_name);
|
||||||
|
clock_pins.insert(port_parser.port());
|
||||||
|
int node_index = pin.pin_count_in_cluster;
|
||||||
|
if(pb->pb_route.count(node_index)){
|
||||||
|
AtomNetId net_id = pb->pb_route[node_index].atom_net_id;
|
||||||
|
std::string net_name = atom_ctx.nlist.net_name(net_id);
|
||||||
|
clock_nets.insert(net_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
port_index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::pair<std::string, BasicPort>> matches;
|
||||||
|
|
||||||
|
/* First match nets & pins from the pcf file */
|
||||||
|
if(pcf_data){
|
||||||
|
for (const PcfIoConstraintId& io_id : pcf_data->io_constraints()) {
|
||||||
|
std::string net = pcf_data->io_net(io_id);
|
||||||
|
BasicPort pin = pcf_data->io_pin(io_id);
|
||||||
|
if(!(clock_nets.count(net) && clock_pins.count(pin)))
|
||||||
|
continue;
|
||||||
|
matches.push_back({net, pin});
|
||||||
|
clock_nets.erase(net);
|
||||||
|
clock_pins.erase(pin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Match the rest in an arbitrary way */
|
||||||
|
for(auto net: clock_nets){
|
||||||
|
VTR_ASSERT_MSG(!clock_pins.empty(), "Not enough clock pins for clocks in the design");
|
||||||
|
auto first_available_pin = *clock_pins.begin();
|
||||||
|
matches.push_back({net, first_available_pin});
|
||||||
|
clock_pins.erase(first_available_pin);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 3. Create the design constraints */
|
||||||
|
RepackDesignConstraints out;
|
||||||
|
for(auto pb_type: pb_type_names){
|
||||||
|
for(auto [net, pin]: matches){
|
||||||
|
auto id = out.create_design_constraint(RepackDesignConstraints::PIN_ASSIGNMENT);
|
||||||
|
out.set_pb_type(id, pb_type);
|
||||||
|
out.set_net(id, net);
|
||||||
|
out.set_pin(id, pin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Top-level function to generate a repack_design_constraints.xml file
|
||||||
|
* from either a .pcf file or vpr context
|
||||||
|
*******************************************************************/
|
||||||
|
template <class T>
|
||||||
|
int gen_repack_constraints_template(const Command& cmd,
|
||||||
|
const CommandContext& cmd_context) {
|
||||||
|
CommandOptionId opt_pcf = cmd.option("pcf");
|
||||||
|
CommandOptionId opt_file = cmd.option("file");
|
||||||
|
|
||||||
|
std::string out_fname = cmd_context.option_value(cmd, opt_file);
|
||||||
|
|
||||||
|
RepackDesignConstraints constraints;
|
||||||
|
|
||||||
|
if (cmd_context.option_enable(cmd, opt_pcf)) {
|
||||||
|
std::string pcf_fname = cmd_context.option_value(cmd, opt_pcf);
|
||||||
|
|
||||||
|
openfpga::PcfData pcf_data;
|
||||||
|
openfpga::read_pcf(pcf_fname.c_str(), pcf_data);
|
||||||
|
VTR_LOG("[gen_repack_constraints] Read the design constraints from a pcf file: %s.\n",
|
||||||
|
pcf_fname.c_str());
|
||||||
|
|
||||||
|
if (!pcf_data.validate()) {
|
||||||
|
VTR_LOG_ERROR("[gen_repack_constraints] PCF contains invalid I/O assignment!\n");
|
||||||
|
return CMD_EXEC_FATAL_ERROR;
|
||||||
|
} else {
|
||||||
|
VTR_LOG("[gen_repack_constraints] PCF basic check passed\n");
|
||||||
|
}
|
||||||
|
constraints = gen_repack_constraints(&pcf_data);
|
||||||
|
} else {
|
||||||
|
constraints = gen_repack_constraints(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
write_xml_repack_design_constraints(out_fname.c_str(), constraints);
|
||||||
|
return CMD_EXEC_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
} /* end namespace openfpga */
|
Loading…
Reference in New Issue