Merge pull request #539 from lnis-uofu/bus_support
Support buses in Verilog testbenches
This commit is contained in:
commit
feaaeea787
|
@ -0,0 +1,40 @@
|
|||
.. _file_format_bus_group_file:
|
||||
|
||||
Bus Group File (.xml)
|
||||
=====================
|
||||
|
||||
The bus group file aims to show
|
||||
|
||||
- How bus ports are flatten by EDA engines, e.g., synthesis.
|
||||
- What are the pins in post-routing corresponding to the bus ports before synthesis
|
||||
|
||||
An example of file is shown as follows.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<bus_group>
|
||||
<bus name="i_addr[0:3]">
|
||||
<pin id="0" name="i_addr_0_"/>
|
||||
<pin id="1" name="i_addr_1_"/>
|
||||
<pin id="2" name="i_addr_2_"/>
|
||||
<pin id="3" name="i_addr_3_"/>
|
||||
</bus>
|
||||
</bus_group>
|
||||
|
||||
Bus-related Syntax
|
||||
------------------
|
||||
|
||||
.. option:: name="<string>"
|
||||
|
||||
The bus port defined before synthesis, e.g., addr[0:3]
|
||||
|
||||
Pin-related Syntax
|
||||
------------------
|
||||
|
||||
.. option:: id="<int>"
|
||||
|
||||
The index of the current pin in a bus port. The index must be the range of **[LSB, MSB-1]** that are defined in the bus.
|
||||
|
||||
.. option:: name="<string>"
|
||||
|
||||
The pin name after bus flatten in synthesis results
|
|
@ -25,3 +25,5 @@ OpenFPGA widely uses XML format for interchangable files
|
|||
io_mapping_file
|
||||
|
||||
bitstream_distribution_file
|
||||
|
||||
bus_group_file
|
||||
|
|
|
@ -68,6 +68,11 @@ write_full_testbench
|
|||
Specify the *Pin Constraints File* (PCF) if you want to custom stimulus in testbenches. For example, ``-pin_constraints_file pin_constraints.xml``
|
||||
Strongly recommend for multi-clock simulations. See detailed file format about :ref:`file_format_pin_constraints_file`.
|
||||
|
||||
.. option:: --bus_group_file <string> or -bgf <string>
|
||||
|
||||
Specify the *Bus Group File* (BGF) if you want to group pins to buses. For example, ``-bgf bus_group.xml``
|
||||
Strongly recommend when input HDL contains bus ports. See detailed file format about :ref:`file_format_bus_group_file`.
|
||||
|
||||
.. option:: --fast_configuration
|
||||
|
||||
Enable fast configuration phase for the top-level testbench in order to reduce runtime of simulations. It is applicable to configuration chain, memory bank and frame-based configuration protocols. For configuration chain, when enabled, the zeros at the head of the bitstream will be skipped. For memory bank and frame-based, when enabled, all the zero configuration bits will be skipped. So ensure that your memory cells can be correctly reset to zero with a reset signal.
|
||||
|
@ -120,6 +125,11 @@ write_preconfigured_fabric_wrapper
|
|||
Specify the *Pin Constraints File* (PCF) if you want to custom stimulus in testbenches. For example, ``-pin_constraints_file pin_constraints.xml``
|
||||
Strongly recommend for multi-clock simulations. See detailed file format about :ref:`file_format_pin_constraints_file`.
|
||||
|
||||
.. option:: --bus_group_file <string> or -bgf <string>
|
||||
|
||||
Specify the *Bus Group File* (BGF) if you want to group pins to buses. For example, ``-bgf bus_group.xml``
|
||||
Strongly recommend when input HDL contains bus ports. See detailed file format about :ref:`file_format_bus_group_file`.
|
||||
|
||||
.. option:: --explicit_port_mapping
|
||||
|
||||
Use explicit port mapping when writing the Verilog netlists
|
||||
|
@ -180,6 +190,11 @@ write_preconfigured_testbench
|
|||
Specify the *Pin Constraints File* (PCF) if you want to custom stimulus in testbenches. For example, ``-pin_constraints_file pin_constraints.xml``
|
||||
Strongly recommend for multi-clock simulations. See detailed file format about :ref:`file_format_pin_constraints_file`.
|
||||
|
||||
.. option:: --bus_group_file <string> or -bgf <string>
|
||||
|
||||
Specify the *Bus Group File* (BGF) if you want to group pins to buses. For example, ``-bgf bus_group.xml``
|
||||
Strongly recommend when input HDL contains bus ports. See detailed file format about :ref:`file_format_bus_group_file`.
|
||||
|
||||
.. option:: --explicit_port_mapping
|
||||
|
||||
Use explicit port mapping when writing the Verilog netlists
|
||||
|
|
|
@ -11,7 +11,7 @@ To enable various design purposes, OpenFPGA integrates several tools to i.e., FP
|
|||
.. _fig_openfpga_tools:
|
||||
|
||||
.. figure:: figures/openfpga_tools.svg
|
||||
:scale: 25%
|
||||
:width: 100%
|
||||
:alt: map to buried treasure
|
||||
|
||||
OpenFPGA tool suites and design flows
|
||||
|
|
|
@ -7,3 +7,4 @@ add_subdirectory(libfabrickey)
|
|||
add_subdirectory(librepackdc)
|
||||
add_subdirectory(libfpgabitstream)
|
||||
add_subdirectory(libpcf)
|
||||
add_subdirectory(libbusgroup)
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
cmake_minimum_required(VERSION 3.9)
|
||||
|
||||
project("libbusgroup")
|
||||
|
||||
file(GLOB_RECURSE EXEC_SOURCES test/*.cpp)
|
||||
file(GLOB_RECURSE LIB_SOURCES src/*.cpp)
|
||||
file(GLOB_RECURSE LIB_HEADERS src/*.h)
|
||||
files_to_dirs(LIB_HEADERS LIB_INCLUDE_DIRS)
|
||||
|
||||
#Remove test executable from library
|
||||
list(REMOVE_ITEM LIB_SOURCES ${EXEC_SOURCES})
|
||||
|
||||
#Create the library
|
||||
add_library(libbusgroup STATIC
|
||||
${LIB_HEADERS}
|
||||
${LIB_SOURCES})
|
||||
target_include_directories(libbusgroup PUBLIC ${LIB_INCLUDE_DIRS})
|
||||
set_target_properties(libbusgroup PROPERTIES PREFIX "") #Avoid extra 'lib' prefix
|
||||
|
||||
#Specify link-time dependancies
|
||||
target_link_libraries(libbusgroup
|
||||
libopenfpgautil
|
||||
libarchopenfpga
|
||||
libvtrutil
|
||||
libpugixml
|
||||
libpugiutil)
|
||||
|
||||
#Create the test executable
|
||||
foreach(testsourcefile ${EXEC_SOURCES})
|
||||
# Use a simple string replace, to cut off .cpp.
|
||||
get_filename_component(testname ${testsourcefile} NAME_WE)
|
||||
add_executable(${testname} ${testsourcefile})
|
||||
# Make sure the library is linked to each test executable
|
||||
target_link_libraries(${testname} libbusgroup)
|
||||
endforeach(testsourcefile ${EXEC_SOURCES})
|
|
@ -0,0 +1,8 @@
|
|||
<bus_group>
|
||||
<bus name="i_addr[0:3]">
|
||||
<pin id="0" name="i_addr_0_"/>
|
||||
<pin id="1" name="i_addr_1_"/>
|
||||
<pin id="2" name="i_addr_2_"/>
|
||||
<pin id="3" name="i_addr_3_"/>
|
||||
</bus>
|
||||
</bus_group>
|
|
@ -0,0 +1,170 @@
|
|||
#include <algorithm>
|
||||
|
||||
#include "vtr_assert.h"
|
||||
#include "vtr_log.h"
|
||||
|
||||
#include "bus_group.h"
|
||||
|
||||
namespace openfpga { // Begin namespace openfpga
|
||||
|
||||
/************************************************************************
|
||||
* Member functions for class BusGroup
|
||||
***********************************************************************/
|
||||
|
||||
/************************************************************************
|
||||
* Constructors
|
||||
***********************************************************************/
|
||||
BusGroup::BusGroup() {
|
||||
return;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Public Accessors : aggregates
|
||||
***********************************************************************/
|
||||
BusGroup::bus_group_range BusGroup::buses() const {
|
||||
return vtr::make_range(bus_ids_.begin(), bus_ids_.end());
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Public Accessors : Basic data query
|
||||
***********************************************************************/
|
||||
openfpga::BasicPort BusGroup::bus_port(const BusGroupId& bus_id) const {
|
||||
VTR_ASSERT(valid_bus_id(bus_id));
|
||||
return bus_ports_[bus_id];
|
||||
}
|
||||
|
||||
std::vector<BusPinId> BusGroup::bus_pins(const BusGroupId& bus_id) const {
|
||||
VTR_ASSERT(valid_bus_id(bus_id));
|
||||
return bus_pin_ids_[bus_id];
|
||||
}
|
||||
|
||||
int BusGroup::pin_index(const BusPinId& pin_id) const {
|
||||
VTR_ASSERT(valid_pin_id(pin_id));
|
||||
return pin_indices_[pin_id];
|
||||
}
|
||||
|
||||
std::string BusGroup::pin_name(const BusPinId& pin_id) const {
|
||||
VTR_ASSERT(valid_pin_id(pin_id));
|
||||
return pin_names_[pin_id];
|
||||
}
|
||||
|
||||
BusGroupId BusGroup::find_pin_bus(const std::string& pin_name) const {
|
||||
std::map<std::string, BusPinId>::const_iterator result = pin_name2id_map_.find(pin_name);
|
||||
if (result == pin_name2id_map_.end()) {
|
||||
/* Not found, return an invalid id */
|
||||
return BusGroupId::INVALID();
|
||||
}
|
||||
/* Found, we should get the parent bus */
|
||||
BusPinId pin_id = result->second;
|
||||
return pin_parent_bus_ids_[pin_id];
|
||||
}
|
||||
|
||||
BusGroupId BusGroup::find_bus(const std::string& bus_name) const {
|
||||
std::map<std::string, BusGroupId>::const_iterator result = bus_name2id_map_.find(bus_name);
|
||||
if (result == bus_name2id_map_.end()) {
|
||||
/* Not found, return an invalid id */
|
||||
return BusGroupId::INVALID();
|
||||
}
|
||||
/* Found, we should get the parent bus */
|
||||
return result->second;
|
||||
}
|
||||
|
||||
BusPinId BusGroup::find_pin(const std::string& pin_name) const {
|
||||
std::map<std::string, BusPinId>::const_iterator result = pin_name2id_map_.find(pin_name);
|
||||
if (result == pin_name2id_map_.end()) {
|
||||
/* Not found, return an invalid id */
|
||||
return BusPinId::INVALID();
|
||||
}
|
||||
/* Found, we should get the parent bus */
|
||||
return result->second;
|
||||
}
|
||||
|
||||
bool BusGroup::empty() const {
|
||||
return 0 == bus_ids_.size();
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Public Mutators
|
||||
***********************************************************************/
|
||||
void BusGroup::reserve_buses(const size_t& num_buses) {
|
||||
bus_ids_.reserve(num_buses);
|
||||
bus_ports_.reserve(num_buses);
|
||||
bus_pin_ids_.reserve(num_buses);
|
||||
}
|
||||
|
||||
void BusGroup::reserve_pins(const size_t& num_pins) {
|
||||
pin_ids_.reserve(num_pins);
|
||||
pin_indices_.reserve(num_pins);
|
||||
pin_names_.reserve(num_pins);
|
||||
pin_parent_bus_ids_.reserve(num_pins);
|
||||
}
|
||||
|
||||
BusGroupId BusGroup::create_bus(const openfpga::BasicPort& bus_port) {
|
||||
/* Create a new id */
|
||||
BusGroupId bus_id = BusGroupId(bus_ids_.size());
|
||||
|
||||
bus_ids_.push_back(bus_id);
|
||||
bus_ports_.push_back(bus_port);
|
||||
bus_pin_ids_.emplace_back();
|
||||
|
||||
/* Register to fast look-up */
|
||||
auto result = bus_name2id_map_.find(bus_port.get_name());
|
||||
if (result == bus_name2id_map_.end()) {
|
||||
bus_name2id_map_[bus_port.get_name()] = bus_id;
|
||||
} else {
|
||||
VTR_LOG_ERROR("Duplicated bus name '%s' in bus group", bus_port.get_name().c_str());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return bus_id;
|
||||
}
|
||||
|
||||
BusPinId BusGroup::create_pin(const BusGroupId& bus_id, const int& index) {
|
||||
/* Create a new id */
|
||||
BusPinId pin_id = BusPinId(pin_ids_.size());
|
||||
|
||||
pin_ids_.push_back(pin_id);
|
||||
|
||||
pin_indices_.push_back(index);
|
||||
pin_names_.emplace_back();
|
||||
|
||||
/* Register the pin to the bus */
|
||||
VTR_ASSERT(valid_bus_id(bus_id));
|
||||
pin_parent_bus_ids_.push_back(bus_id);
|
||||
|
||||
/* If the pin index is beyond the range of the bus_pin_ids, resize it */
|
||||
if (size_t(index) >= bus_pin_ids_[bus_id].size()) {
|
||||
bus_pin_ids_[bus_id].resize(index + 1);
|
||||
}
|
||||
bus_pin_ids_[bus_id][index] = pin_id;
|
||||
|
||||
return pin_id;
|
||||
}
|
||||
|
||||
|
||||
void BusGroup::set_pin_name(const BusPinId& pin_id, const std::string& name) {
|
||||
VTR_ASSERT(valid_pin_id(pin_id));
|
||||
pin_names_[pin_id] = name;
|
||||
|
||||
/* Register to fast look-up */
|
||||
auto result = pin_name2id_map_.find(name);
|
||||
if (result == pin_name2id_map_.end()) {
|
||||
pin_name2id_map_[name] = pin_id;
|
||||
} else {
|
||||
VTR_LOG_ERROR("Duplicated pin name '%s' in bus group", name.c_str());
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Internal invalidators/validators
|
||||
***********************************************************************/
|
||||
bool BusGroup::valid_bus_id(const BusGroupId& bus_id) const {
|
||||
return ( size_t(bus_id) < bus_ids_.size() ) && ( bus_id == bus_ids_[bus_id] );
|
||||
}
|
||||
|
||||
bool BusGroup::valid_pin_id(const BusPinId& pin_id) const {
|
||||
return ( size_t(pin_id) < pin_ids_.size() ) && ( pin_id == pin_ids_[pin_id] );
|
||||
}
|
||||
|
||||
} // End of namespace openfpga
|
|
@ -0,0 +1,125 @@
|
|||
#ifndef BUS_GROUP_H
|
||||
#define BUS_GROUP_H
|
||||
|
||||
/********************************************************************
|
||||
* This file include the declaration of pin constraints
|
||||
*******************************************************************/
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <array>
|
||||
|
||||
/* Headers from vtrutil library */
|
||||
#include "vtr_vector.h"
|
||||
|
||||
/* Headers from openfpgautil library */
|
||||
#include "openfpga_port.h"
|
||||
|
||||
#include "bus_group_fwd.h"
|
||||
|
||||
namespace openfpga { // Begin namespace openfpga
|
||||
|
||||
/********************************************************************
|
||||
* A data structure to describe the bus-to-pin mapping
|
||||
* This data structure may include a number of buses
|
||||
* each of which has:
|
||||
* - a unique id and name
|
||||
* - a number of pins with names and index which are flatten from the bus
|
||||
*
|
||||
* Typical usage:
|
||||
* --------------
|
||||
* // Create an object of bus group
|
||||
* BusGroup bus_group;
|
||||
* // Create a new port
|
||||
* BasicPort bus_a("BusA", 0, 3)
|
||||
* // Add a bus
|
||||
* BusGroupId bus_group_id = bus_group.create_bus(bus_a);
|
||||
*
|
||||
*******************************************************************/
|
||||
class BusGroup {
|
||||
public: /* Types */
|
||||
typedef vtr::vector<BusGroupId, BusGroupId>::const_iterator bus_group_iterator;
|
||||
typedef vtr::vector<BusPinId, BusPinId>::const_iterator bus_pin_iterator;
|
||||
/* Create range */
|
||||
typedef vtr::Range<bus_group_iterator> bus_group_range;
|
||||
typedef vtr::Range<bus_pin_iterator> bus_pin_range;
|
||||
public: /* Constructors */
|
||||
BusGroup();
|
||||
public: /* Accessors: aggregates */
|
||||
bus_group_range buses() const;
|
||||
public: /* Public Accessors: Basic data query */
|
||||
/** Get port information of a bus with a given id */
|
||||
BasicPort bus_port(const BusGroupId& bus_id) const;
|
||||
|
||||
/* Get the pins under a specific bus */
|
||||
std::vector<BusPinId> bus_pins(const BusGroupId& bus_id) const;
|
||||
|
||||
/* Get the index of a pin */
|
||||
int pin_index(const BusPinId& pin_id) const;
|
||||
|
||||
/* Get the name of a pin */
|
||||
std::string pin_name(const BusPinId& pin_id) const;
|
||||
|
||||
/* Find the bus that a pin belongs to */
|
||||
BusGroupId find_pin_bus(const std::string& pin_name) const;
|
||||
|
||||
/* Find the bus id with a given name */
|
||||
BusGroupId find_bus(const std::string& bus_name) const;
|
||||
|
||||
/* Find the pin id with a given name */
|
||||
BusPinId find_pin(const std::string& pin_name) const;
|
||||
|
||||
/* Check if there are any buses */
|
||||
bool empty() const;
|
||||
|
||||
public: /* Public Mutators */
|
||||
/* Reserve a number of buses to be memory efficent */
|
||||
void reserve_buses(const size_t& num_buses);
|
||||
|
||||
/* Reserve a number of pins to be memory efficent */
|
||||
void reserve_pins(const size_t& num_pins);
|
||||
|
||||
/* Add a bus to storage */
|
||||
BusGroupId create_bus(const openfpga::BasicPort& bus_port);
|
||||
|
||||
/* Add a pin to a bus, with a given index in the bus, e.g., A[1] in A[0:2] */
|
||||
BusPinId create_pin(const BusGroupId& bus_id, const int& index);
|
||||
|
||||
/* Set the name for a pin */
|
||||
void set_pin_name(const BusPinId& pin_id, const std::string& name);
|
||||
|
||||
public: /* Public invalidators/validators */
|
||||
/* Show if the bus id is a valid for data queries */
|
||||
bool valid_bus_id(const BusGroupId& bus_id) const;
|
||||
|
||||
/* Show if the pin id is a valid for data queries */
|
||||
bool valid_pin_id(const BusPinId& pin_id) const;
|
||||
|
||||
private: /* Internal data */
|
||||
/* Unique ids for each bus */
|
||||
vtr::vector<BusGroupId, BusGroupId> bus_ids_;
|
||||
|
||||
/* Port information of each bus */
|
||||
vtr::vector<BusGroupId, BasicPort> bus_ports_;
|
||||
|
||||
/* Indices of each pin under each bus */
|
||||
vtr::vector<BusGroupId, std::vector<BusPinId>> bus_pin_ids_;
|
||||
|
||||
/* Unique ids for each pin */
|
||||
vtr::vector<BusPinId, BusPinId> pin_ids_;
|
||||
|
||||
/* Index for each pin */
|
||||
vtr::vector<BusPinId, int> pin_indices_;
|
||||
|
||||
/* Name of each pin under each bus */
|
||||
vtr::vector<BusPinId, std::string> pin_names_;
|
||||
|
||||
/* Parent bus of each pin */
|
||||
vtr::vector<BusPinId, BusGroupId> pin_parent_bus_ids_;
|
||||
|
||||
/* Fast look-up */
|
||||
std::map<std::string, BusGroupId> bus_name2id_map_;
|
||||
std::map<std::string, BusPinId> pin_name2id_map_;
|
||||
};
|
||||
|
||||
} // End of namespace openfpga
|
||||
#endif
|
|
@ -0,0 +1,28 @@
|
|||
/************************************************************************
|
||||
* A header file for BusGroup class, including critical data declaration
|
||||
* Please include this file only for using any PinConstraints data structure
|
||||
* Refer to bus_group.h for more details
|
||||
***********************************************************************/
|
||||
|
||||
/************************************************************************
|
||||
* Create strong id for BusGroup to avoid illegal type casting
|
||||
***********************************************************************/
|
||||
#ifndef BUS_GROUP_FWD_H
|
||||
#define BUS_GROUP_FWD_H
|
||||
|
||||
#include "vtr_strong_id.h"
|
||||
|
||||
namespace openfpga { // Begin namespace openfpga
|
||||
|
||||
struct bus_group_id_tag;
|
||||
struct bus_pin_id_tag;
|
||||
|
||||
typedef vtr::StrongId<bus_group_id_tag> BusGroupId;
|
||||
typedef vtr::StrongId<bus_pin_id_tag> BusPinId;
|
||||
|
||||
/* Short declaration of class */
|
||||
class BusGroup;
|
||||
|
||||
} // End of namespace openfpga
|
||||
|
||||
#endif
|
|
@ -0,0 +1,13 @@
|
|||
#ifndef BUS_GROUP_XML_CONSTANTS_H
|
||||
#define BUS_GROUP_XML_CONSTANTS_H
|
||||
|
||||
/* Constants required by XML parser */
|
||||
|
||||
constexpr char* XML_BUS_GROUP_NODE_NAME = "bus_group";
|
||||
constexpr char* XML_BUS_NODE_NAME = "bus";
|
||||
constexpr char* XML_BUS_PORT_ATTRIBUTE_NAME = "name";
|
||||
constexpr char* XML_PIN_NODE_NAME = "pin";
|
||||
constexpr char* XML_PIN_INDEX_ATTRIBUTE_NAME = "id";
|
||||
constexpr char* XML_PIN_NAME_ATTRIBUTE_NAME = "name";
|
||||
|
||||
#endif
|
|
@ -0,0 +1,134 @@
|
|||
/********************************************************************
|
||||
* This file includes the top-level function of this library
|
||||
* which reads an XML of bus group file to the associated
|
||||
* data structures
|
||||
*******************************************************************/
|
||||
#include <string>
|
||||
|
||||
/* Headers from pugi XML library */
|
||||
#include "pugixml.hpp"
|
||||
#include "pugixml_util.hpp"
|
||||
|
||||
/* Headers from vtr util library */
|
||||
#include "vtr_assert.h"
|
||||
#include "vtr_time.h"
|
||||
|
||||
/* Headers from libopenfpga util library */
|
||||
#include "openfpga_port_parser.h"
|
||||
|
||||
/* Headers from libarchfpga */
|
||||
#include "arch_error.h"
|
||||
#include "read_xml_util.h"
|
||||
|
||||
#include "bus_group_xml_constants.h"
|
||||
#include "read_xml_bus_group.h"
|
||||
|
||||
namespace openfpga { // Begin namespace openfpga
|
||||
|
||||
/********************************************************************
|
||||
* Parse XML codes of a <pin> to an object of BusGroup
|
||||
*******************************************************************/
|
||||
static
|
||||
void read_xml_pin(pugi::xml_node& xml_pin,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
BusGroup& bus_group,
|
||||
const BusGroupId& bus_id) {
|
||||
if (false == bus_group.valid_bus_id(bus_id)) {
|
||||
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_pin),
|
||||
"Invalid id of a bus group!\n");
|
||||
}
|
||||
|
||||
int pin_index = get_attribute(xml_pin, XML_PIN_INDEX_ATTRIBUTE_NAME, loc_data).as_int();
|
||||
std::string pin_name = get_attribute(xml_pin, XML_PIN_NAME_ATTRIBUTE_NAME, loc_data).as_string();
|
||||
|
||||
/* Before update storage, check if the pin index is in the range */
|
||||
BasicPort pin_port(bus_group.bus_port(bus_id).get_name(), pin_index, pin_index);
|
||||
if (!bus_group.bus_port(bus_id).contained(pin_port)) {
|
||||
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_pin),
|
||||
"Pin index is out of range of the bus port width!\n");
|
||||
}
|
||||
|
||||
BusPinId pin_id = bus_group.create_pin(bus_id, pin_index);
|
||||
bus_group.set_pin_name(pin_id, pin_name);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Parse XML codes of a <bus> to an object of BusGroup
|
||||
*******************************************************************/
|
||||
static
|
||||
void read_xml_bus(pugi::xml_node& xml_bus,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
BusGroup& bus_group) {
|
||||
|
||||
openfpga::PortParser port_parser(get_attribute(xml_bus, XML_BUS_PORT_ATTRIBUTE_NAME, loc_data).as_string());
|
||||
|
||||
/* Create a new bus in the storage */
|
||||
BusGroupId bus_id = bus_group.create_bus(port_parser.port());
|
||||
|
||||
if (false == bus_group.valid_bus_id(bus_id)) {
|
||||
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_bus),
|
||||
"Fail to create a bus group!\n");
|
||||
}
|
||||
|
||||
/* Ensure the bus port is valid */
|
||||
if (!bus_group.bus_port(bus_id).is_valid()) {
|
||||
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_bus),
|
||||
"Bus port is invalid, check LSB and MSB!\n");
|
||||
}
|
||||
|
||||
for (pugi::xml_node xml_pin : xml_bus.children()) {
|
||||
/* Error out if the XML child has an invalid name! */
|
||||
if (xml_pin.name() != std::string(XML_PIN_NODE_NAME)) {
|
||||
bad_tag(xml_pin, loc_data, xml_bus, {XML_PIN_NODE_NAME});
|
||||
}
|
||||
read_xml_pin(xml_pin, loc_data, bus_group, bus_id);
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Parse XML codes about <bus_group> to an object of BusGroup
|
||||
*******************************************************************/
|
||||
BusGroup read_xml_bus_group(const char* fname) {
|
||||
|
||||
vtr::ScopedStartFinishTimer timer("Read Bus Group");
|
||||
|
||||
BusGroup bus_group;
|
||||
|
||||
/* Parse the file */
|
||||
pugi::xml_document doc;
|
||||
pugiutil::loc_data loc_data;
|
||||
|
||||
try {
|
||||
loc_data = pugiutil::load_xml(doc, fname);
|
||||
|
||||
pugi::xml_node xml_root = get_single_child(doc, XML_BUS_GROUP_NODE_NAME, loc_data);
|
||||
|
||||
size_t num_buses = std::distance(xml_root.children().begin(), xml_root.children().end());
|
||||
|
||||
/* Count the total number of pins */
|
||||
size_t num_pins = 0;
|
||||
for (pugi::xml_node xml_bus : xml_root.children()) {
|
||||
num_pins += std::distance(xml_bus.children().begin(), xml_bus.children().end());
|
||||
}
|
||||
|
||||
/* Reserve memory space for the buses */
|
||||
bus_group.reserve_buses(num_buses);
|
||||
/* Reserve memory space for the pins */
|
||||
bus_group.reserve_pins(num_pins);
|
||||
|
||||
for (pugi::xml_node xml_bus : xml_root.children()) {
|
||||
/* Error out if the XML child has an invalid name! */
|
||||
if (xml_bus.name() != std::string(XML_BUS_NODE_NAME)) {
|
||||
bad_tag(xml_bus, loc_data, xml_root, {XML_BUS_NODE_NAME});
|
||||
}
|
||||
read_xml_bus(xml_bus, loc_data, bus_group);
|
||||
}
|
||||
} catch (pugiutil::XmlError& e) {
|
||||
archfpga_throw(fname, e.line(),
|
||||
"%s", e.what());
|
||||
}
|
||||
|
||||
return bus_group;
|
||||
}
|
||||
|
||||
} // End of namespace openfpga
|
|
@ -0,0 +1,21 @@
|
|||
#ifndef READ_XML_BUS_GROUP_H
|
||||
#define READ_XML_BUS_GROUP_H
|
||||
|
||||
/********************************************************************
|
||||
* Include header files that are required by function declaration
|
||||
*******************************************************************/
|
||||
#include "pugixml_util.hpp"
|
||||
#include "pugixml.hpp"
|
||||
#include "bus_group.h"
|
||||
|
||||
/********************************************************************
|
||||
* Function declaration
|
||||
*******************************************************************/
|
||||
|
||||
namespace openfpga { // Begin namespace openfpga
|
||||
|
||||
BusGroup read_xml_bus_group(const char* fname);
|
||||
|
||||
} // End of namespace openfpga
|
||||
|
||||
#endif
|
|
@ -0,0 +1,112 @@
|
|||
/********************************************************************
|
||||
* This file includes functions that outputs a bus group object to XML format
|
||||
*******************************************************************/
|
||||
/* Headers from system goes first */
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
|
||||
/* Headers from vtr util library */
|
||||
#include "vtr_assert.h"
|
||||
#include "vtr_log.h"
|
||||
#include "vtr_time.h"
|
||||
|
||||
/* Headers from openfpga util library */
|
||||
#include "openfpga_digest.h"
|
||||
|
||||
/* Headers from arch openfpga library */
|
||||
#include "write_xml_utils.h"
|
||||
|
||||
/* Headers from pin constraint library */
|
||||
#include "bus_group_xml_constants.h"
|
||||
#include "write_xml_bus_group.h"
|
||||
|
||||
namespace openfpga { // Begin namespace openfpga
|
||||
|
||||
/********************************************************************
|
||||
* A writer to output a bus to XML format
|
||||
*
|
||||
* Return 0 if successful
|
||||
* Return 1 if there are more serious bugs in the architecture
|
||||
* Return 2 if fail when creating files
|
||||
*******************************************************************/
|
||||
static
|
||||
int write_xml_bus(std::fstream& fp,
|
||||
const BusGroup& bus_group,
|
||||
const BusGroupId& bus_id) {
|
||||
/* Validate the file stream */
|
||||
if (false == openfpga::valid_file_stream(fp)) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
openfpga::write_tab_to_file(fp, 1);
|
||||
fp << "<" << XML_BUS_NODE_NAME << "";
|
||||
|
||||
if (false == bus_group.valid_bus_id(bus_id)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
write_xml_attribute(fp, XML_BUS_PORT_ATTRIBUTE_NAME, generate_xml_port_name(bus_group.bus_port(bus_id)).c_str());
|
||||
fp << ">" << "\n";
|
||||
|
||||
/* Output all the pins under this bus */
|
||||
for (const BusPinId& pin_id : bus_group.bus_pins(bus_id)) {
|
||||
openfpga::write_tab_to_file(fp, 2);
|
||||
fp << "<" << XML_PIN_NODE_NAME << "";
|
||||
|
||||
write_xml_attribute(fp, XML_PIN_INDEX_ATTRIBUTE_NAME, bus_group.pin_index(pin_id));
|
||||
write_xml_attribute(fp, XML_PIN_NAME_ATTRIBUTE_NAME, bus_group.pin_name(pin_id).c_str());
|
||||
|
||||
fp << "/>" << "\n";
|
||||
}
|
||||
|
||||
openfpga::write_tab_to_file(fp, 1);
|
||||
fp << "</" << XML_BUS_NODE_NAME << "";
|
||||
fp << ">" << "\n";
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* A writer to output a bus group object to XML format
|
||||
*
|
||||
* Return 0 if successful
|
||||
* Return 1 if there are more serious bugs in the architecture
|
||||
* Return 2 if fail when creating files
|
||||
*******************************************************************/
|
||||
int write_xml_bus_group(const char* fname,
|
||||
const BusGroup& bus_group) {
|
||||
|
||||
vtr::ScopedStartFinishTimer timer("Write Bus Group");
|
||||
|
||||
/* Create a file handler */
|
||||
std::fstream fp;
|
||||
/* Open the file stream */
|
||||
fp.open(std::string(fname), std::fstream::out | std::fstream::trunc);
|
||||
|
||||
/* Validate the file stream */
|
||||
openfpga::check_file_stream(fname, fp);
|
||||
|
||||
/* Write the root node */
|
||||
fp << "<" << XML_BUS_GROUP_NODE_NAME << ">" << "\n";
|
||||
|
||||
int err_code = 0;
|
||||
|
||||
/* Write each bus */
|
||||
for (const BusGroupId& bus : bus_group.buses()) {
|
||||
/* Write bus */
|
||||
err_code = write_xml_bus(fp, bus_group, bus);
|
||||
if (0 != err_code) {
|
||||
return err_code;
|
||||
}
|
||||
}
|
||||
|
||||
/* Finish writing the root node */
|
||||
fp << "</" << XML_BUS_GROUP_NODE_NAME << ">" << "\n";
|
||||
|
||||
/* Close the file stream */
|
||||
fp.close();
|
||||
|
||||
return err_code;
|
||||
}
|
||||
|
||||
} // End of namespace openfpga
|
|
@ -0,0 +1,20 @@
|
|||
#ifndef WRITE_XML_BUS_GROUP_H
|
||||
#define WRITE_XML_BUS_GROUP_H
|
||||
|
||||
/********************************************************************
|
||||
* Include header files that are required by function declaration
|
||||
*******************************************************************/
|
||||
#include <fstream>
|
||||
#include "bus_group.h"
|
||||
|
||||
/********************************************************************
|
||||
* Function declaration
|
||||
*******************************************************************/
|
||||
namespace openfpga { // Begin namespace openfpga
|
||||
|
||||
int write_xml_bus_group(const char* fname,
|
||||
const BusGroup& bus_group);
|
||||
|
||||
} // End of namespace openfpga
|
||||
|
||||
#endif
|
|
@ -0,0 +1,33 @@
|
|||
/********************************************************************
|
||||
* Unit test functions to validate the correctness of
|
||||
* 1. parser of data structures
|
||||
* 2. writer of data structures
|
||||
*******************************************************************/
|
||||
/* Headers from vtrutils */
|
||||
#include "vtr_assert.h"
|
||||
#include "vtr_log.h"
|
||||
|
||||
/* Headers from readarchopenfpga */
|
||||
#include "read_xml_bus_group.h"
|
||||
#include "write_xml_bus_group.h"
|
||||
|
||||
int main(int argc, const char** argv) {
|
||||
/* Ensure we have only one or two argument */
|
||||
VTR_ASSERT((2 == argc) || (3 == argc));
|
||||
|
||||
/* Parse the circuit library from an XML file */
|
||||
const openfpga::BusGroup& bus_group = openfpga::read_xml_bus_group(argv[1]);
|
||||
VTR_LOG("Parsed %lu bus(es) from XML into bus group.\n",
|
||||
bus_group.buses().size());
|
||||
|
||||
/* Output the bus group to an XML file
|
||||
* This is optional only used when there is a second argument
|
||||
*/
|
||||
if (3 <= argc) {
|
||||
openfpga::write_xml_bus_group(argv[2], bus_group);
|
||||
VTR_LOG("Write the bus group to an XML file: %s.\n",
|
||||
argv[2]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -28,6 +28,7 @@ target_link_libraries(libopenfpga
|
|||
libini
|
||||
libpcf
|
||||
libvtrutil
|
||||
libbusgroup
|
||||
libvpr)
|
||||
|
||||
#Create the test executable
|
||||
|
|
|
@ -17,6 +17,9 @@
|
|||
/* Headers from pcf library */
|
||||
#include "read_xml_pin_constraints.h"
|
||||
|
||||
/* Headers from bgf library */
|
||||
#include "read_xml_bus_group.h"
|
||||
|
||||
/* Include global variables of VPR */
|
||||
#include "globals.h"
|
||||
|
||||
|
@ -79,6 +82,7 @@ int write_full_testbench(const OpenfpgaContext& openfpga_ctx,
|
|||
CommandOptionId opt_bitstream = cmd.option("bitstream");
|
||||
CommandOptionId opt_fabric_netlist = cmd.option("fabric_netlist_file_path");
|
||||
CommandOptionId opt_pcf = cmd.option("pin_constraints_file");
|
||||
CommandOptionId opt_bgf = cmd.option("bus_group_file");
|
||||
CommandOptionId opt_reference_benchmark = cmd.option("reference_benchmark_file_path");
|
||||
CommandOptionId opt_fast_configuration = cmd.option("fast_configuration");
|
||||
CommandOptionId opt_explicit_port_mapping = cmd.option("explicit_port_mapping");
|
||||
|
@ -112,6 +116,12 @@ int write_full_testbench(const OpenfpgaContext& openfpga_ctx,
|
|||
pin_constraints = read_xml_pin_constraints(cmd_context.option_value(cmd, opt_pcf).c_str());
|
||||
}
|
||||
|
||||
/* If bug group file are enabled by command options, read the file */
|
||||
BusGroup bus_group;
|
||||
if (true == cmd_context.option_enable(cmd, opt_bgf)) {
|
||||
bus_group = read_xml_bus_group(cmd_context.option_value(cmd, opt_bgf).c_str());
|
||||
}
|
||||
|
||||
return fpga_verilog_full_testbench(openfpga_ctx.module_graph(),
|
||||
openfpga_ctx.bitstream_manager(),
|
||||
openfpga_ctx.fabric_bitstream(),
|
||||
|
@ -119,6 +129,7 @@ int write_full_testbench(const OpenfpgaContext& openfpga_ctx,
|
|||
g_vpr_ctx.atom(),
|
||||
g_vpr_ctx.placement(),
|
||||
pin_constraints,
|
||||
bus_group,
|
||||
cmd_context.option_value(cmd, opt_bitstream),
|
||||
openfpga_ctx.io_location_map(),
|
||||
openfpga_ctx.fabric_global_port_info(),
|
||||
|
@ -138,6 +149,7 @@ int write_preconfigured_fabric_wrapper(const OpenfpgaContext& openfpga_ctx,
|
|||
CommandOptionId opt_output_dir = cmd.option("file");
|
||||
CommandOptionId opt_fabric_netlist = cmd.option("fabric_netlist_file_path");
|
||||
CommandOptionId opt_pcf = cmd.option("pin_constraints_file");
|
||||
CommandOptionId opt_bgf = cmd.option("bus_group_file");
|
||||
CommandOptionId opt_explicit_port_mapping = cmd.option("explicit_port_mapping");
|
||||
CommandOptionId opt_default_net_type = cmd.option("default_net_type");
|
||||
CommandOptionId opt_include_signal_init = cmd.option("include_signal_init");
|
||||
|
@ -171,11 +183,18 @@ int write_preconfigured_fabric_wrapper(const OpenfpgaContext& openfpga_ctx,
|
|||
pin_constraints = read_xml_pin_constraints(cmd_context.option_value(cmd, opt_pcf).c_str());
|
||||
}
|
||||
|
||||
/* If bug group file are enabled by command options, read the file */
|
||||
BusGroup bus_group;
|
||||
if (true == cmd_context.option_enable(cmd, opt_bgf)) {
|
||||
bus_group = read_xml_bus_group(cmd_context.option_value(cmd, opt_bgf).c_str());
|
||||
}
|
||||
|
||||
return fpga_verilog_preconfigured_fabric_wrapper(openfpga_ctx.module_graph(),
|
||||
openfpga_ctx.bitstream_manager(),
|
||||
g_vpr_ctx.atom(),
|
||||
g_vpr_ctx.placement(),
|
||||
pin_constraints,
|
||||
bus_group,
|
||||
openfpga_ctx.io_location_map(),
|
||||
openfpga_ctx.fabric_global_port_info(),
|
||||
openfpga_ctx.vpr_netlist_annotation(),
|
||||
|
@ -192,6 +211,7 @@ int write_preconfigured_testbench(const OpenfpgaContext& openfpga_ctx,
|
|||
|
||||
CommandOptionId opt_output_dir = cmd.option("file");
|
||||
CommandOptionId opt_pcf = cmd.option("pin_constraints_file");
|
||||
CommandOptionId opt_bgf = cmd.option("bus_group_file");
|
||||
CommandOptionId opt_fabric_netlist = cmd.option("fabric_netlist_file_path");
|
||||
CommandOptionId opt_reference_benchmark = cmd.option("reference_benchmark_file_path");
|
||||
CommandOptionId opt_explicit_port_mapping = cmd.option("explicit_port_mapping");
|
||||
|
@ -222,9 +242,16 @@ int write_preconfigured_testbench(const OpenfpgaContext& openfpga_ctx,
|
|||
pin_constraints = read_xml_pin_constraints(cmd_context.option_value(cmd, opt_pcf).c_str());
|
||||
}
|
||||
|
||||
/* If bug group file are enabled by command options, read the file */
|
||||
BusGroup bus_group;
|
||||
if (true == cmd_context.option_enable(cmd, opt_bgf)) {
|
||||
bus_group = read_xml_bus_group(cmd_context.option_value(cmd, opt_bgf).c_str());
|
||||
}
|
||||
|
||||
return fpga_verilog_preconfigured_testbench(openfpga_ctx.module_graph(),
|
||||
g_vpr_ctx.atom(),
|
||||
pin_constraints,
|
||||
bus_group,
|
||||
openfpga_ctx.fabric_global_port_info(),
|
||||
openfpga_ctx.vpr_netlist_annotation(),
|
||||
openfpga_ctx.simulation_setting(),
|
||||
|
|
|
@ -89,6 +89,11 @@ ShellCommandId add_openfpga_write_full_testbench_command(openfpga::Shell<Openfpg
|
|||
shell_cmd.set_option_short_name(pcf_opt, "pcf");
|
||||
shell_cmd.set_option_require_value(pcf_opt, openfpga::OPT_STRING);
|
||||
|
||||
/* add an option '--bus_group_file in short '-bgf' */
|
||||
CommandOptionId bgf_opt = shell_cmd.add_option("bus_group_file", false, "specify the file path to the group pins to bus");
|
||||
shell_cmd.set_option_short_name(bgf_opt, "bgf");
|
||||
shell_cmd.set_option_require_value(bgf_opt, openfpga::OPT_STRING);
|
||||
|
||||
/* add an option '--reference_benchmark_file_path'*/
|
||||
CommandOptionId ref_bm_opt = shell_cmd.add_option("reference_benchmark_file_path", false, "specify the file path to the reference verilog netlist. If specified, the testbench will include self-checking codes");
|
||||
shell_cmd.set_option_require_value(ref_bm_opt, openfpga::OPT_STRING);
|
||||
|
@ -154,6 +159,11 @@ ShellCommandId add_openfpga_write_preconfigured_fabric_wrapper_command(openfpga:
|
|||
shell_cmd.set_option_short_name(pcf_opt, "pcf");
|
||||
shell_cmd.set_option_require_value(pcf_opt, openfpga::OPT_STRING);
|
||||
|
||||
/* add an option '--bus_group_file in short '-bgf' */
|
||||
CommandOptionId bgf_opt = shell_cmd.add_option("bus_group_file", false, "specify the file path to the group pins to bus");
|
||||
shell_cmd.set_option_short_name(bgf_opt, "bgf");
|
||||
shell_cmd.set_option_require_value(bgf_opt, openfpga::OPT_STRING);
|
||||
|
||||
/* add an option '--explicit_port_mapping' */
|
||||
shell_cmd.add_option("explicit_port_mapping", false, "use explicit port mapping in verilog netlists");
|
||||
|
||||
|
@ -210,6 +220,11 @@ ShellCommandId add_openfpga_write_preconfigured_testbench_command(openfpga::Shel
|
|||
shell_cmd.set_option_short_name(pcf_opt, "pcf");
|
||||
shell_cmd.set_option_require_value(pcf_opt, openfpga::OPT_STRING);
|
||||
|
||||
/* add an option '--bus_group_file in short '-bgf' */
|
||||
CommandOptionId bgf_opt = shell_cmd.add_option("bus_group_file", false, "specify the file path to the group pins to bus");
|
||||
shell_cmd.set_option_short_name(bgf_opt, "bgf");
|
||||
shell_cmd.set_option_require_value(bgf_opt, openfpga::OPT_STRING);
|
||||
|
||||
/* Add an option '--reference_benchmark_file_path'*/
|
||||
CommandOptionId ref_bm_opt = shell_cmd.add_option("reference_benchmark_file_path", false, "Specify the file path to the reference Verilog netlist. If specified, the testbench will include self-checking codes");
|
||||
shell_cmd.set_option_require_value(ref_bm_opt, openfpga::OPT_STRING);
|
||||
|
|
|
@ -159,6 +159,7 @@ int fpga_verilog_full_testbench(const ModuleManager &module_manager,
|
|||
const AtomContext &atom_ctx,
|
||||
const PlacementContext &place_ctx,
|
||||
const PinConstraints& pin_constraints,
|
||||
const BusGroup& bus_group,
|
||||
const std::string& bitstream_file,
|
||||
const IoLocationMap &io_location_map,
|
||||
const FabricGlobalPortInfo &fabric_global_port_info,
|
||||
|
@ -188,6 +189,7 @@ int fpga_verilog_full_testbench(const ModuleManager &module_manager,
|
|||
fabric_global_port_info,
|
||||
atom_ctx, place_ctx,
|
||||
pin_constraints,
|
||||
bus_group,
|
||||
bitstream_file,
|
||||
io_location_map,
|
||||
netlist_annotation,
|
||||
|
@ -214,6 +216,7 @@ int fpga_verilog_preconfigured_fabric_wrapper(const ModuleManager &module_manage
|
|||
const AtomContext &atom_ctx,
|
||||
const PlacementContext &place_ctx,
|
||||
const PinConstraints& pin_constraints,
|
||||
const BusGroup& bus_group,
|
||||
const IoLocationMap &io_location_map,
|
||||
const FabricGlobalPortInfo &fabric_global_port_info,
|
||||
const VprNetlistAnnotation &netlist_annotation,
|
||||
|
@ -239,6 +242,7 @@ int fpga_verilog_preconfigured_fabric_wrapper(const ModuleManager &module_manage
|
|||
circuit_lib, fabric_global_port_info,
|
||||
atom_ctx, place_ctx,
|
||||
pin_constraints,
|
||||
bus_group,
|
||||
io_location_map,
|
||||
netlist_annotation,
|
||||
netlist_name,
|
||||
|
@ -257,6 +261,7 @@ int fpga_verilog_preconfigured_fabric_wrapper(const ModuleManager &module_manage
|
|||
int fpga_verilog_preconfigured_testbench(const ModuleManager &module_manager,
|
||||
const AtomContext &atom_ctx,
|
||||
const PinConstraints& pin_constraints,
|
||||
const BusGroup& bus_group,
|
||||
const FabricGlobalPortInfo &fabric_global_port_info,
|
||||
const VprNetlistAnnotation &netlist_annotation,
|
||||
const SimulationSetting &simulation_setting,
|
||||
|
@ -282,6 +287,7 @@ int fpga_verilog_preconfigured_testbench(const ModuleManager &module_manager,
|
|||
module_manager,
|
||||
fabric_global_port_info,
|
||||
pin_constraints,
|
||||
bus_group,
|
||||
simulation_setting,
|
||||
options);
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "fabric_global_port_info.h"
|
||||
#include "vpr_netlist_annotation.h"
|
||||
#include "memory_bank_shift_register_banks.h"
|
||||
#include "bus_group.h"
|
||||
#include "fabric_verilog_options.h"
|
||||
#include "verilog_testbench_options.h"
|
||||
|
||||
|
@ -52,6 +53,7 @@ int fpga_verilog_full_testbench(const ModuleManager& module_manager,
|
|||
const AtomContext& atom_ctx,
|
||||
const PlacementContext& place_ctx,
|
||||
const PinConstraints& pin_constraints,
|
||||
const BusGroup& bus_group,
|
||||
const std::string& bitstream_file,
|
||||
const IoLocationMap& io_location_map,
|
||||
const FabricGlobalPortInfo &fabric_global_port_info,
|
||||
|
@ -66,6 +68,7 @@ int fpga_verilog_preconfigured_fabric_wrapper(const ModuleManager &module_manage
|
|||
const AtomContext &atom_ctx,
|
||||
const PlacementContext &place_ctx,
|
||||
const PinConstraints& pin_constraints,
|
||||
const BusGroup& bus_group,
|
||||
const IoLocationMap &io_location_map,
|
||||
const FabricGlobalPortInfo &fabric_global_port_info,
|
||||
const VprNetlistAnnotation &netlist_annotation,
|
||||
|
@ -76,6 +79,7 @@ int fpga_verilog_preconfigured_fabric_wrapper(const ModuleManager &module_manage
|
|||
int fpga_verilog_preconfigured_testbench(const ModuleManager &module_manager,
|
||||
const AtomContext &atom_ctx,
|
||||
const PinConstraints& pin_constraints,
|
||||
const BusGroup& bus_group,
|
||||
const FabricGlobalPortInfo &fabric_global_port_info,
|
||||
const VprNetlistAnnotation &netlist_annotation,
|
||||
const SimulationSetting &simulation_setting,
|
||||
|
|
|
@ -109,6 +109,7 @@ void print_verilog_top_random_testbench_benchmark_instance(std::fstream& fp,
|
|||
const AtomContext& atom_ctx,
|
||||
const VprNetlistAnnotation& netlist_annotation,
|
||||
const PinConstraints& pin_constraints,
|
||||
const BusGroup& bus_group,
|
||||
const bool& explicit_port_mapping) {
|
||||
/* Validate the file stream */
|
||||
valid_file_stream(fp);
|
||||
|
@ -116,22 +117,16 @@ void print_verilog_top_random_testbench_benchmark_instance(std::fstream& fp,
|
|||
/* Instanciate benchmark */
|
||||
print_verilog_comment(fp, std::string("----- Reference Benchmark Instanication -------"));
|
||||
|
||||
/* Do NOT use explicit port mapping here:
|
||||
* VPR added a prefix of "out_" to the output ports of input benchmark
|
||||
*/
|
||||
std::vector<std::string> prefix_to_remove;
|
||||
prefix_to_remove.push_back(std::string(VPR_BENCHMARK_OUT_PORT_PREFIX));
|
||||
prefix_to_remove.push_back(std::string(OPENFPGA_BENCHMARK_OUT_PORT_PREFIX));
|
||||
print_verilog_testbench_benchmark_instance(fp, reference_verilog_top_name,
|
||||
std::string(BENCHMARK_INSTANCE_NAME),
|
||||
std::string(),
|
||||
std::string(),
|
||||
std::string(),
|
||||
prefix_to_remove,
|
||||
std::string(BENCHMARK_PORT_POSTFIX),
|
||||
std::vector<std::string>(),
|
||||
atom_ctx, netlist_annotation,
|
||||
pin_constraints,
|
||||
bus_group,
|
||||
explicit_port_mapping);
|
||||
|
||||
print_verilog_comment(fp, std::string("----- End reference Benchmark Instanication -------"));
|
||||
|
@ -149,29 +144,24 @@ void print_verilog_random_testbench_fpga_instance(std::fstream& fp,
|
|||
const AtomContext& atom_ctx,
|
||||
const VprNetlistAnnotation& netlist_annotation,
|
||||
const PinConstraints& pin_constraints,
|
||||
const BusGroup& bus_group,
|
||||
const bool& explicit_port_mapping) {
|
||||
/* Validate the file stream */
|
||||
valid_file_stream(fp);
|
||||
|
||||
print_verilog_comment(fp, std::string("----- FPGA fabric instanciation -------"));
|
||||
|
||||
/* VPR added a prefix of "out_" to the output ports of input benchmark */
|
||||
std::vector<std::string> prefix_to_remove;
|
||||
prefix_to_remove.push_back(std::string(VPR_BENCHMARK_OUT_PORT_PREFIX));
|
||||
prefix_to_remove.push_back(std::string(OPENFPGA_BENCHMARK_OUT_PORT_PREFIX));
|
||||
|
||||
|
||||
/* Always use explicit port mapping */
|
||||
print_verilog_testbench_benchmark_instance(fp, std::string(circuit_name + std::string(FORMAL_VERIFICATION_TOP_MODULE_POSTFIX)),
|
||||
std::string(FPGA_INSTANCE_NAME),
|
||||
std::string(),
|
||||
std::string(),
|
||||
std::string(),
|
||||
prefix_to_remove,
|
||||
std::string(FPGA_PORT_POSTFIX),
|
||||
std::vector<std::string>(),
|
||||
atom_ctx, netlist_annotation,
|
||||
pin_constraints,
|
||||
bus_group,
|
||||
explicit_port_mapping);
|
||||
|
||||
print_verilog_comment(fp, std::string("----- End FPGA Fabric Instanication -------"));
|
||||
|
@ -288,6 +278,7 @@ void print_verilog_random_top_testbench(const std::string& circuit_name,
|
|||
const ModuleManager& module_manager,
|
||||
const FabricGlobalPortInfo& global_ports,
|
||||
const PinConstraints& pin_constraints,
|
||||
const BusGroup& bus_group,
|
||||
const SimulationSetting& simulation_parameters,
|
||||
const VerilogTestbenchOption &options) {
|
||||
std::string timer_message = std::string("Write configuration-skip testbench for FPGA top-level Verilog netlist implemented by '") + circuit_name.c_str() + std::string("'");
|
||||
|
@ -316,6 +307,7 @@ void print_verilog_random_top_testbench(const std::string& circuit_name,
|
|||
print_verilog_random_testbench_fpga_instance(fp, circuit_name,
|
||||
atom_ctx, netlist_annotation,
|
||||
pin_constraints,
|
||||
bus_group,
|
||||
options.explicit_port_mapping());
|
||||
|
||||
/* Call defined benchmark */
|
||||
|
@ -323,6 +315,7 @@ void print_verilog_random_top_testbench(const std::string& circuit_name,
|
|||
print_verilog_top_random_testbench_benchmark_instance(fp, circuit_name,
|
||||
atom_ctx, netlist_annotation,
|
||||
pin_constraints,
|
||||
bus_group,
|
||||
options.explicit_port_mapping());
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "fabric_global_port_info.h"
|
||||
#include "simulation_setting.h"
|
||||
#include "verilog_testbench_options.h"
|
||||
#include "bus_group.h"
|
||||
|
||||
/********************************************************************
|
||||
* Function declaration
|
||||
|
@ -26,6 +27,7 @@ void print_verilog_random_top_testbench(const std::string& circuit_name,
|
|||
const ModuleManager& module_manager,
|
||||
const FabricGlobalPortInfo& global_ports,
|
||||
const PinConstraints& pin_constraints,
|
||||
const BusGroup& bus_group,
|
||||
const SimulationSetting& simulation_parameters,
|
||||
const VerilogTestbenchOption &options);
|
||||
|
||||
|
|
|
@ -38,7 +38,8 @@ static
|
|||
void print_verilog_preconfig_top_module_ports(std::fstream &fp,
|
||||
const std::string &circuit_name,
|
||||
const AtomContext &atom_ctx,
|
||||
const VprNetlistAnnotation &netlist_annotation) {
|
||||
const VprNetlistAnnotation &netlist_annotation,
|
||||
const BusGroup& bus_group) {
|
||||
|
||||
/* Validate the file stream */
|
||||
valid_file_stream(fp);
|
||||
|
@ -47,14 +48,15 @@ void print_verilog_preconfig_top_module_ports(std::fstream &fp,
|
|||
fp << "module " << circuit_name << std::string(FORMAL_VERIFICATION_TOP_MODULE_POSTFIX);
|
||||
fp << " (" << std::endl;
|
||||
|
||||
/* Add module ports */
|
||||
size_t port_counter = 0;
|
||||
|
||||
/* Port type-to-type mapping */
|
||||
std::map<AtomBlockType, enum e_dump_verilog_port_type> port_type2type_map;
|
||||
port_type2type_map[AtomBlockType::INPAD] = VERILOG_PORT_INPUT;
|
||||
port_type2type_map[AtomBlockType::OUTPAD] = VERILOG_PORT_OUTPUT;
|
||||
|
||||
/* Ports to be added, this is to avoid any bus port */
|
||||
std::vector<BasicPort> port_list;
|
||||
std::vector<AtomBlockType> port_types;
|
||||
|
||||
/* Print all the I/Os of the circuit implementation to be tested*/
|
||||
for (const AtomBlockId &atom_blk : atom_ctx.nlist.blocks()) {
|
||||
/* We only care I/O logical blocks !*/
|
||||
|
@ -62,8 +64,8 @@ void print_verilog_preconfig_top_module_ports(std::fstream &fp,
|
|||
continue;
|
||||
}
|
||||
|
||||
/* The block may be renamed as it contains special characters which violate Verilog syntax */
|
||||
std::string block_name = atom_ctx.nlist.block_name(atom_blk);
|
||||
/* The block may be renamed as it contains special characters which violate Verilog syntax */
|
||||
if (true == netlist_annotation.is_block_renamed(atom_blk)) {
|
||||
block_name = netlist_annotation.block_name(atom_blk);
|
||||
}
|
||||
|
@ -82,12 +84,38 @@ void print_verilog_preconfig_top_module_ports(std::fstream &fp,
|
|||
}
|
||||
}
|
||||
|
||||
/* If the pin is part of a bus,
|
||||
* - Check if the bus is already in the list
|
||||
* - If not, add it to the port list
|
||||
* - If yes, do nothing and move onto the next port
|
||||
* If the pin does not belong to any bus
|
||||
* - Add it to the bus port
|
||||
*/
|
||||
BusGroupId bus_id = bus_group.find_pin_bus(block_name);
|
||||
if (bus_id) {
|
||||
if (port_list.end() == std::find(port_list.begin(), port_list.end(), bus_group.bus_port(bus_id))) {
|
||||
port_list.push_back(bus_group.bus_port(bus_id));
|
||||
port_types.push_back(atom_ctx.nlist.block_type(atom_blk));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Both input and output ports have only size of 1 */
|
||||
BasicPort module_port(std::string(block_name), 1);
|
||||
port_list.push_back(module_port);
|
||||
port_types.push_back(atom_ctx.nlist.block_type(atom_blk));
|
||||
}
|
||||
|
||||
/* After collecting all the ports, now print the port mapping */
|
||||
size_t port_counter = 0;
|
||||
for (size_t iport = 0; iport < port_list.size(); ++iport) {
|
||||
BasicPort module_port = port_list[iport];
|
||||
AtomBlockType port_type = port_types[iport];
|
||||
if (0 < port_counter) {
|
||||
fp << "," << std::endl;
|
||||
}
|
||||
/* Both input and output ports have only size of 1 */
|
||||
BasicPort module_port(std::string(block_name), 1);
|
||||
fp << generate_verilog_port(port_type2type_map[atom_ctx.nlist.block_type(atom_blk)], module_port);
|
||||
|
||||
fp << generate_verilog_port(port_type2type_map[port_type], module_port);
|
||||
|
||||
/* Update port counter */
|
||||
port_counter++;
|
||||
|
@ -434,6 +462,7 @@ int print_verilog_preconfig_top_module(const ModuleManager &module_manager,
|
|||
const AtomContext &atom_ctx,
|
||||
const PlacementContext &place_ctx,
|
||||
const PinConstraints& pin_constraints,
|
||||
const BusGroup& bus_group,
|
||||
const IoLocationMap &io_location_map,
|
||||
const VprNetlistAnnotation &netlist_annotation,
|
||||
const std::string &circuit_name,
|
||||
|
@ -461,7 +490,7 @@ int print_verilog_preconfig_top_module(const ModuleManager &module_manager,
|
|||
options.default_net_type());
|
||||
|
||||
/* Print module declaration and ports */
|
||||
print_verilog_preconfig_top_module_ports(fp, circuit_name, atom_ctx, netlist_annotation);
|
||||
print_verilog_preconfig_top_module_ports(fp, circuit_name, atom_ctx, netlist_annotation, bus_group);
|
||||
|
||||
/* Find the top_module */
|
||||
ModuleId top_module = module_manager.find_module(generate_fpga_top_module_name());
|
||||
|
@ -488,16 +517,13 @@ int print_verilog_preconfig_top_module(const ModuleManager &module_manager,
|
|||
}
|
||||
|
||||
/* Connect I/Os to benchmark I/Os or constant driver */
|
||||
std::vector<std::string> prefix_to_remove;
|
||||
prefix_to_remove.push_back(std::string(VPR_BENCHMARK_OUT_PORT_PREFIX));
|
||||
prefix_to_remove.push_back(std::string(OPENFPGA_BENCHMARK_OUT_PORT_PREFIX));
|
||||
print_verilog_testbench_connect_fpga_ios(fp, module_manager, top_module,
|
||||
atom_ctx, place_ctx, io_location_map,
|
||||
netlist_annotation,
|
||||
bus_group,
|
||||
std::string(FORMAL_VERIFICATION_TOP_MODULE_PORT_POSTFIX),
|
||||
std::string(),
|
||||
std::string(),
|
||||
prefix_to_remove,
|
||||
std::vector<std::string>(),
|
||||
(size_t)VERILOG_DEFAULT_SIGNAL_INIT_VALUE);
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "io_location_map.h"
|
||||
#include "fabric_global_port_info.h"
|
||||
#include "config_protocol.h"
|
||||
#include "bus_group.h"
|
||||
#include "vpr_netlist_annotation.h"
|
||||
#include "verilog_testbench_options.h"
|
||||
|
||||
|
@ -32,6 +33,7 @@ int print_verilog_preconfig_top_module(const ModuleManager& module_manager,
|
|||
const AtomContext& atom_ctx,
|
||||
const PlacementContext& place_ctx,
|
||||
const PinConstraints& pin_constraints,
|
||||
const BusGroup& bus_group,
|
||||
const IoLocationMap& io_location_map,
|
||||
const VprNetlistAnnotation& netlist_annotation,
|
||||
const std::string& circuit_name,
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
#include "module_manager_utils.h"
|
||||
#include "fabric_global_port_info_utils.h"
|
||||
#include "openfpga_atom_netlist_utils.h"
|
||||
|
||||
#include "verilog_constants.h"
|
||||
#include "verilog_writer_utils.h"
|
||||
|
@ -79,19 +80,22 @@ void print_verilog_testbench_benchmark_instance(std::fstream& fp,
|
|||
const std::string& module_input_port_postfix,
|
||||
const std::string& module_output_port_postfix,
|
||||
const std::string& input_port_postfix,
|
||||
const std::vector<std::string>& output_port_prefix_to_remove,
|
||||
const std::string& output_port_postfix,
|
||||
const std::vector<std::string>& clock_port_names,
|
||||
const AtomContext& atom_ctx,
|
||||
const VprNetlistAnnotation& netlist_annotation,
|
||||
const PinConstraints& pin_constraints,
|
||||
const BusGroup& bus_group,
|
||||
const bool& use_explicit_port_map) {
|
||||
/* Validate the file stream */
|
||||
valid_file_stream(fp);
|
||||
|
||||
fp << "\t" << module_name << " " << instance_name << "(" << std::endl;
|
||||
|
||||
size_t port_counter = 0;
|
||||
/* Consider all the unique port names */
|
||||
std::vector<std::string> port_names;
|
||||
std::vector<AtomBlockType> port_types;
|
||||
|
||||
for (const AtomBlockId& atom_blk : atom_ctx.nlist.blocks()) {
|
||||
/* Bypass non-I/O atom blocks ! */
|
||||
if ( (AtomBlockType::INPAD != atom_ctx.nlist.block_type(atom_blk))
|
||||
|
@ -105,62 +109,129 @@ void print_verilog_testbench_benchmark_instance(std::fstream& fp,
|
|||
block_name = netlist_annotation.block_name(atom_blk);
|
||||
}
|
||||
|
||||
/* The first port does not need a comma */
|
||||
if(0 < port_counter){
|
||||
fp << "," << std::endl;
|
||||
}
|
||||
/* Input port follows the logical block name while output port requires a special postfix */
|
||||
if (AtomBlockType::INPAD == atom_ctx.nlist.block_type(atom_blk)) {
|
||||
fp << "\t\t";
|
||||
if (true == use_explicit_port_map) {
|
||||
fp << "." << block_name << module_input_port_postfix << "(";
|
||||
/* Note that VPR added a prefix "out_" or "out:" to the name of output blocks
|
||||
* We can remove this when specified through input argument
|
||||
*/
|
||||
if (AtomBlockType::OUTPAD == atom_ctx.nlist.block_type(atom_blk)) {
|
||||
block_name = remove_atom_block_name_prefix(block_name);
|
||||
}
|
||||
|
||||
/* If the pin is part of a bus,
|
||||
* - Check if the bus is already in the list
|
||||
* - If not, add it to the port list
|
||||
* - If yes, do nothing and move onto the next port
|
||||
* If the pin does not belong to any bus
|
||||
* - Add it to the bus port
|
||||
*/
|
||||
BusGroupId bus_id = bus_group.find_pin_bus(block_name);
|
||||
if (bus_id) {
|
||||
if (port_names.end() == std::find(port_names.begin(), port_names.end(), bus_group.bus_port(bus_id).get_name())) {
|
||||
port_names.push_back(bus_group.bus_port(bus_id).get_name());
|
||||
port_types.push_back(atom_ctx.nlist.block_type(atom_blk));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Input port follows the logical block name while output port requires a special postfix */
|
||||
port_names.push_back(block_name);
|
||||
port_types.push_back(atom_ctx.nlist.block_type(atom_blk));
|
||||
}
|
||||
|
||||
/* Print out the instance with port mapping */
|
||||
size_t port_counter = 0;
|
||||
for (size_t iport = 0; iport < port_names.size(); ++iport) {
|
||||
/* The first port does not need a comma */
|
||||
if (0 < port_counter){
|
||||
fp << "," << std::endl;
|
||||
}
|
||||
|
||||
fp << "\t\t";
|
||||
if (AtomBlockType::INPAD == port_types[iport]) {
|
||||
if (true == use_explicit_port_map) {
|
||||
fp << "." << port_names[iport] << module_input_port_postfix << "(";
|
||||
}
|
||||
|
||||
/* For bus ports, include a complete list of pins */
|
||||
BusGroupId bus_id = bus_group.find_bus(port_names[iport]);
|
||||
if (bus_id) {
|
||||
fp << "{";
|
||||
int pin_counter = 0;
|
||||
/* Include all the pins */
|
||||
for (const BusPinId& pin : bus_group.bus_pins(bus_id)) {
|
||||
if (0 < pin_counter) {
|
||||
fp << ", ";
|
||||
}
|
||||
/* Polarity of some input may have to be inverted, as defined in pin constraints
|
||||
* For example, the reset signal of the benchmark is active low
|
||||
* while the reset signal of the FPGA fabric is active high (inside FPGA, the reset signal will be inverted)
|
||||
* However, to ensure correct stimuli to the benchmark, we have to invert the signal
|
||||
*/
|
||||
if (PinConstraints::LOGIC_HIGH == pin_constraints.net_default_value(block_name)) {
|
||||
if (PinConstraints::LOGIC_HIGH == pin_constraints.net_default_value(bus_group.pin_name(pin))) {
|
||||
fp << "~";
|
||||
}
|
||||
|
||||
fp << bus_group.pin_name(pin);
|
||||
|
||||
/* For clock ports, skip postfix */
|
||||
if (clock_port_names.end() != std::find(clock_port_names.begin(), clock_port_names.end(), block_name)) {
|
||||
fp << block_name;
|
||||
} else {
|
||||
fp << block_name << input_port_postfix;
|
||||
if (clock_port_names.end() == std::find(clock_port_names.begin(), clock_port_names.end(), port_names[iport])) {
|
||||
fp << input_port_postfix;
|
||||
}
|
||||
if (true == use_explicit_port_map) {
|
||||
fp << ")";
|
||||
|
||||
pin_counter++;
|
||||
}
|
||||
fp << "}";
|
||||
} else {
|
||||
VTR_ASSERT_SAFE(AtomBlockType::OUTPAD == atom_ctx.nlist.block_type(atom_blk));
|
||||
fp << "\t\t";
|
||||
/* Note that VPR added a prefix "out_" or "out:" to the name of output blocks
|
||||
* We can remove this when specified through input argument
|
||||
/* Polarity of some input may have to be inverted, as defined in pin constraints
|
||||
* For example, the reset signal of the benchmark is active low
|
||||
* while the reset signal of the FPGA fabric is active high (inside FPGA, the reset signal will be inverted)
|
||||
* However, to ensure correct stimuli to the benchmark, we have to invert the signal
|
||||
*/
|
||||
std::string output_block_name = block_name;
|
||||
for (const std::string& prefix_to_remove : output_port_prefix_to_remove) {
|
||||
if (!prefix_to_remove.empty()) {
|
||||
if (0 == output_block_name.find(prefix_to_remove)) {
|
||||
output_block_name.erase(0, prefix_to_remove.length());
|
||||
break;
|
||||
if (PinConstraints::LOGIC_HIGH == pin_constraints.net_default_value(port_names[iport])) {
|
||||
fp << "~";
|
||||
}
|
||||
|
||||
fp << port_names[iport];
|
||||
/* For clock ports, skip postfix */
|
||||
if (clock_port_names.end() == std::find(clock_port_names.begin(), clock_port_names.end(), port_names[iport])) {
|
||||
fp << input_port_postfix;
|
||||
}
|
||||
}
|
||||
|
||||
if (true == use_explicit_port_map) {
|
||||
fp << "." << output_block_name << module_output_port_postfix << "(";
|
||||
fp << ")";
|
||||
}
|
||||
} else {
|
||||
VTR_ASSERT_SAFE(AtomBlockType::OUTPAD == port_types[iport]);
|
||||
if (true == use_explicit_port_map) {
|
||||
fp << "." << port_names[iport] << module_output_port_postfix << "(";
|
||||
}
|
||||
|
||||
/* For bus ports, include a complete list of pins */
|
||||
BusGroupId bus_id = bus_group.find_bus(port_names[iport]);
|
||||
if (bus_id) {
|
||||
fp << "{";
|
||||
int pin_counter = 0;
|
||||
/* Include all the pins */
|
||||
for (const BusPinId& pin : bus_group.bus_pins(bus_id)) {
|
||||
if (0 < pin_counter) {
|
||||
fp << ", ";
|
||||
}
|
||||
fp << bus_group.pin_name(pin) << output_port_postfix;
|
||||
pin_counter++;
|
||||
}
|
||||
fp << "}";
|
||||
} else {
|
||||
fp << port_names[iport] << output_port_postfix;
|
||||
}
|
||||
fp << block_name << output_port_postfix;
|
||||
if (true == use_explicit_port_map) {
|
||||
fp << ")";
|
||||
}
|
||||
}
|
||||
|
||||
/* Update the counter */
|
||||
port_counter++;
|
||||
}
|
||||
fp << "\t);" << std::endl;
|
||||
fp << "\n\t);" << std::endl;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
|
@ -177,10 +248,10 @@ void print_verilog_testbench_connect_fpga_ios(std::fstream& fp,
|
|||
const PlacementContext& place_ctx,
|
||||
const IoLocationMap& io_location_map,
|
||||
const VprNetlistAnnotation& netlist_annotation,
|
||||
const BusGroup& bus_group,
|
||||
const std::string& net_name_postfix,
|
||||
const std::string& io_input_port_name_postfix,
|
||||
const std::string& io_output_port_name_postfix,
|
||||
const std::vector<std::string>& output_port_prefix_to_remove,
|
||||
const std::vector<std::string>& clock_port_names,
|
||||
const size_t& unused_io_value) {
|
||||
/* Validate the file stream */
|
||||
|
@ -276,13 +347,8 @@ void print_verilog_testbench_connect_fpga_ios(std::fstream& fp,
|
|||
/* Note that VPR added a prefix to the name of output blocks
|
||||
* We can remove this when specified through input argument
|
||||
*/
|
||||
for (const std::string& prefix_to_remove : output_port_prefix_to_remove) {
|
||||
if (!prefix_to_remove.empty()) {
|
||||
if (0 == block_name.find(prefix_to_remove)) {
|
||||
block_name.erase(0, prefix_to_remove.length());
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (AtomBlockType::OUTPAD == atom_ctx.nlist.block_type(atom_blk)) {
|
||||
block_name = remove_atom_block_name_prefix(block_name);
|
||||
}
|
||||
|
||||
/* Create the port for benchmark I/O, due to BLIF benchmark, each I/O always has a size of 1
|
||||
|
@ -290,6 +356,18 @@ void print_verilog_testbench_connect_fpga_ios(std::fstream& fp,
|
|||
* due to verification context! Here, we give full customization on naming
|
||||
*/
|
||||
BasicPort benchmark_io_port;
|
||||
|
||||
/* If this benchmark pin belongs to any bus group, use the bus pin instead */
|
||||
BusGroupId bus_id = bus_group.find_pin_bus(block_name);
|
||||
BusPinId bus_pin_id = bus_group.find_pin(block_name);
|
||||
if (bus_id) {
|
||||
block_name = bus_group.bus_port(bus_id).get_name();
|
||||
VTR_ASSERT_SAFE(bus_pin_id);
|
||||
benchmark_io_port.set_width(bus_group.pin_index(bus_pin_id), bus_group.pin_index(bus_pin_id));
|
||||
} else {
|
||||
benchmark_io_port.set_width(1);
|
||||
}
|
||||
|
||||
if (AtomBlockType::INPAD == atom_ctx.nlist.block_type(atom_blk)) {
|
||||
/* If the port is a clock, do not add a postfix */
|
||||
if (clock_port_names.end() != std::find(clock_port_names.begin(), clock_port_names.end(), block_name)) {
|
||||
|
@ -297,13 +375,11 @@ void print_verilog_testbench_connect_fpga_ios(std::fstream& fp,
|
|||
} else {
|
||||
benchmark_io_port.set_name(std::string(block_name + io_input_port_name_postfix));
|
||||
}
|
||||
benchmark_io_port.set_width(1);
|
||||
print_verilog_comment(fp, std::string("----- Blif Benchmark input " + block_name + " is mapped to FPGA IOPAD " + module_mapped_io_port.get_name() + "[" + std::to_string(io_index) + "] -----"));
|
||||
print_verilog_wire_connection(fp, module_mapped_io_port, benchmark_io_port, false);
|
||||
} else {
|
||||
VTR_ASSERT(AtomBlockType::OUTPAD == atom_ctx.nlist.block_type(atom_blk));
|
||||
benchmark_io_port.set_name(std::string(block_name + io_output_port_name_postfix));
|
||||
benchmark_io_port.set_width(1);
|
||||
print_verilog_comment(fp, std::string("----- Blif Benchmark output " + block_name + " is mapped to FPGA IOPAD " + module_mapped_io_port.get_name() + "[" + std::to_string(io_index) + "] -----"));
|
||||
print_verilog_wire_connection(fp, benchmark_io_port, module_mapped_io_port, false);
|
||||
}
|
||||
|
@ -487,6 +563,7 @@ void print_verilog_testbench_check(std::fstream& fp,
|
|||
}
|
||||
|
||||
if (AtomBlockType::OUTPAD == atom_ctx.nlist.block_type(atom_blk)) {
|
||||
block_name = remove_atom_block_name_prefix(block_name);
|
||||
fp << "\t\t\tif(!(" << block_name << fpga_port_postfix;
|
||||
fp << " === " << block_name << benchmark_port_postfix;
|
||||
fp << ") && !(" << block_name << benchmark_port_postfix;
|
||||
|
@ -514,6 +591,7 @@ void print_verilog_testbench_check(std::fstream& fp,
|
|||
if (true == netlist_annotation.is_block_renamed(atom_blk)) {
|
||||
block_name = netlist_annotation.block_name(atom_blk);
|
||||
}
|
||||
block_name = remove_atom_block_name_prefix(block_name);
|
||||
|
||||
fp << "\talways@(posedge " << block_name << check_flag_port_postfix << ") begin" << std::endl;
|
||||
fp << "\t\tif(" << block_name << check_flag_port_postfix << ") begin" << std::endl;
|
||||
|
@ -621,6 +699,9 @@ void print_verilog_testbench_random_stimuli(std::fstream& fp,
|
|||
if (true == netlist_annotation.is_block_renamed(atom_blk)) {
|
||||
block_name = netlist_annotation.block_name(atom_blk);
|
||||
}
|
||||
if (AtomBlockType::OUTPAD == atom_ctx.nlist.block_type(atom_blk)) {
|
||||
block_name = remove_atom_block_name_prefix(block_name);
|
||||
}
|
||||
|
||||
/* Bypass clock ports because their stimulus cannot be random */
|
||||
if (clock_port_names.end() != std::find(clock_port_names.begin(), clock_port_names.end(), block_name)) {
|
||||
|
@ -656,6 +737,7 @@ void print_verilog_testbench_random_stimuli(std::fstream& fp,
|
|||
if (true == netlist_annotation.is_block_renamed(atom_blk)) {
|
||||
block_name = netlist_annotation.block_name(atom_blk);
|
||||
}
|
||||
block_name = remove_atom_block_name_prefix(block_name);
|
||||
|
||||
/* Each logical block assumes a single-width port */
|
||||
BasicPort output_port(std::string(block_name + check_flag_port_postfix), 1);
|
||||
|
@ -690,6 +772,9 @@ void print_verilog_testbench_random_stimuli(std::fstream& fp,
|
|||
if (true == netlist_annotation.is_block_renamed(atom_blk)) {
|
||||
block_name = netlist_annotation.block_name(atom_blk);
|
||||
}
|
||||
if (AtomBlockType::OUTPAD == atom_ctx.nlist.block_type(atom_blk)) {
|
||||
block_name = remove_atom_block_name_prefix(block_name);
|
||||
}
|
||||
|
||||
/* Bypass clock ports because their stimulus cannot be random */
|
||||
if (clock_port_names.end() != std::find(clock_port_names.begin(), clock_port_names.end(), block_name)) {
|
||||
|
@ -785,6 +870,7 @@ void print_verilog_testbench_shared_ports(std::fstream& fp,
|
|||
if (true == netlist_annotation.is_block_renamed(atom_blk)) {
|
||||
block_name = netlist_annotation.block_name(atom_blk);
|
||||
}
|
||||
block_name = remove_atom_block_name_prefix(block_name);
|
||||
|
||||
/* Each logical block assumes a single-width port */
|
||||
BasicPort output_port(std::string(block_name + fpga_output_port_postfix), 1);
|
||||
|
@ -811,6 +897,7 @@ void print_verilog_testbench_shared_ports(std::fstream& fp,
|
|||
if (true == netlist_annotation.is_block_renamed(atom_blk)) {
|
||||
block_name = netlist_annotation.block_name(atom_blk);
|
||||
}
|
||||
block_name = remove_atom_block_name_prefix(block_name);
|
||||
|
||||
/* Each logical block assumes a single-width port */
|
||||
BasicPort output_port(std::string(block_name + benchmark_output_port_postfix), 1);
|
||||
|
@ -833,6 +920,7 @@ void print_verilog_testbench_shared_ports(std::fstream& fp,
|
|||
if (true == netlist_annotation.is_block_renamed(atom_blk)) {
|
||||
block_name = netlist_annotation.block_name(atom_blk);
|
||||
}
|
||||
block_name = remove_atom_block_name_prefix(block_name);
|
||||
|
||||
/* Each logical block assumes a single-width port */
|
||||
BasicPort output_port(std::string(block_name + check_flag_port_postfix), 1);
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "simulation_setting.h"
|
||||
#include "fabric_global_port_info.h"
|
||||
#include "pin_constraints.h"
|
||||
#include "bus_group.h"
|
||||
|
||||
/********************************************************************
|
||||
* Function declaration
|
||||
|
@ -38,12 +39,12 @@ void print_verilog_testbench_benchmark_instance(std::fstream& fp,
|
|||
const std::string& module_input_port_postfix,
|
||||
const std::string& module_output_port_postfix,
|
||||
const std::string& input_port_postfix,
|
||||
const std::vector<std::string>& output_port_prefix_to_remove,
|
||||
const std::string& output_port_postfix,
|
||||
const std::vector<std::string>& clock_port_names,
|
||||
const AtomContext& atom_ctx,
|
||||
const VprNetlistAnnotation& netlist_annotation,
|
||||
const PinConstraints& pin_constraints,
|
||||
const BusGroup& bus_group,
|
||||
const bool& use_explicit_port_map);
|
||||
|
||||
void print_verilog_testbench_connect_fpga_ios(std::fstream& fp,
|
||||
|
@ -53,10 +54,10 @@ void print_verilog_testbench_connect_fpga_ios(std::fstream& fp,
|
|||
const PlacementContext& place_ctx,
|
||||
const IoLocationMap& io_location_map,
|
||||
const VprNetlistAnnotation& netlist_annotation,
|
||||
const BusGroup& bus_group,
|
||||
const std::string& net_name_postfix,
|
||||
const std::string& io_input_port_name_postfix,
|
||||
const std::string& io_output_port_name_postfix,
|
||||
const std::vector<std::string>& output_port_prefix_to_remove,
|
||||
const std::vector<std::string>& clock_port_names,
|
||||
const size_t& unused_io_value);
|
||||
|
||||
|
|
|
@ -937,6 +937,7 @@ void print_verilog_top_testbench_benchmark_instance(std::fstream& fp,
|
|||
const AtomContext& atom_ctx,
|
||||
const VprNetlistAnnotation& netlist_annotation,
|
||||
const PinConstraints& pin_constraints,
|
||||
const BusGroup& bus_group,
|
||||
const std::vector<std::string>& clock_port_names,
|
||||
const bool& explicit_port_mapping) {
|
||||
/* Validate the file stream */
|
||||
|
@ -945,22 +946,16 @@ void print_verilog_top_testbench_benchmark_instance(std::fstream& fp,
|
|||
/* Instanciate benchmark */
|
||||
print_verilog_comment(fp, std::string("----- Reference Benchmark Instanication -------"));
|
||||
|
||||
/* Do NOT use explicit port mapping here:
|
||||
* VPR added a prefix of "out_" to the output ports of input benchmark
|
||||
*/
|
||||
std::vector<std::string> prefix_to_remove;
|
||||
prefix_to_remove.push_back(std::string(VPR_BENCHMARK_OUT_PORT_PREFIX));
|
||||
prefix_to_remove.push_back(std::string(OPENFPGA_BENCHMARK_OUT_PORT_PREFIX));
|
||||
print_verilog_testbench_benchmark_instance(fp, reference_verilog_top_name,
|
||||
std::string(TOP_TESTBENCH_REFERENCE_INSTANCE_NAME),
|
||||
std::string(),
|
||||
std::string(),
|
||||
std::string(TOP_TESTBENCH_SHARED_INPUT_POSTFIX),
|
||||
prefix_to_remove,
|
||||
std::string(TOP_TESTBENCH_REFERENCE_OUTPUT_POSTFIX),
|
||||
clock_port_names,
|
||||
atom_ctx, netlist_annotation,
|
||||
pin_constraints,
|
||||
bus_group,
|
||||
explicit_port_mapping);
|
||||
|
||||
print_verilog_comment(fp, std::string("----- End reference Benchmark Instanication -------"));
|
||||
|
@ -1924,6 +1919,7 @@ int print_verilog_full_testbench(const ModuleManager& module_manager,
|
|||
const AtomContext& atom_ctx,
|
||||
const PlacementContext& place_ctx,
|
||||
const PinConstraints& pin_constraints,
|
||||
const BusGroup& bus_group,
|
||||
const std::string& bitstream_file,
|
||||
const IoLocationMap& io_location_map,
|
||||
const VprNetlistAnnotation& netlist_annotation,
|
||||
|
@ -2064,10 +2060,10 @@ int print_verilog_full_testbench(const ModuleManager& module_manager,
|
|||
print_verilog_testbench_connect_fpga_ios(fp, module_manager, top_module,
|
||||
atom_ctx, place_ctx, io_location_map,
|
||||
netlist_annotation,
|
||||
BusGroup(),
|
||||
std::string(),
|
||||
std::string(TOP_TESTBENCH_SHARED_INPUT_POSTFIX),
|
||||
std::string(TOP_TESTBENCH_FPGA_OUTPUT_POSTFIX),
|
||||
std::vector<std::string>(),
|
||||
clock_port_names,
|
||||
(size_t)VERILOG_DEFAULT_SIGNAL_INIT_VALUE);
|
||||
|
||||
|
@ -2078,6 +2074,7 @@ int print_verilog_full_testbench(const ModuleManager& module_manager,
|
|||
atom_ctx,
|
||||
netlist_annotation,
|
||||
pin_constraints,
|
||||
bus_group,
|
||||
clock_port_names,
|
||||
explicit_port_mapping);
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "simulation_setting.h"
|
||||
#include "memory_bank_shift_register_banks.h"
|
||||
#include "verilog_testbench_options.h"
|
||||
#include "bus_group.h"
|
||||
|
||||
/********************************************************************
|
||||
* Function declaration
|
||||
|
@ -37,6 +38,7 @@ int print_verilog_full_testbench(const ModuleManager& module_manager,
|
|||
const AtomContext& atom_ctx,
|
||||
const PlacementContext& place_ctx,
|
||||
const PinConstraints& pin_constraints,
|
||||
const BusGroup& bus_group,
|
||||
const std::string& bitstream_file,
|
||||
const IoLocationMap& io_location_map,
|
||||
const VprNetlistAnnotation& netlist_annotation,
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
/* Headers from vtrutil library */
|
||||
#include "atom_netlist_utils.h"
|
||||
|
||||
#include "openfpga_reserved_words.h"
|
||||
#include "openfpga_atom_netlist_utils.h"
|
||||
|
||||
/* begin namespace openfpga */
|
||||
|
@ -38,4 +39,27 @@ std::vector<std::string> find_atom_netlist_clock_port_names(const AtomNetlist& a
|
|||
return clock_names;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Remove the prefix that is added to the name of a output block (by VPR)
|
||||
*******************************************************************/
|
||||
std::string remove_atom_block_name_prefix(const std::string& block_name) {
|
||||
/* VPR added a prefix of "out_" to the output ports of input benchmark */
|
||||
std::vector<std::string> prefix_to_remove;
|
||||
prefix_to_remove.push_back(std::string(VPR_BENCHMARK_OUT_PORT_PREFIX));
|
||||
prefix_to_remove.push_back(std::string(OPENFPGA_BENCHMARK_OUT_PORT_PREFIX));
|
||||
|
||||
std::string ret_block_name = block_name;
|
||||
|
||||
for (const std::string& cur_prefix_to_remove : prefix_to_remove) {
|
||||
if (!cur_prefix_to_remove.empty()) {
|
||||
if (0 == ret_block_name.find(cur_prefix_to_remove)) {
|
||||
ret_block_name.erase(0, cur_prefix_to_remove.length());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret_block_name;
|
||||
}
|
||||
|
||||
} /* end namespace openfpga */
|
||||
|
|
|
@ -19,6 +19,8 @@ namespace openfpga {
|
|||
std::vector<std::string> find_atom_netlist_clock_port_names(const AtomNetlist& atom_nlist,
|
||||
const VprNetlistAnnotation& netlist_annotation);
|
||||
|
||||
std::string remove_atom_block_name_prefix(const std::string& block_name);
|
||||
|
||||
} /* end namespace openfpga */
|
||||
|
||||
#endif
|
||||
|
|
|
@ -39,3 +39,4 @@ synth -run check
|
|||
# Clean and output blif
|
||||
opt_clean -purge
|
||||
write_blif rewritten_${OUTPUT_BLIF}
|
||||
write_verilog ${OUTPUT_VERILOG}
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
# Run VPR for the 'and' design
|
||||
#--write_rr_graph example_rr_graph.xml
|
||||
vpr ${VPR_ARCH_FILE} ${VPR_TESTBENCH_BLIF} --clock_modeling ideal
|
||||
|
||||
# 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 --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 clustering nets based on routing results
|
||||
pb_pin_fixup --verbose
|
||||
|
||||
# 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
|
||||
|
||||
# Build fabric-dependent bitstream
|
||||
build_fabric_bitstream --verbose
|
||||
|
||||
# Write fabric-dependent bitstream
|
||||
write_fabric_bitstream --file fabric_bitstream.bit --format plain_text
|
||||
|
||||
# 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 --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} ${OPENFPGA_VERILOG_PORT_MAPPING} --include_signal_init --bitstream fabric_bitstream.bit --pin_constraints_file ${OPENFPGA_PIN_CONSTRAINTS_FILE} --bus_group_file ${OPENFPGA_BUS_GROUP_FILE}
|
||||
|
||||
# Finish and exit OpenFPGA
|
||||
exit
|
||||
|
||||
# Note :
|
||||
# To run verification at the end of the flow maintain source in ./SRC directory
|
|
@ -0,0 +1,65 @@
|
|||
# Run VPR for the 'and' design
|
||||
#--write_rr_graph example_rr_graph.xml
|
||||
vpr ${VPR_ARCH_FILE} ${VPR_TESTBENCH_BLIF} --clock_modeling ideal
|
||||
|
||||
# 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 --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 clustering nets based on routing results
|
||||
pb_pin_fixup --verbose
|
||||
|
||||
# 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
|
||||
|
||||
# Build fabric-dependent bitstream
|
||||
build_fabric_bitstream --verbose
|
||||
|
||||
# Write fabric-dependent bitstream
|
||||
write_fabric_bitstream --file fabric_bitstream.bit --format plain_text
|
||||
|
||||
# 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 --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_preconfigured_fabric_wrapper --embed_bitstream iverilog --file ./SRC ${OPENFPGA_VERILOG_PORT_MAPPING} --pin_constraints_file ${OPENFPGA_PIN_CONSTRAINTS_FILE} --bus_group_file ${OPENFPGA_BUS_GROUP_FILE}
|
||||
write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} ${OPENFPGA_VERILOG_PORT_MAPPING} --pin_constraints_file ${OPENFPGA_PIN_CONSTRAINTS_FILE} --bus_group_file ${OPENFPGA_BUS_GROUP_FILE}
|
||||
|
||||
# Finish and exit OpenFPGA
|
||||
exit
|
||||
|
||||
# Note :
|
||||
# To run verification at the end of the flow maintain source in ./SRC directory
|
|
@ -166,3 +166,9 @@ run-task basic_tests/write_gsb/write_gsb_to_xml --debug --show_thread_logs
|
|||
run-task basic_tests/write_gsb/write_gsb_to_xml_compress_routing --debug --show_thread_logs
|
||||
run-task basic_tests/write_gsb/write_unique_gsb_to_xml --debug --show_thread_logs
|
||||
run-task basic_tests/write_gsb/write_unique_gsb_to_xml_compress_routing --debug --show_thread_logs
|
||||
|
||||
echo -e "Testing bus group features";
|
||||
run-task basic_tests/bus_group/preconfig_testbench_explicit_mapping --debug --show_thread_logs
|
||||
run-task basic_tests/bus_group/preconfig_testbench_implicit_mapping --debug --show_thread_logs
|
||||
run-task basic_tests/bus_group/full_testbench_explicit_mapping --debug --show_thread_logs
|
||||
run-task basic_tests/bus_group/full_testbench_implicit_mapping --debug --show_thread_logs
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
<bus_group>
|
||||
<bus name="result[0:7]">
|
||||
<pin id="0" name="result_7_"/>
|
||||
<pin id="1" name="result_6_"/>
|
||||
<pin id="2" name="result_5_"/>
|
||||
<pin id="3" name="result_4_"/>
|
||||
<pin id="4" name="result_3_"/>
|
||||
<pin id="5" name="result_2_"/>
|
||||
<pin id="6" name="result_1_"/>
|
||||
<pin id="7" name="result_0_"/>
|
||||
</bus>
|
||||
</bus_group>
|
|
@ -0,0 +1,7 @@
|
|||
<pin_constraints>
|
||||
<!-- For a given .blif file, we want to assign
|
||||
- the reset signal to the op_reset[0] port of the FPGA fabric
|
||||
-->
|
||||
<set_io pin="op_reset[0]" net="reset"/>
|
||||
</pin_constraints>
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
|
||||
# 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=yosys_vpr
|
||||
|
||||
[OpenFPGA_SHELL]
|
||||
openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/full_testbench_bus_group_example_script.openfpga
|
||||
openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_dpram8K_dsp36_fracff_40nm_openfpga.xml
|
||||
openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/fixed_sim_openfpga.xml
|
||||
openfpga_verilog_port_mapping=--explicit_port_mapping
|
||||
openfpga_bus_group_file=${PATH:TASK_DIR}/config/counter8_bus_group.xml
|
||||
|
||||
[ARCHITECTURES]
|
||||
arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_fracff_40nm.xml
|
||||
|
||||
[BENCHMARKS]
|
||||
bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/counters/counter_8bit_async_reset/counter.v
|
||||
|
||||
[SYNTHESIS_PARAM]
|
||||
# Yosys script parameters
|
||||
bench_yosys_cell_sim_verilog_common=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_fracff_40nm_cell_sim.v
|
||||
bench_yosys_dff_map_verilog_common=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_fracff_40nm_dff_map.v
|
||||
bench_yosys_bram_map_rules_common=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_40nm_bram.txt
|
||||
bench_yosys_bram_map_verilog_common=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_40nm_bram_map.v
|
||||
bench_yosys_dsp_map_verilog_common=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_40nm_dsp_map.v
|
||||
bench_yosys_dsp_map_parameters_common=-D DSP_A_MAXWIDTH=36 -D DSP_B_MAXWIDTH=36 -D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 -D DSP_NAME=mult_36x36
|
||||
bench_read_verilog_options_common = -nolatches
|
||||
bench_yosys_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_dff_flow.ys
|
||||
bench_yosys_rewrite_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_flow_with_rewrite.ys
|
||||
|
||||
bench0_top = counter
|
||||
bench0_openfpga_pin_constraints_file=${PATH:TASK_DIR}/config/pin_constraints_reset.xml
|
||||
|
||||
[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH]
|
||||
end_flow_with_test=
|
|
@ -0,0 +1,12 @@
|
|||
<bus_group>
|
||||
<bus name="result[0:7]">
|
||||
<pin id="0" name="result_7_"/>
|
||||
<pin id="1" name="result_6_"/>
|
||||
<pin id="2" name="result_5_"/>
|
||||
<pin id="3" name="result_4_"/>
|
||||
<pin id="4" name="result_3_"/>
|
||||
<pin id="5" name="result_2_"/>
|
||||
<pin id="6" name="result_1_"/>
|
||||
<pin id="7" name="result_0_"/>
|
||||
</bus>
|
||||
</bus_group>
|
|
@ -0,0 +1,7 @@
|
|||
<pin_constraints>
|
||||
<!-- For a given .blif file, we want to assign
|
||||
- the reset signal to the op_reset[0] port of the FPGA fabric
|
||||
-->
|
||||
<set_io pin="op_reset[0]" net="reset"/>
|
||||
</pin_constraints>
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
|
||||
# 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=yosys_vpr
|
||||
|
||||
[OpenFPGA_SHELL]
|
||||
openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/full_testbench_bus_group_example_script.openfpga
|
||||
openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_dpram8K_dsp36_fracff_40nm_openfpga.xml
|
||||
openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/fixed_sim_openfpga.xml
|
||||
openfpga_verilog_port_mapping=
|
||||
openfpga_bus_group_file=${PATH:TASK_DIR}/config/counter8_bus_group.xml
|
||||
|
||||
[ARCHITECTURES]
|
||||
arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_fracff_40nm.xml
|
||||
|
||||
[BENCHMARKS]
|
||||
bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/counters/counter_8bit_async_reset/counter.v
|
||||
|
||||
[SYNTHESIS_PARAM]
|
||||
# Yosys script parameters
|
||||
bench_yosys_cell_sim_verilog_common=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_fracff_40nm_cell_sim.v
|
||||
bench_yosys_dff_map_verilog_common=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_fracff_40nm_dff_map.v
|
||||
bench_yosys_bram_map_rules_common=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_40nm_bram.txt
|
||||
bench_yosys_bram_map_verilog_common=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_40nm_bram_map.v
|
||||
bench_yosys_dsp_map_verilog_common=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_40nm_dsp_map.v
|
||||
bench_yosys_dsp_map_parameters_common=-D DSP_A_MAXWIDTH=36 -D DSP_B_MAXWIDTH=36 -D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 -D DSP_NAME=mult_36x36
|
||||
bench_read_verilog_options_common = -nolatches
|
||||
bench_yosys_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_dff_flow.ys
|
||||
bench_yosys_rewrite_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_flow_with_rewrite.ys
|
||||
|
||||
bench0_top = counter
|
||||
bench0_openfpga_pin_constraints_file=${PATH:TASK_DIR}/config/pin_constraints_reset.xml
|
||||
|
||||
[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH]
|
||||
end_flow_with_test=
|
|
@ -0,0 +1,12 @@
|
|||
<bus_group>
|
||||
<bus name="result[0:7]">
|
||||
<pin id="0" name="result_7_"/>
|
||||
<pin id="1" name="result_6_"/>
|
||||
<pin id="2" name="result_5_"/>
|
||||
<pin id="3" name="result_4_"/>
|
||||
<pin id="4" name="result_3_"/>
|
||||
<pin id="5" name="result_2_"/>
|
||||
<pin id="6" name="result_1_"/>
|
||||
<pin id="7" name="result_0_"/>
|
||||
</bus>
|
||||
</bus_group>
|
|
@ -0,0 +1,7 @@
|
|||
<pin_constraints>
|
||||
<!-- For a given .blif file, we want to assign
|
||||
- the reset signal to the op_reset[0] port of the FPGA fabric
|
||||
-->
|
||||
<set_io pin="op_reset[0]" net="reset"/>
|
||||
</pin_constraints>
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
|
||||
# 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=yosys_vpr
|
||||
|
||||
[OpenFPGA_SHELL]
|
||||
openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/preconfigured_testbench_bus_group_example_script.openfpga
|
||||
openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_dpram8K_dsp36_fracff_40nm_openfpga.xml
|
||||
openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/fixed_sim_openfpga.xml
|
||||
openfpga_verilog_port_mapping=--explicit_port_mapping
|
||||
openfpga_bus_group_file=${PATH:TASK_DIR}/config/counter8_bus_group.xml
|
||||
|
||||
[ARCHITECTURES]
|
||||
arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_fracff_40nm.xml
|
||||
|
||||
[BENCHMARKS]
|
||||
bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/counters/counter_8bit_async_reset/counter.v
|
||||
|
||||
[SYNTHESIS_PARAM]
|
||||
# Yosys script parameters
|
||||
bench_yosys_cell_sim_verilog_common=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_fracff_40nm_cell_sim.v
|
||||
bench_yosys_dff_map_verilog_common=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_fracff_40nm_dff_map.v
|
||||
bench_yosys_bram_map_rules_common=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_40nm_bram.txt
|
||||
bench_yosys_bram_map_verilog_common=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_40nm_bram_map.v
|
||||
bench_yosys_dsp_map_verilog_common=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_40nm_dsp_map.v
|
||||
bench_yosys_dsp_map_parameters_common=-D DSP_A_MAXWIDTH=36 -D DSP_B_MAXWIDTH=36 -D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 -D DSP_NAME=mult_36x36
|
||||
bench_read_verilog_options_common = -nolatches
|
||||
bench_yosys_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_dff_flow.ys
|
||||
bench_yosys_rewrite_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_flow_with_rewrite.ys
|
||||
|
||||
bench0_top = counter
|
||||
bench0_openfpga_pin_constraints_file=${PATH:TASK_DIR}/config/pin_constraints_reset.xml
|
||||
|
||||
[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH]
|
||||
end_flow_with_test=
|
||||
vpr_fpga_verilog_formal_verification_top_netlist=
|
|
@ -0,0 +1,12 @@
|
|||
<bus_group>
|
||||
<bus name="result[0:7]">
|
||||
<pin id="0" name="result_7_"/>
|
||||
<pin id="1" name="result_6_"/>
|
||||
<pin id="2" name="result_5_"/>
|
||||
<pin id="3" name="result_4_"/>
|
||||
<pin id="4" name="result_3_"/>
|
||||
<pin id="5" name="result_2_"/>
|
||||
<pin id="6" name="result_1_"/>
|
||||
<pin id="7" name="result_0_"/>
|
||||
</bus>
|
||||
</bus_group>
|
|
@ -0,0 +1,7 @@
|
|||
<pin_constraints>
|
||||
<!-- For a given .blif file, we want to assign
|
||||
- the reset signal to the op_reset[0] port of the FPGA fabric
|
||||
-->
|
||||
<set_io pin="op_reset[0]" net="reset"/>
|
||||
</pin_constraints>
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
|
||||
# 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=yosys_vpr
|
||||
|
||||
[OpenFPGA_SHELL]
|
||||
openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/preconfigured_testbench_bus_group_example_script.openfpga
|
||||
openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_dpram8K_dsp36_fracff_40nm_openfpga.xml
|
||||
openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/fixed_sim_openfpga.xml
|
||||
openfpga_verilog_port_mapping=
|
||||
openfpga_bus_group_file=${PATH:TASK_DIR}/config/counter8_bus_group.xml
|
||||
|
||||
[ARCHITECTURES]
|
||||
arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_fracff_40nm.xml
|
||||
|
||||
[BENCHMARKS]
|
||||
bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/counters/counter_8bit_async_reset/counter.v
|
||||
|
||||
[SYNTHESIS_PARAM]
|
||||
# Yosys script parameters
|
||||
bench_yosys_cell_sim_verilog_common=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_fracff_40nm_cell_sim.v
|
||||
bench_yosys_dff_map_verilog_common=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_fracff_40nm_dff_map.v
|
||||
bench_yosys_bram_map_rules_common=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_40nm_bram.txt
|
||||
bench_yosys_bram_map_verilog_common=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_40nm_bram_map.v
|
||||
bench_yosys_dsp_map_verilog_common=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_40nm_dsp_map.v
|
||||
bench_yosys_dsp_map_parameters_common=-D DSP_A_MAXWIDTH=36 -D DSP_B_MAXWIDTH=36 -D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 -D DSP_NAME=mult_36x36
|
||||
bench_read_verilog_options_common = -nolatches
|
||||
bench_yosys_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_dff_flow.ys
|
||||
bench_yosys_rewrite_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_flow_with_rewrite.ys
|
||||
|
||||
bench0_top = counter
|
||||
bench0_openfpga_pin_constraints_file=${PATH:TASK_DIR}/config/pin_constraints_reset.xml
|
||||
|
||||
[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH]
|
||||
end_flow_with_test=
|
||||
vpr_fpga_verilog_formal_verification_top_netlist=
|
Loading…
Reference in New Issue