[Tool] Use use standard data structure to store global port information

This commit is contained in:
tangxifan 2020-11-10 19:07:28 -07:00
parent cbb1545ee3
commit dcb50e4f19
16 changed files with 518 additions and 150 deletions

View File

@ -17,6 +17,7 @@
#include "fabric_hierarchy_writer.h"
#include "fabric_key_writer.h"
#include "build_fabric_io_location_map.h"
#include "build_fabric_global_port_info.h"
#include "openfpga_build_fabric.h"
/* Include global variables of VPR */
@ -120,6 +121,11 @@ int build_fabric(OpenfpgaContext& openfpga_ctx,
openfpga_ctx.mutable_io_location_map() = build_fabric_io_location_map(openfpga_ctx.module_graph(),
g_vpr_ctx.device().grid);
/* Build fabric global port information */
openfpga_ctx.mutable_fabric_global_port_info() = build_fabric_global_port_info(openfpga_ctx.module_graph(),
openfpga_ctx.arch().tile_annotations,
openfpga_ctx.arch().circuit_lib);
/* Output fabric key if user requested */
if (true == cmd_context.option_enable(cmd, opt_write_fabric_key)) {
std::string fkey_fname = cmd_context.option_value(cmd, opt_write_fabric_key);

View File

@ -19,6 +19,7 @@
#include "fabric_bitstream.h"
#include "device_rr_gsb.h"
#include "io_location_map.h"
#include "fabric_global_port_info.h"
/********************************************************************
* This file includes the declaration of the date structure
@ -65,6 +66,7 @@ class OpenfpgaContext : public Context {
const openfpga::BitstreamManager& bitstream_manager() const { return bitstream_manager_; }
const openfpga::FabricBitstream& fabric_bitstream() const { return fabric_bitstream_; }
const openfpga::IoLocationMap& io_location_map() const { return io_location_map_; }
const openfpga::FabricGlobalPortInfo& fabric_global_port_info() const { return fabric_global_port_info_; }
const std::unordered_map<AtomNetId, t_net_power>& net_activity() const { return net_activity_; }
const openfpga::NetlistManager& verilog_netlists() const { return verilog_netlists_; }
const openfpga::NetlistManager& spice_netlists() const { return spice_netlists_; }
@ -85,6 +87,7 @@ class OpenfpgaContext : public Context {
openfpga::BitstreamManager& mutable_bitstream_manager() { return bitstream_manager_; }
openfpga::FabricBitstream& mutable_fabric_bitstream() { return fabric_bitstream_; }
openfpga::IoLocationMap& mutable_io_location_map() { return io_location_map_; }
openfpga::FabricGlobalPortInfo& mutable_fabric_global_port_info() { return fabric_global_port_info_; }
std::unordered_map<AtomNetId, t_net_power>& mutable_net_activity() { return net_activity_; }
openfpga::NetlistManager& mutable_verilog_netlists() { return verilog_netlists_; }
openfpga::NetlistManager& mutable_spice_netlists() { return spice_netlists_; }
@ -123,6 +126,7 @@ class OpenfpgaContext : public Context {
/* Fabric module graph */
openfpga::ModuleManager module_graph_;
openfpga::IoLocationMap io_location_map_;
openfpga::FabricGlobalPortInfo fabric_global_port_info_;
/* Bitstream database */
openfpga::BitstreamManager bitstream_manager_;

View File

@ -96,6 +96,7 @@ int write_verilog_testbench(OpenfpgaContext& openfpga_ctx,
g_vpr_ctx.atom(),
g_vpr_ctx.placement(),
openfpga_ctx.io_location_map(),
openfpga_ctx.fabric_global_port_info(),
openfpga_ctx.vpr_netlist_annotation(),
openfpga_ctx.arch().circuit_lib,
openfpga_ctx.simulation_setting(),

View File

@ -0,0 +1,90 @@
/********************************************************************
* This file includes functions that are used to build the global port
* information for the top-level module of the FPGA fabric
* It helps OpenFPGA to build testbenches with the attributes of the global ports
*******************************************************************/
#include <map>
#include <algorithm>
/* Headers from vtrutil library */
#include "vtr_assert.h"
#include "vtr_time.h"
#include "vtr_log.h"
#include "openfpga_naming.h"
#include "circuit_library_utils.h"
#include "build_fabric_global_port_info.h"
/* begin namespace openfpga */
namespace openfpga {
/********************************************************************
* Find all the GPIO ports in the grid module
* and cache their port/pin index in the top-level module
*******************************************************************/
FabricGlobalPortInfo build_fabric_global_port_info(const ModuleManager& module_manager,
const TileAnnotation& tile_annotation,
const CircuitLibrary& circuit_lib) {
vtr::ScopedStartFinishTimer timer("Create global port info for top module");
FabricGlobalPortInfo fabric_global_port_info;
/* Find top-level module */
std::string top_module_name = generate_fpga_top_module_name();
ModuleId top_module = module_manager.find_module(top_module_name);
if (true != module_manager.valid_module_id(top_module)) {
VTR_LOG_ERROR("Unable to find the top-level module '%s'!\n",
top_module_name.c_str());
exit(1);
}
/* Add the global ports from circuit library */
for (const CircuitPortId& global_port : find_circuit_library_global_ports(circuit_lib)) {
/* We should find a port in the top module */
ModulePortId module_port = module_manager.find_module_port(top_module, circuit_lib.port_prefix(global_port));
/* Only add those ports have been defined in top-level module */
if (false == module_manager.valid_module_port_id(top_module, module_port)) {
continue;
}
/* Add the port information */
FabricGlobalPortId fabric_port = fabric_global_port_info.create_global_port(module_port);
fabric_global_port_info.set_global_port_is_clock(fabric_port, CIRCUIT_MODEL_PORT_CLOCK == circuit_lib.port_type(global_port));
fabric_global_port_info.set_global_port_is_reset(fabric_port, circuit_lib.port_is_reset(global_port));
fabric_global_port_info.set_global_port_is_set(fabric_port, circuit_lib.port_is_set(global_port));
fabric_global_port_info.set_global_port_is_prog(fabric_port, circuit_lib.port_is_prog(global_port));
fabric_global_port_info.set_global_port_is_config_enable(fabric_port, circuit_lib.port_is_config_enable(global_port));
fabric_global_port_info.set_global_port_default_value(fabric_port, circuit_lib.port_default_value(global_port));
}
/* Add the global ports from tile annotation */
for (const TileGlobalPortId& global_port : tile_annotation.global_ports()) {
/* We should find a port in the top module */
ModulePortId module_port = module_manager.find_module_port(top_module, tile_annotation.global_port_name(global_port));
/* Only add those ports have been defined in top-level module */
if (false == module_manager.valid_module_port_id(top_module, module_port)) {
continue;
}
/* Avoid adding redundant ports */
bool already_in_list = false;
for (const FabricGlobalPortId& port : fabric_global_port_info.global_ports()) {
if (module_port == fabric_global_port_info.global_module_port(port)) {
already_in_list = true;
break;
}
}
if (true == already_in_list) {
continue;
}
/* Add the port information */
FabricGlobalPortId fabric_port = fabric_global_port_info.create_global_port(module_port);
fabric_global_port_info.set_global_port_is_clock(fabric_port, tile_annotation.global_port_is_clock(global_port));
fabric_global_port_info.set_global_port_is_reset(fabric_port, tile_annotation.global_port_is_reset(global_port));
fabric_global_port_info.set_global_port_is_set(fabric_port, tile_annotation.global_port_is_set(global_port));
fabric_global_port_info.set_global_port_default_value(fabric_port, tile_annotation.global_port_default_value(global_port));
}
return fabric_global_port_info;
}
} /* end namespace openfpga */

View File

@ -0,0 +1,27 @@
#ifndef BUILD_FABRIC_GLOBAL_PORT_INFO_H
#define BUILD_FABRIC_GLOBAL_PORT_INFO_H
/********************************************************************
* Include header files that are required by function declaration
*******************************************************************/
#include <string>
#include "tile_annotation.h"
#include "circuit_library.h"
#include "fabric_global_port_info.h"
#include "module_manager.h"
/********************************************************************
* Function declaration
*******************************************************************/
/* begin namespace openfpga */
namespace openfpga {
FabricGlobalPortInfo build_fabric_global_port_info(const ModuleManager& module_manager,
const TileAnnotation& tile_annotation,
const CircuitLibrary& circuit_lib);
} /* end namespace openfpga */
#endif

View File

@ -0,0 +1,137 @@
/************************************************************************
* Member functions for class FabricGlobalPortInfo
***********************************************************************/
#include "vtr_assert.h"
#include "fabric_global_port_info.h"
/* namespace openfpga begins */
namespace openfpga {
/************************************************************************
* Constructors
***********************************************************************/
FabricGlobalPortInfo::FabricGlobalPortInfo() {
return;
}
/************************************************************************
* Public Accessors : aggregates
***********************************************************************/
FabricGlobalPortInfo::global_port_range FabricGlobalPortInfo::global_ports() const {
return vtr::make_range(global_port_ids_.begin(), global_port_ids_.end());
}
/************************************************************************
* Public Accessors
***********************************************************************/
ModulePortId FabricGlobalPortInfo::global_module_port(const FabricGlobalPortId& global_port_id) const {
VTR_ASSERT(valid_global_port_id(global_port_id));
return global_module_ports_[global_port_id];
}
bool FabricGlobalPortInfo::global_port_is_clock(const FabricGlobalPortId& global_port_id) const {
VTR_ASSERT(valid_global_port_id(global_port_id));
return global_port_is_clock_[global_port_id];
}
bool FabricGlobalPortInfo::global_port_is_set(const FabricGlobalPortId& global_port_id) const {
VTR_ASSERT(valid_global_port_id(global_port_id));
return global_port_is_set_[global_port_id];
}
bool FabricGlobalPortInfo::global_port_is_reset(const FabricGlobalPortId& global_port_id) const {
VTR_ASSERT(valid_global_port_id(global_port_id));
return global_port_is_reset_[global_port_id];
}
bool FabricGlobalPortInfo::global_port_is_prog(const FabricGlobalPortId& global_port_id) const {
VTR_ASSERT(valid_global_port_id(global_port_id));
return global_port_is_prog_[global_port_id];
}
bool FabricGlobalPortInfo::global_port_is_config_enable(const FabricGlobalPortId& global_port_id) const {
VTR_ASSERT(valid_global_port_id(global_port_id));
return global_port_is_config_enable_[global_port_id];
}
bool FabricGlobalPortInfo::global_port_is_io(const FabricGlobalPortId& global_port_id) const {
VTR_ASSERT(valid_global_port_id(global_port_id));
return global_port_is_io_[global_port_id];
}
size_t FabricGlobalPortInfo::global_port_default_value(const FabricGlobalPortId& global_port_id) const {
VTR_ASSERT(valid_global_port_id(global_port_id));
return global_port_default_values_[global_port_id];
}
/************************************************************************
* Public Mutators
***********************************************************************/
FabricGlobalPortId FabricGlobalPortInfo::create_global_port(const ModulePortId& module_port) {
/* This is a legal name. we can create a new id */
FabricGlobalPortId port_id = FabricGlobalPortId(global_port_ids_.size());
global_port_ids_.push_back(port_id);
global_module_ports_.push_back(module_port);
global_port_is_clock_.push_back(false);
global_port_is_set_.push_back(false);
global_port_is_reset_.push_back(false);
global_port_is_prog_.push_back(false);
global_port_is_io_.push_back(false);
global_port_is_config_enable_.push_back(false);
global_port_default_values_.push_back(0);
return port_id;
}
void FabricGlobalPortInfo::set_global_port_is_clock(const FabricGlobalPortId& global_port_id,
const bool& is_clock) {
VTR_ASSERT(valid_global_port_id(global_port_id));
global_port_is_clock_[global_port_id] = is_clock;
}
void FabricGlobalPortInfo::set_global_port_is_set(const FabricGlobalPortId& global_port_id,
const bool& is_set) {
VTR_ASSERT(valid_global_port_id(global_port_id));
global_port_is_set_[global_port_id] = is_set;
}
void FabricGlobalPortInfo::set_global_port_is_reset(const FabricGlobalPortId& global_port_id,
const bool& is_reset) {
VTR_ASSERT(valid_global_port_id(global_port_id));
global_port_is_reset_[global_port_id] = is_reset;
}
void FabricGlobalPortInfo::set_global_port_is_prog(const FabricGlobalPortId& global_port_id,
const bool& is_prog) {
VTR_ASSERT(valid_global_port_id(global_port_id));
global_port_is_prog_[global_port_id] = is_prog;
}
void FabricGlobalPortInfo::set_global_port_is_config_enable(const FabricGlobalPortId& global_port_id,
const bool& is_config_enable) {
VTR_ASSERT(valid_global_port_id(global_port_id));
global_port_is_config_enable_[global_port_id] = is_config_enable;
}
void FabricGlobalPortInfo::set_global_port_is_io(const FabricGlobalPortId& global_port_id,
const bool& is_io) {
VTR_ASSERT(valid_global_port_id(global_port_id));
global_port_is_io_[global_port_id] = is_io;
}
void FabricGlobalPortInfo::set_global_port_default_value(const FabricGlobalPortId& global_port_id,
const size_t& default_value) {
VTR_ASSERT(valid_global_port_id(global_port_id));
global_port_default_values_[global_port_id] = default_value;
}
/************************************************************************
* Internal invalidators/validators
***********************************************************************/
/* Validators */
bool FabricGlobalPortInfo::valid_global_port_id(const FabricGlobalPortId& global_port_id) const {
return ( size_t(global_port_id) < global_port_ids_.size() ) && ( global_port_id == global_port_ids_[global_port_id] );
}
} /* namespace openfpga ends */

View File

@ -0,0 +1,79 @@
#ifndef FABRIC_GLOBAL_PORT_INFO_H
#define FABRIC_GLOBAL_PORT_INFO_H
/********************************************************************
* Include header files required by the data structure definition
*******************************************************************/
#include <vector>
#include <string>
#include "vtr_vector.h"
#include "module_manager_fwd.h"
#include "fabric_global_port_info_fwd.h"
/* namespace openfpga begins */
namespace openfpga {
/********************************************************************
* A data structure to store necessary information for the global
* ports that have been defined for the FPGA fabric
*
* Currently the global port information is mainly used for testbench generation
*******************************************************************/
class FabricGlobalPortInfo {
public: /* Types */
typedef vtr::vector<FabricGlobalPortId, FabricGlobalPortId>::const_iterator global_port_iterator;
/* Create range */
typedef vtr::Range<global_port_iterator> global_port_range;
public: /* Constructor */
FabricGlobalPortInfo();
public: /* Public accessors: aggregators */
global_port_range global_ports() const;
public: /* Public accessors */
ModulePortId global_module_port(const FabricGlobalPortId& global_port_id) const;
bool global_port_is_clock(const FabricGlobalPortId& global_port_id) const;
bool global_port_is_set(const FabricGlobalPortId& global_port_id) const;
bool global_port_is_reset(const FabricGlobalPortId& global_port_id) const;
bool global_port_is_prog(const FabricGlobalPortId& global_port_id) const;
bool global_port_is_config_enable(const FabricGlobalPortId& global_port_id) const;
bool global_port_is_io(const FabricGlobalPortId& global_port_id) const;
size_t global_port_default_value(const FabricGlobalPortId& global_port_id) const;
public: /* Public mutators */
/* By default, we do not set it as a clock.
* Users should set it through the set_global_port_is_clock() function
*/
FabricGlobalPortId create_global_port(const ModulePortId& module_port);
void set_global_port_is_clock(const FabricGlobalPortId& global_port_id,
const bool& is_clock);
void set_global_port_is_set(const FabricGlobalPortId& global_port_id,
const bool& is_set);
void set_global_port_is_reset(const FabricGlobalPortId& global_port_id,
const bool& is_reset);
void set_global_port_is_prog(const FabricGlobalPortId& global_port_id,
const bool& is_prog);
void set_global_port_is_config_enable(const FabricGlobalPortId& global_port_id,
const bool& is_config_enable);
void set_global_port_is_io(const FabricGlobalPortId& global_port_id,
const bool& is_io);
void set_global_port_default_value(const FabricGlobalPortId& global_port_id,
const size_t& default_value);
public: /* Public validator */
bool valid_global_port_id(const FabricGlobalPortId& global_port_id) const;
private: /* Internal data */
/* Global port information for tiles */
vtr::vector<FabricGlobalPortId, FabricGlobalPortId> global_port_ids_;
vtr::vector<FabricGlobalPortId, ModulePortId> global_module_ports_;
vtr::vector<FabricGlobalPortId, bool> global_port_is_clock_;
vtr::vector<FabricGlobalPortId, bool> global_port_is_reset_;
vtr::vector<FabricGlobalPortId, bool> global_port_is_set_;
vtr::vector<FabricGlobalPortId, bool> global_port_is_prog_;
vtr::vector<FabricGlobalPortId, bool> global_port_is_config_enable_;
vtr::vector<FabricGlobalPortId, bool> global_port_is_io_;
vtr::vector<FabricGlobalPortId, size_t> global_port_default_values_;
};
} /* namespace openfpga ends */
#endif

View File

@ -0,0 +1,22 @@
/************************************************************************
* A header file for FabricGlobalPortList class, including critical data declaration
* Please include this file only for using any FabricGlobalPortList data structure
* Refer to fabric_global_port_list.h for more details
***********************************************************************/
/************************************************************************
* Create strong id for fabric global ports to avoid illegal type casting
***********************************************************************/
#ifndef FABRIC_GLOBAL_PORT_INFO_FWD_H
#define FABRIC_GLOBAL_PORT_INFO_FWD_H
#include "vtr_strong_id.h"
struct fabric_global_port_id_tag;
typedef vtr::StrongId<fabric_global_port_id_tag> FabricGlobalPortId;
/* Short declaration of class */
class FabricGlobalPortInfo;
#endif

View File

@ -153,6 +153,7 @@ void fpga_verilog_testbench(const ModuleManager &module_manager,
const AtomContext &atom_ctx,
const PlacementContext &place_ctx,
const IoLocationMap &io_location_map,
const FabricGlobalPortInfo &fabric_global_port_info,
const VprNetlistAnnotation &netlist_annotation,
const CircuitLibrary &circuit_lib,
const SimulationSetting &simulation_setting,
@ -172,17 +173,12 @@ void fpga_verilog_testbench(const ModuleManager &module_manager,
print_verilog_simulation_preprocessing_flags(std::string(src_dir_path),
options);
/* Collect global ports from the circuit library:
* TODO: should we place this in the OpenFPGA context?
*/
std::vector<CircuitPortId> global_ports = find_circuit_library_global_ports(circuit_lib);
/* Generate wrapper module for FPGA fabric (mapped by the input benchmark and pre-configured testbench for verification */
if (true == options.print_formal_verification_top_netlist()) {
std::string formal_verification_top_netlist_file_path = src_dir_path + netlist_name + std::string(FORMAL_VERIFICATION_VERILOG_FILE_POSTFIX);
print_verilog_preconfig_top_module(module_manager, bitstream_manager,
config_protocol,
circuit_lib, global_ports,
circuit_lib, fabric_global_port_info,
atom_ctx, place_ctx, io_location_map,
netlist_annotation,
netlist_name,
@ -207,7 +203,7 @@ void fpga_verilog_testbench(const ModuleManager &module_manager,
print_verilog_top_testbench(module_manager,
bitstream_manager, fabric_bitstream,
config_protocol,
circuit_lib, global_ports,
fabric_global_port_info,
atom_ctx, place_ctx, io_location_map,
netlist_annotation,
netlist_name,

View File

@ -20,6 +20,7 @@
#include "fabric_bitstream.h"
#include "simulation_setting.h"
#include "io_location_map.h"
#include "fabric_global_port_info.h"
#include "vpr_netlist_annotation.h"
#include "fabric_verilog_options.h"
#include "verilog_testbench_options.h"
@ -47,6 +48,7 @@ void fpga_verilog_testbench(const ModuleManager& module_manager,
const AtomContext& atom_ctx,
const PlacementContext& place_ctx,
const IoLocationMap& io_location_map,
const FabricGlobalPortInfo &fabric_global_port_info,
const VprNetlistAnnotation& netlist_annotation,
const CircuitLibrary& circuit_lib,
const SimulationSetting& simulation_parameters,

View File

@ -118,8 +118,7 @@ namespace openfpga
static void print_verilog_preconfig_top_module_connect_global_ports(std::fstream &fp,
const ModuleManager &module_manager,
const ModuleId &top_module,
const CircuitLibrary &circuit_lib,
const std::vector<CircuitPortId> &global_ports,
const FabricGlobalPortInfo &fabric_global_ports,
const std::vector<std::string> &benchmark_clock_port_names)
{
/* Validate the file stream */
@ -127,40 +126,16 @@ namespace openfpga
print_verilog_comment(fp, std::string("----- Begin Connect Global ports of FPGA top module -----"));
/* Global ports of the top module in module manager do not carry any attributes,
* such as is_clock, is_set, etc.
* Therefore, for each global port in the top module, we find the circuit port in the circuit library
* which share the same name. We can access to the attributes.
* To gurantee the correct link between global ports in module manager and those in circuit library
* We have performed some critical check in check_circuit_library() for global ports,
* where we guarantee all the global ports share the same name must have the same attributes.
* So that each global port with the same name is unique!
*/
for (const BasicPort &module_global_port : module_manager.module_ports_by_type(top_module, ModuleManager::MODULE_GLOBAL_PORT))
{
CircuitPortId linked_circuit_port_id = CircuitPortId::INVALID();
/* Find the circuit port with the same name */
for (const CircuitPortId &circuit_port_id : global_ports)
{
if (0 != module_global_port.get_name().compare(circuit_lib.port_prefix(circuit_port_id)))
{
continue;
}
linked_circuit_port_id = circuit_port_id;
break;
}
/* Must find one valid circuit port */
VTR_ASSERT(CircuitPortId::INVALID() != linked_circuit_port_id);
/* Port size should match! */
VTR_ASSERT(module_global_port.get_width() == circuit_lib.port_size(linked_circuit_port_id));
for (const FabricGlobalPortId& global_port_id : fabric_global_ports.global_ports()) {
ModulePortId module_global_port_id = fabric_global_ports.global_module_port(global_port_id);
VTR_ASSERT(ModuleManager::MODULE_GLOBAL_PORT == module_manager.port_type(top_module, module_global_port_id));
BasicPort module_global_port = module_manager.module_port(top_module, module_global_port_id);
/* Now, for operating clock port, we should wire it to the clock of benchmark! */
if ((CIRCUIT_MODEL_PORT_CLOCK == circuit_lib.port_type(linked_circuit_port_id)) && (false == circuit_lib.port_is_prog(linked_circuit_port_id)))
{
if ((true == fabric_global_ports.global_port_is_clock(global_port_id))
&& (false == fabric_global_ports.global_port_is_prog(global_port_id))) {
/* Wiring to each pin of the global port: benchmark clock is always 1-bit */
for (const size_t &pin : module_global_port.pins())
{
for (const std::string &clock_port_name : benchmark_clock_port_names)
{
for (const size_t &pin : module_global_port.pins()) {
for (const std::string &clock_port_name : benchmark_clock_port_names) {
BasicPort module_clock_pin(module_global_port.get_name(), pin, pin);
BasicPort benchmark_clock_pin(clock_port_name + std::string(FORMAL_VERIFICATION_TOP_MODULE_PORT_POSTFIX), 1);
print_verilog_wire_connection(fp, module_clock_pin, benchmark_clock_pin, false);
@ -171,7 +146,7 @@ namespace openfpga
}
/* For other ports, give an default value */
std::vector<size_t> default_values(module_global_port.get_width(), circuit_lib.port_default_value(linked_circuit_port_id));
std::vector<size_t> default_values(module_global_port.get_width(), fabric_global_ports.global_port_default_value(global_port_id));
print_verilog_wire_constant_values(fp, module_global_port, default_values);
}
@ -430,7 +405,7 @@ namespace openfpga
const BitstreamManager &bitstream_manager,
const ConfigProtocol &config_protocol,
const CircuitLibrary &circuit_lib,
const std::vector<CircuitPortId> &global_ports,
const FabricGlobalPortInfo &global_ports,
const AtomContext &atom_ctx,
const PlacementContext &place_ctx,
const IoLocationMap &io_location_map,
@ -475,7 +450,7 @@ namespace openfpga
/* Connect FPGA top module global ports to constant or benchmark global signals! */
print_verilog_preconfig_top_module_connect_global_ports(fp, module_manager, top_module,
circuit_lib, global_ports,
global_ports,
benchmark_clock_port_names);
/* Connect I/Os to benchmark I/Os or constant driver */

View File

@ -11,6 +11,7 @@
#include "module_manager.h"
#include "bitstream_manager.h"
#include "io_location_map.h"
#include "fabric_global_port_info.h"
#include "config_protocol.h"
#include "vpr_netlist_annotation.h"
@ -25,7 +26,7 @@ void print_verilog_preconfig_top_module(const ModuleManager& module_manager,
const BitstreamManager& bitstream_manager,
const ConfigProtocol &config_protocol,
const CircuitLibrary& circuit_lib,
const std::vector<CircuitPortId>& global_ports,
const FabricGlobalPortInfo &global_ports,
const AtomContext& atom_ctx,
const PlacementContext& place_ctx,
const IoLocationMap& io_location_map,

View File

@ -6,7 +6,6 @@
#include <iomanip>
#include <algorithm>
/* Headers from vtrutil library */
#include "vtr_log.h"
#include "vtr_assert.h"
@ -24,6 +23,7 @@
#include "openfpga_atom_netlist_utils.h"
#include "fabric_bitstream_utils.h"
#include "fabric_global_port_info_utils.h"
#include "verilog_constants.h"
#include "verilog_writer_utils.h"
@ -62,54 +62,6 @@ constexpr char* TOP_TB_CLOCK_REG_POSTFIX = "_reg";
constexpr char* AUTOCHECK_TOP_TESTBENCH_VERILOG_MODULE_POSTFIX = "_autocheck_top_tb";
/********************************************************************
* Identify global reset ports for programming
*******************************************************************/
static
std::vector<CircuitPortId> find_global_programming_reset_ports(const CircuitLibrary& circuit_lib,
const std::vector<CircuitPortId>& global_ports) {
/* Try to find global reset ports for programming */
std::vector<CircuitPortId> global_prog_reset_ports;
for (const CircuitPortId& global_port : global_ports) {
VTR_ASSERT(true == circuit_lib.port_is_global(global_port));
if (false == circuit_lib.port_is_prog(global_port)) {
continue;
}
VTR_ASSERT(true == circuit_lib.port_is_prog(global_port));
VTR_ASSERT( (false == circuit_lib.port_is_reset(global_port))
|| (false == circuit_lib.port_is_set(global_port)));
if (true == circuit_lib.port_is_reset(global_port)) {
global_prog_reset_ports.push_back(global_port);
}
}
return global_prog_reset_ports;
}
/********************************************************************
* Identify global set ports for programming
*******************************************************************/
static
std::vector<CircuitPortId> find_global_programming_set_ports(const CircuitLibrary& circuit_lib,
const std::vector<CircuitPortId>& global_ports) {
/* Try to find global set ports for programming */
std::vector<CircuitPortId> global_prog_set_ports;
for (const CircuitPortId& global_port : global_ports) {
VTR_ASSERT(true == circuit_lib.port_is_global(global_port));
if (false == circuit_lib.port_is_prog(global_port)) {
continue;
}
VTR_ASSERT(true == circuit_lib.port_is_prog(global_port));
VTR_ASSERT( (false == circuit_lib.port_is_reset(global_port))
|| (false == circuit_lib.port_is_set(global_port)));
if (true == circuit_lib.port_is_set(global_port)) {
global_prog_set_ports.push_back(global_port);
}
}
return global_prog_set_ports;
}
/********************************************************************
* Print local wires for flatten memory (standalone) configuration protocols
*******************************************************************/
@ -300,8 +252,7 @@ static
void print_verilog_top_testbench_global_ports_stimuli(std::fstream& fp,
const ModuleManager& module_manager,
const ModuleId& top_module,
const CircuitLibrary& circuit_lib,
const std::vector<CircuitPortId>& global_ports,
const FabricGlobalPortInfo& fabric_global_port_info,
const bool& active_global_prog_reset,
const bool& active_global_prog_set) {
/* Validate the file stream */
@ -310,8 +261,8 @@ void print_verilog_top_testbench_global_ports_stimuli(std::fstream& fp,
print_verilog_comment(fp, std::string("----- Begin connecting global ports of FPGA fabric to stimuli -----"));
/* Connect global clock ports to operating or programming clock signal */
for (const CircuitPortId& model_global_port : global_ports) {
if (CIRCUIT_MODEL_PORT_CLOCK != circuit_lib.port_type(model_global_port)) {
for (const FabricGlobalPortId& fabric_global_port : fabric_global_port_info.global_ports()) {
if (false == fabric_global_port_info.global_port_is_clock(fabric_global_port)) {
continue;
}
/* Reach here, it means we have a global clock to deal with:
@ -321,15 +272,15 @@ void print_verilog_top_testbench_global_ports_stimuli(std::fstream& fp,
* connect it to the local wire of operating clock
*/
/* Find the module port */
ModulePortId module_global_port = module_manager.find_module_port(top_module, circuit_lib.port_prefix(model_global_port));
ModulePortId module_global_port = fabric_global_port_info.global_module_port(fabric_global_port);
VTR_ASSERT(true == module_manager.valid_module_port_id(top_module, module_global_port));
BasicPort stimuli_clock_port;
if (true == circuit_lib.port_is_prog(model_global_port)) {
if (true == fabric_global_port_info.global_port_is_prog(fabric_global_port)) {
stimuli_clock_port.set_name(std::string(TOP_TB_PROG_CLOCK_PORT_NAME));
stimuli_clock_port.set_width(1);
} else {
VTR_ASSERT_SAFE(false == circuit_lib.port_is_prog(model_global_port));
VTR_ASSERT_SAFE(false == fabric_global_port_info.global_port_is_prog(fabric_global_port));
stimuli_clock_port.set_name(std::string(TOP_TB_OP_CLOCK_PORT_NAME));
stimuli_clock_port.set_width(1);
}
@ -339,21 +290,21 @@ void print_verilog_top_testbench_global_ports_stimuli(std::fstream& fp,
*/
print_verilog_wire_connection(fp, module_manager.module_port(top_module, module_global_port),
stimuli_clock_port,
1 == circuit_lib.port_default_value(model_global_port));
1 == fabric_global_port_info.global_port_default_value(fabric_global_port));
}
/* Connect global configuration done ports to configuration done signal */
for (const CircuitPortId& model_global_port : global_ports) {
for (const FabricGlobalPortId& fabric_global_port : fabric_global_port_info.global_ports()) {
/* Bypass clock signals, they have been processed */
if (CIRCUIT_MODEL_PORT_CLOCK == circuit_lib.port_type(model_global_port)) {
if (true == fabric_global_port_info.global_port_is_clock(fabric_global_port)) {
continue;
}
if (false == circuit_lib.port_is_config_enable(model_global_port)) {
if (false == fabric_global_port_info.global_port_is_config_enable(fabric_global_port)) {
continue;
}
/* Reach here, it means we have a configuration done port to deal with */
/* Find the module port */
ModulePortId module_global_port = module_manager.find_module_port(top_module, circuit_lib.port_prefix(model_global_port));
ModulePortId module_global_port = fabric_global_port_info.global_module_port(fabric_global_port);
VTR_ASSERT(true == module_manager.valid_module_port_id(top_module, module_global_port));
BasicPort stimuli_config_done_port(std::string(TOP_TB_CONFIG_DONE_PORT_NAME), 1);
@ -363,37 +314,37 @@ void print_verilog_top_testbench_global_ports_stimuli(std::fstream& fp,
*/
print_verilog_wire_connection(fp, module_manager.module_port(top_module, module_global_port),
stimuli_config_done_port,
1 == circuit_lib.port_default_value(model_global_port));
1 == fabric_global_port_info.global_port_default_value(fabric_global_port));
}
/* Connect global reset ports to operating or programming reset signal */
for (const CircuitPortId& model_global_port : global_ports) {
for (const FabricGlobalPortId& fabric_global_port : fabric_global_port_info.global_ports()) {
/* Bypass clock signals, they have been processed */
if (CIRCUIT_MODEL_PORT_CLOCK == circuit_lib.port_type(model_global_port)) {
if (true == fabric_global_port_info.global_port_is_clock(fabric_global_port)) {
continue;
}
/* Bypass config_done signals, they have been processed */
if (true == circuit_lib.port_is_config_enable(model_global_port)) {
if (true == fabric_global_port_info.global_port_is_config_enable(fabric_global_port)) {
continue;
}
if (false == circuit_lib.port_is_reset(model_global_port)) {
if (false == fabric_global_port_info.global_port_is_reset(fabric_global_port)) {
continue;
}
/* Reach here, it means we have a reset port to deal with */
/* Find the module port */
ModulePortId module_global_port = module_manager.find_module_port(top_module, circuit_lib.port_prefix(model_global_port));
ModulePortId module_global_port = fabric_global_port_info.global_module_port(fabric_global_port);
VTR_ASSERT(true == module_manager.valid_module_port_id(top_module, module_global_port));
/* For global programming reset port, we will active only when specified */
BasicPort stimuli_reset_port;
bool activate = true;
if (true == circuit_lib.port_is_prog(model_global_port)) {
if (true == fabric_global_port_info.global_port_is_prog(fabric_global_port)) {
stimuli_reset_port.set_name(std::string(TOP_TB_PROG_RESET_PORT_NAME));
stimuli_reset_port.set_width(1);
activate = active_global_prog_reset;
} else {
VTR_ASSERT_SAFE(false == circuit_lib.port_is_prog(model_global_port));
VTR_ASSERT_SAFE(false == fabric_global_port_info.global_port_is_prog(fabric_global_port));
stimuli_reset_port.set_name(std::string(TOP_TB_RESET_PORT_NAME));
stimuli_reset_port.set_width(1);
}
@ -404,47 +355,47 @@ void print_verilog_top_testbench_global_ports_stimuli(std::fstream& fp,
if (true == activate) {
print_verilog_wire_connection(fp, module_manager.module_port(top_module, module_global_port),
stimuli_reset_port,
1 == circuit_lib.port_default_value(model_global_port));
1 == fabric_global_port_info.global_port_default_value(fabric_global_port));
} else {
VTR_ASSERT_SAFE(false == activate);
print_verilog_wire_constant_values(fp, module_manager.module_port(top_module, module_global_port),
std::vector<size_t>(1, circuit_lib.port_default_value(model_global_port)));
std::vector<size_t>(1, fabric_global_port_info.global_port_default_value(fabric_global_port)));
}
}
/* Connect global set ports to operating or programming set signal */
for (const CircuitPortId& model_global_port : global_ports) {
for (const FabricGlobalPortId& fabric_global_port : fabric_global_port_info.global_ports()) {
/* Bypass clock signals, they have been processed */
if (CIRCUIT_MODEL_PORT_CLOCK == circuit_lib.port_type(model_global_port)) {
if (true == fabric_global_port_info.global_port_is_clock(fabric_global_port)) {
continue;
}
/* Bypass config_done signals, they have been processed */
if (true == circuit_lib.port_is_config_enable(model_global_port)) {
if (true == fabric_global_port_info.global_port_is_config_enable(fabric_global_port)) {
continue;
}
/* Bypass reset signals, they have been processed */
if (true == circuit_lib.port_is_reset(model_global_port)) {
if (true == fabric_global_port_info.global_port_is_reset(fabric_global_port)) {
continue;
}
if (false == circuit_lib.port_is_set(model_global_port)) {
if (false == fabric_global_port_info.global_port_is_set(fabric_global_port)) {
continue;
}
/* Reach here, it means we have a set port to deal with */
/* Find the module port */
ModulePortId module_global_port = module_manager.find_module_port(top_module, circuit_lib.port_prefix(model_global_port));
ModulePortId module_global_port = fabric_global_port_info.global_module_port(fabric_global_port);
VTR_ASSERT(true == module_manager.valid_module_port_id(top_module, module_global_port));
/* For global programming set port, we will active only when specified */
BasicPort stimuli_set_port;
bool activate = true;
if (true == circuit_lib.port_is_prog(model_global_port)) {
if (true == fabric_global_port_info.global_port_is_prog(fabric_global_port)) {
stimuli_set_port.set_name(std::string(TOP_TB_PROG_SET_PORT_NAME));
stimuli_set_port.set_width(1);
activate = active_global_prog_set;
} else {
VTR_ASSERT_SAFE(false == circuit_lib.port_is_prog(model_global_port));
VTR_ASSERT_SAFE(false == fabric_global_port_info.global_port_is_prog(fabric_global_port));
stimuli_set_port.set_name(std::string(TOP_TB_SET_PORT_NAME));
stimuli_set_port.set_width(1);
}
@ -455,56 +406,51 @@ void print_verilog_top_testbench_global_ports_stimuli(std::fstream& fp,
if (true == activate) {
print_verilog_wire_connection(fp, module_manager.module_port(top_module, module_global_port),
stimuli_set_port,
1 == circuit_lib.port_default_value(model_global_port));
1 == fabric_global_port_info.global_port_default_value(fabric_global_port));
} else {
VTR_ASSERT_SAFE(false == activate);
print_verilog_wire_constant_values(fp, module_manager.module_port(top_module, module_global_port),
std::vector<size_t>(1, circuit_lib.port_default_value(model_global_port)));
std::vector<size_t>(1, fabric_global_port_info.global_port_default_value(fabric_global_port)));
}
}
/* For the rest of global ports, wire them to constant signals */
for (const CircuitPortId& model_global_port : global_ports) {
for (const FabricGlobalPortId& fabric_global_port : fabric_global_port_info.global_ports()) {
/* Bypass clock signals, they have been processed */
if (CIRCUIT_MODEL_PORT_CLOCK == circuit_lib.port_type(model_global_port)) {
if (true == fabric_global_port_info.global_port_is_clock(fabric_global_port)) {
continue;
}
/* Bypass config_done signals, they have been processed */
if (true == circuit_lib.port_is_config_enable(model_global_port)) {
if (true == fabric_global_port_info.global_port_is_config_enable(fabric_global_port)) {
continue;
}
/* Bypass reset signals, they have been processed */
if (true == circuit_lib.port_is_reset(model_global_port)) {
if (true == fabric_global_port_info.global_port_is_reset(fabric_global_port)) {
continue;
}
/* Bypass set signals, they have been processed */
if (true == circuit_lib.port_is_set(model_global_port)) {
if (true == fabric_global_port_info.global_port_is_set(fabric_global_port)) {
continue;
}
/* Bypass io signals, they do not need any drivers */
if (true == circuit_lib.port_is_io(model_global_port)) {
if (true == fabric_global_port_info.global_port_is_io(fabric_global_port)) {
continue;
}
/* Find the port name, gpio port has special names */
std::string port_name;
if (true == circuit_lib.port_is_io(model_global_port)) {
port_name = generate_fpga_global_io_port_name(std::string(GIO_INOUT_PREFIX), circuit_lib, circuit_lib.port_parent_model(model_global_port), model_global_port);
} else {
VTR_ASSERT_SAFE(false == circuit_lib.port_is_io(model_global_port));
port_name = circuit_lib.port_prefix(model_global_port);
}
VTR_ASSERT_SAFE(false == fabric_global_port_info.global_port_is_io(fabric_global_port));
/* Reach here, it means we have a port to deal with */
/* Find the module port and wire it to constant values */
ModulePortId module_global_port = module_manager.find_module_port(top_module, port_name);
ModulePortId module_global_port = fabric_global_port_info.global_module_port(fabric_global_port);
VTR_ASSERT(true == module_manager.valid_module_port_id(top_module, module_global_port));
BasicPort module_port = module_manager.module_port(top_module, module_global_port);
std::vector<size_t> default_values(module_port.get_width(), circuit_lib.port_default_value(model_global_port));
std::vector<size_t> default_values(module_port.get_width(), fabric_global_port_info.global_port_default_value(fabric_global_port));
print_verilog_wire_constant_values(fp, module_port, default_values);
}
@ -1279,8 +1225,8 @@ void print_verilog_top_testbench_vanilla_bitstream(std::fstream& fp,
static
bool find_bit_value_to_skip_for_fast_configuration(const e_config_protocol_type& config_protocol_type,
const bool& fast_configuration,
const std::vector<CircuitPortId>& global_prog_reset_ports,
const std::vector<CircuitPortId>& global_prog_set_ports,
const std::vector<FabricGlobalPortId>& global_prog_reset_ports,
const std::vector<FabricGlobalPortId>& global_prog_set_ports,
const BitstreamManager& bitstream_manager,
const FabricBitstream& fabric_bitstream) {
@ -1824,8 +1770,7 @@ void print_verilog_top_testbench(const ModuleManager& module_manager,
const BitstreamManager& bitstream_manager,
const FabricBitstream& fabric_bitstream,
const ConfigProtocol& config_protocol,
const CircuitLibrary& circuit_lib,
const std::vector<CircuitPortId>& global_ports,
const FabricGlobalPortInfo& global_ports,
const AtomContext& atom_ctx,
const PlacementContext& place_ctx,
const IoLocationMap& io_location_map,
@ -1860,8 +1805,8 @@ void print_verilog_top_testbench(const ModuleManager& module_manager,
std::vector<std::string> clock_port_names = find_atom_netlist_clock_port_names(atom_ctx.nlist, netlist_annotation);
/* Preparation: find all the reset/set ports for programming usage */
std::vector<CircuitPortId> global_prog_reset_ports = find_global_programming_reset_ports(circuit_lib, global_ports);
std::vector<CircuitPortId> global_prog_set_ports = find_global_programming_set_ports(circuit_lib, global_ports);
std::vector<FabricGlobalPortId> global_prog_reset_ports = find_fabric_global_programming_reset_ports(global_ports);
std::vector<FabricGlobalPortId> global_prog_set_ports = find_fabric_global_programming_set_ports(global_ports);
/* Identify if we can apply fast configuration */
bool apply_fast_configuration = fast_configuration;
@ -1935,7 +1880,7 @@ void print_verilog_top_testbench(const ModuleManager& module_manager,
/* Generate stimuli for global ports or connect them to existed signals */
print_verilog_top_testbench_global_ports_stimuli(fp,
module_manager, top_module,
circuit_lib, global_ports,
global_ports,
active_global_prog_reset,
active_global_prog_set);

View File

@ -9,10 +9,10 @@
#include "module_manager.h"
#include "bitstream_manager.h"
#include "fabric_bitstream.h"
#include "circuit_library.h"
#include "config_protocol.h"
#include "vpr_context.h"
#include "io_location_map.h"
#include "fabric_global_port_info.h"
#include "vpr_netlist_annotation.h"
#include "simulation_setting.h"
@ -27,8 +27,7 @@ void print_verilog_top_testbench(const ModuleManager& module_manager,
const BitstreamManager& bitstream_manager,
const FabricBitstream& fabric_bitstream,
const ConfigProtocol& config_protocol,
const CircuitLibrary& circuit_lib,
const std::vector<CircuitPortId>& global_ports,
const FabricGlobalPortInfo& global_ports,
const AtomContext& atom_ctx,
const PlacementContext& place_ctx,
const IoLocationMap& io_location_map,

View File

@ -0,0 +1,61 @@
/************************************************************************
* Function to perform fundamental operation for the fabric global ports
* These functions are not universal methods for the FabricGlobalPortInfo class
* They are made to ease the development in some specific purposes
* Please classify such functions in this file
***********************************************************************/
#include <algorithm>
/* Headers from vtrutil library */
#include "vtr_assert.h"
#include "vtr_log.h"
#include "fabric_global_port_info_utils.h"
/* begin namespace openfpga */
namespace openfpga {
/********************************************************************
* Identify global reset ports for programming
*******************************************************************/
std::vector<FabricGlobalPortId> find_fabric_global_programming_reset_ports(const FabricGlobalPortInfo& fabric_global_port_info) {
/* Try to find global reset ports for programming */
std::vector<FabricGlobalPortId> global_prog_reset_ports;
for (const FabricGlobalPortId& global_port : fabric_global_port_info.global_ports()) {
if (false == fabric_global_port_info.global_port_is_prog(global_port)) {
continue;
}
VTR_ASSERT(true == fabric_global_port_info.global_port_is_prog(global_port));
VTR_ASSERT( (false == fabric_global_port_info.global_port_is_reset(global_port))
|| (false == fabric_global_port_info.global_port_is_set(global_port)));
if (true == fabric_global_port_info.global_port_is_reset(global_port)) {
global_prog_reset_ports.push_back(global_port);
}
}
return global_prog_reset_ports;
}
/********************************************************************
* Identify global set ports for programming
*******************************************************************/
std::vector<FabricGlobalPortId> find_fabric_global_programming_set_ports(const FabricGlobalPortInfo& fabric_global_port_info) {
/* Try to find global set ports for programming */
std::vector<FabricGlobalPortId> global_prog_set_ports;
for (const FabricGlobalPortId& global_port : fabric_global_port_info.global_ports()) {
if (false == fabric_global_port_info.global_port_is_prog(global_port)) {
continue;
}
VTR_ASSERT(true == fabric_global_port_info.global_port_is_prog(global_port));
VTR_ASSERT( (false == fabric_global_port_info.global_port_is_reset(global_port))
|| (false == fabric_global_port_info.global_port_is_set(global_port)));
if (true == fabric_global_port_info.global_port_is_set(global_port)) {
global_prog_set_ports.push_back(global_port);
}
}
return global_prog_set_ports;
}
} /* end namespace openfpga */

View File

@ -0,0 +1,23 @@
#ifndef FABRIC_GLOBAL_PORT_INFO_UTILS_H
#define FABRIC_GLOBAL_PORT_INFO_UTILS_H
/********************************************************************
* Include header files that are required by function declaration
*******************************************************************/
#include <vector>
#include "fabric_global_port_info.h"
/********************************************************************
* Function declaration
*******************************************************************/
/* begin namespace openfpga */
namespace openfpga {
std::vector<FabricGlobalPortId> find_fabric_global_programming_reset_ports(const FabricGlobalPortInfo& fabric_global_port_info);
std::vector<FabricGlobalPortId> find_fabric_global_programming_set_ports(const FabricGlobalPortInfo& fabric_global_port_info);
} /* end namespace openfpga */
#endif