Merge branch 'master' of https://github.com/lnis-uofu/OpenFPGA into vtr_upgrade
This commit is contained in:
commit
56619f9a47
|
@ -1 +1 @@
|
|||
1.1.457
|
||||
1.1.463
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
***********************************************************************/
|
||||
#include "vtr_log.h"
|
||||
#include "vtr_assert.h"
|
||||
#include "rr_gsb_utils.h"
|
||||
#include "device_rr_gsb.h"
|
||||
|
||||
/* namespace openfpga begins */
|
||||
|
@ -11,6 +12,9 @@ namespace openfpga {
|
|||
/************************************************************************
|
||||
* Constructors
|
||||
***********************************************************************/
|
||||
DeviceRRGSB::DeviceRRGSB(const VprDeviceAnnotation& device_annotation)
|
||||
: device_annotation_(device_annotation) {
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Public accessors
|
||||
|
@ -230,7 +234,7 @@ void DeviceRRGSB::build_cb_unique_module(const RRGraphView& rr_graph, const t_rr
|
|||
/* Traverse the unique_mirror list and check it is an mirror of another */
|
||||
for (size_t id = 0; id < get_num_cb_unique_module(cb_type); ++id) {
|
||||
const RRGSB& unique_module = get_cb_unique_module(cb_type, id);
|
||||
if (true == rr_gsb_[ix][iy].is_cb_mirror(rr_graph, unique_module, cb_type)) {
|
||||
if (true == is_cb_mirror(rr_graph, device_annotation_, rr_gsb_[ix][iy], unique_module, cb_type)) {
|
||||
/* This is a mirror, raise the flag and we finish */
|
||||
is_unique_module = false;
|
||||
/* Record the id of unique mirror */
|
||||
|
@ -266,7 +270,7 @@ void DeviceRRGSB::build_sb_unique_module(const RRGraphView& rr_graph) {
|
|||
* else the sb is unique
|
||||
*/
|
||||
const RRGSB& unique_module = get_sb_unique_module(id);
|
||||
if (true == rr_gsb_[ix][iy].is_sb_mirror(rr_graph, unique_module)) {
|
||||
if (true == is_sb_mirror(rr_graph, device_annotation_, rr_gsb_[ix][iy], unique_module)) {
|
||||
/* This is a mirror, raise the flag and we finish */
|
||||
is_unique_module = false;
|
||||
/* Record the id of unique mirror */
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "rr_graph_view.h"
|
||||
|
||||
#include "rr_gsb.h"
|
||||
#include "vpr_device_annotation.h"
|
||||
|
||||
/* namespace openfpga begins */
|
||||
namespace openfpga {
|
||||
|
@ -26,6 +27,7 @@ namespace openfpga {
|
|||
*******************************************************************/
|
||||
class DeviceRRGSB {
|
||||
public: /* Contructors */
|
||||
DeviceRRGSB(const VprDeviceAnnotation& device_annotation);
|
||||
public: /* Accessors */
|
||||
vtr::Point<size_t> get_gsb_range() const; /* get the max coordinate of the switch block array */
|
||||
const RRGSB& get_gsb(const vtr::Point<size_t>& coordinate) const; /* Get a rr switch block in the array with a coordinate */
|
||||
|
@ -84,6 +86,9 @@ class DeviceRRGSB {
|
|||
|
||||
std::vector<std::vector<size_t>> cby_unique_module_id_; /* A map from rr_gsb to its unique mirror */
|
||||
std::vector<vtr::Point<size_t>> cby_unique_module_; /* For each side of connection block, we identify a list of unique modules based on its connection. This is a matrix [0..num_module] */
|
||||
|
||||
/* Cached data */
|
||||
const VprDeviceAnnotation& device_annotation_;
|
||||
};
|
||||
|
||||
} /* End namespace openfpga*/
|
||||
|
|
|
@ -124,7 +124,7 @@ class OpenfpgaContext : public Context {
|
|||
openfpga::VprBitstreamAnnotation vpr_bitstream_annotation_;
|
||||
|
||||
/* Device-level annotation */
|
||||
openfpga::DeviceRRGSB device_rr_gsb_;
|
||||
openfpga::DeviceRRGSB device_rr_gsb_{vpr_device_annotation_};
|
||||
|
||||
/* Library of physical implmentation of routing multiplexers */
|
||||
openfpga::MuxLibrary mux_lib_;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
*******************************************************************/
|
||||
/* Headers from vtrutil library */
|
||||
#include "vtr_assert.h"
|
||||
#include "vtr_log.h"
|
||||
|
||||
/* Headers from openfpgautil library */
|
||||
#include "openfpga_side_manager.h"
|
||||
|
@ -55,4 +56,326 @@ std::vector<RRNodeId> get_rr_gsb_chan_node_configurable_driver_nodes(const RRGra
|
|||
return driver_nodes;
|
||||
}
|
||||
|
||||
/** @brief Evaluate if two routing channels are mirror to each other */
|
||||
static
|
||||
bool is_chan_mirror(const RRGraph& rr_graph,
|
||||
const VprDeviceAnnotation& device_annotation,
|
||||
const RRChan& base,
|
||||
const RRChan& cand) {
|
||||
/* If any following element does not match, it is not mirror */
|
||||
/* 1. type */
|
||||
if (base.get_type() != cand.get_type()) {
|
||||
return false;
|
||||
}
|
||||
/* 2. track_width */
|
||||
if (base.get_chan_width() != cand.get_chan_width()) {
|
||||
return false;
|
||||
}
|
||||
/* 3. for each node */
|
||||
for (size_t inode = 0; inode < base.get_chan_width(); ++inode) {
|
||||
/* 3.1 check node type */
|
||||
if (rr_graph.node_type(base.get_node(inode)) != rr_graph.node_type(cand.get_node(inode))) {
|
||||
return false;
|
||||
}
|
||||
/* 3.2 check node directionality */
|
||||
if (rr_graph.node_direction(base.get_node(inode)) != rr_graph.node_direction(cand.get_node(inode))) {
|
||||
return false;
|
||||
}
|
||||
/* 3.3 check node segment */
|
||||
/* FIXME: Maybe this is too tight! Consider to remove the restrictions on segments */
|
||||
if (device_annotation.rr_segment_circuit_model(base.get_node_segment(inode)) != device_annotation.rr_segment_circuit_model(cand.get_node_segment(inode))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** @brief check if two rr_nodes in two GSBs have a similar set of drive_rr_nodes for each drive_rr_node:
|
||||
* 1. CHANX or CHANY: should have the same side and index
|
||||
* 2. OPIN or IPIN: should have the same side and index
|
||||
* 3. each drive_rr_switch should be the same
|
||||
*/
|
||||
static
|
||||
bool is_sb_node_mirror(const RRGraph& rr_graph,
|
||||
const VprDeviceAnnotation& device_annotation,
|
||||
const RRGSB& base,
|
||||
const RRGSB& cand,
|
||||
const e_side& node_side,
|
||||
const size_t& track_id) {
|
||||
/* Ensure rr_nodes are either the output of short-connection or multiplexer */
|
||||
bool is_short_conkt = base.is_sb_node_passing_wire(rr_graph, node_side, track_id);
|
||||
|
||||
if (is_short_conkt != cand.is_sb_node_passing_wire(rr_graph, node_side, track_id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (true == is_short_conkt) {
|
||||
/* Since, both are pass wires,
|
||||
* The two node should be equivalent
|
||||
* we can return here
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Use unsorted/sorted edges */
|
||||
std::vector<RREdgeId> node_in_edges = base.get_chan_node_in_edges(rr_graph, node_side, track_id);
|
||||
std::vector<RREdgeId> cand_node_in_edges = cand.get_chan_node_in_edges(rr_graph, node_side, track_id);
|
||||
|
||||
/* For non-passing wires, check driving rr_nodes */
|
||||
if (node_in_edges.size() != cand_node_in_edges.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
VTR_ASSERT(node_in_edges.size() == cand_node_in_edges.size());
|
||||
|
||||
for (size_t iedge = 0; iedge < node_in_edges.size(); ++iedge) {
|
||||
RREdgeId src_edge = node_in_edges[iedge];
|
||||
RREdgeId src_cand_edge = cand_node_in_edges[iedge];
|
||||
RRNodeId src_node = rr_graph.edge_src_node(src_edge);
|
||||
RRNodeId src_cand_node = rr_graph.edge_src_node(src_cand_edge);
|
||||
/* node type should be the same */
|
||||
if (rr_graph.node_type(src_node) != rr_graph.node_type(src_cand_node)) {
|
||||
return false;
|
||||
}
|
||||
/* switch type should be the same */
|
||||
if (device_annotation.rr_switch_circuit_model(rr_graph.edge_switch(src_edge)) != device_annotation.rr_switch_circuit_model(rr_graph.edge_switch(src_cand_edge))) {
|
||||
return false;
|
||||
}
|
||||
int src_node_id, des_node_id;
|
||||
enum e_side src_node_side, des_node_side;
|
||||
base.get_node_side_and_index(rr_graph, src_node, OUT_PORT, src_node_side, src_node_id);
|
||||
cand.get_node_side_and_index(rr_graph, src_cand_node, OUT_PORT, des_node_side, des_node_id);
|
||||
if (src_node_id != des_node_id) {
|
||||
return false;
|
||||
}
|
||||
if (src_node_side != des_node_side) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** @brief Check if all the routing segments of a side of candidate SB is a mirror of the current one */
|
||||
static
|
||||
bool is_sb_side_segment_mirror(const RRGraph& rr_graph,
|
||||
const VprDeviceAnnotation& device_annotation,
|
||||
const RRGSB& base,
|
||||
const RRGSB& cand,
|
||||
const e_side& side,
|
||||
const RRSegmentId& seg_id) {
|
||||
/* Create a side manager */
|
||||
SideManager side_manager(side);
|
||||
|
||||
/* Make sure both Switch blocks has this side!!! */
|
||||
VTR_ASSERT ( side_manager.to_size_t() < base.get_num_sides() );
|
||||
VTR_ASSERT ( side_manager.to_size_t() < cand.get_num_sides() );
|
||||
|
||||
/* check the numbers/directionality of channel rr_nodes */
|
||||
/* Ensure we have the same channel width on this side */
|
||||
if (base.get_chan_width(side) != cand.get_chan_width(side)) {
|
||||
return false;
|
||||
}
|
||||
for (size_t itrack = 0; itrack < base.get_chan_width(side); ++itrack) {
|
||||
/* FIXME: Maybe this is too tight! Consider to remove the restrictions on segments */
|
||||
if (device_annotation.rr_segment_circuit_model(seg_id) != device_annotation.rr_segment_circuit_model(base.get_chan_node_segment(side, itrack))) {
|
||||
continue;
|
||||
}
|
||||
/* Check the directionality of each node */
|
||||
if (base.get_chan_node_direction(side, itrack) != cand.get_chan_node_direction(side, itrack)) {
|
||||
return false;
|
||||
}
|
||||
/* Check the track_id of each node
|
||||
* ptc is not necessary, we care the connectivity!
|
||||
*/
|
||||
/* For OUT_PORT rr_node, we need to check fan-in */
|
||||
if (OUT_PORT != base.get_chan_node_direction(side, itrack)) {
|
||||
continue; /* skip IN_PORT */
|
||||
}
|
||||
|
||||
if (false == is_sb_node_mirror(rr_graph, device_annotation, base, cand, side, itrack)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* check the numbers of opin_rr_nodes */
|
||||
if (base.get_num_opin_nodes(side) != cand.get_num_opin_nodes(side)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** @brief check if a side of candidate SB is a mirror of the current one
|
||||
* Check the specified side of two switch blocks:
|
||||
* 1. Number of channel/opin/ipin rr_nodes are same
|
||||
* For channel rr_nodes
|
||||
* 2. check if their track_ids (ptc_num) are same
|
||||
* 3. Check if the switches (ids) are same
|
||||
* For opin/ipin rr_nodes,
|
||||
* 4. check if their parent type_descriptors same,
|
||||
* 5. check if pin class id and pin id are same
|
||||
* If all above are satisfied, the side of the two switch blocks are mirrors!
|
||||
*/
|
||||
static
|
||||
bool is_sb_side_mirror(const RRGraph& rr_graph,
|
||||
const VprDeviceAnnotation& device_annotation,
|
||||
const RRGSB& base,
|
||||
const RRGSB& cand,
|
||||
const e_side& side) {
|
||||
|
||||
/* get a list of segments */
|
||||
std::vector<RRSegmentId> seg_ids = base.get_chan_segment_ids(side);
|
||||
|
||||
for (size_t iseg = 0; iseg < seg_ids.size(); ++iseg) {
|
||||
if (false == is_sb_side_segment_mirror(rr_graph, device_annotation, base, cand, side, seg_ids[iseg])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** @brief Identify if the Switch Block part of two GSBs are mirror (same in structure) or not. Return true if so, otherwise return false
|
||||
* Idenify mirror Switch blocks
|
||||
* Check each two switch blocks:
|
||||
* 1. Number of channel/opin/ipin rr_nodes are same
|
||||
* For channel rr_nodes
|
||||
* 2. check if their track_ids (ptc_num) are same
|
||||
* 3. Check if the switches (ids) are same
|
||||
* For opin/ipin rr_nodes,
|
||||
* 4. check if their parent type_descriptors same,
|
||||
* 5. check if pin class id and pin id are same
|
||||
* If all above are satisfied, the two switch blocks are mirrors!
|
||||
*/
|
||||
bool is_sb_mirror(const RRGraph& rr_graph,
|
||||
const VprDeviceAnnotation& device_annotation,
|
||||
const RRGSB& base,
|
||||
const RRGSB& cand) {
|
||||
/* check the numbers of sides */
|
||||
if (base.get_num_sides() != cand.get_num_sides()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* check the numbers/directionality of channel rr_nodes */
|
||||
for (size_t side = 0; side < base.get_num_sides(); ++side) {
|
||||
SideManager side_manager(side);
|
||||
if (false == is_sb_side_mirror(rr_graph, device_annotation, base, cand, side_manager.get_side())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** @brief Check if two ipin_nodes have a similar set of drive_rr_nodes for each drive_rr_node:
|
||||
* 1. CHANX or CHANY: should have the same side and index
|
||||
* 2. each drive_rr_switch should be the same
|
||||
*/
|
||||
static
|
||||
bool is_cb_node_mirror(const RRGraph& rr_graph,
|
||||
const VprDeviceAnnotation& device_annotation,
|
||||
const RRGSB& base,
|
||||
const RRGSB& cand,
|
||||
const t_rr_type& cb_type,
|
||||
const e_side& node_side,
|
||||
const size_t& node_id) {
|
||||
/* Ensure rr_nodes are either the output of short-connection or multiplexer */
|
||||
RRNodeId node = base.get_ipin_node(node_side, node_id);
|
||||
RRNodeId cand_node = cand.get_ipin_node(node_side, node_id);
|
||||
|
||||
if ( rr_graph.node_in_edges(node).size() != rr_graph.node_in_edges(cand_node).size() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<RREdgeId> node_in_edges;
|
||||
for (const RREdgeId& edge : rr_graph.node_in_edges(node)) {
|
||||
node_in_edges.push_back(edge);
|
||||
}
|
||||
|
||||
std::vector<RREdgeId> cand_node_in_edges;
|
||||
for (const RREdgeId& edge : rr_graph.node_in_edges(cand_node)) {
|
||||
cand_node_in_edges.push_back(edge);
|
||||
}
|
||||
VTR_ASSERT(node_in_edges.size() == cand_node_in_edges.size());
|
||||
|
||||
for (size_t iedge = 0; iedge < node_in_edges.size(); ++iedge) {
|
||||
RREdgeId src_edge = node_in_edges[iedge];
|
||||
RREdgeId src_cand_edge = cand_node_in_edges[iedge];
|
||||
RRNodeId src_node = rr_graph.edge_src_node(src_edge);
|
||||
RRNodeId src_cand_node = rr_graph.edge_src_node(src_cand_edge);
|
||||
/* node type should be the same */
|
||||
if (rr_graph.node_type(src_node) != rr_graph.node_type(src_cand_node)) {
|
||||
return false;
|
||||
}
|
||||
/* switch type should be the same */
|
||||
if (device_annotation.rr_switch_circuit_model(rr_graph.edge_switch(src_edge)) != device_annotation.rr_switch_circuit_model(rr_graph.edge_switch(src_cand_edge))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int src_node_id, des_node_id;
|
||||
enum e_side src_node_side, des_node_side;
|
||||
enum e_side chan_side = base.get_cb_chan_side(cb_type);
|
||||
switch (rr_graph.node_type(src_node)) {
|
||||
case CHANX:
|
||||
case CHANY:
|
||||
/* if the drive rr_nodes are routing tracks, find index */
|
||||
src_node_id = base.get_chan_node_index(chan_side, src_node);
|
||||
des_node_id = cand.get_chan_node_index(chan_side, src_cand_node);
|
||||
break;
|
||||
case OPIN:
|
||||
base.get_node_side_and_index(rr_graph, src_node, OUT_PORT, src_node_side, src_node_id);
|
||||
cand.get_node_side_and_index(rr_graph, src_cand_node, OUT_PORT, des_node_side, des_node_id);
|
||||
if (src_node_side != des_node_side) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
VTR_LOG("Invalid type of drive_rr_nodes for ipin_node!\n");
|
||||
exit(1);
|
||||
}
|
||||
if (src_node_id != des_node_id) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** @brief Check if the candidate CB is a mirror of the current baselien */
|
||||
bool is_cb_mirror(const RRGraph& rr_graph,
|
||||
const VprDeviceAnnotation& device_annotation,
|
||||
const RRGSB& base,
|
||||
const RRGSB& cand,
|
||||
const t_rr_type& cb_type) {
|
||||
/* Check if channel width is the same */
|
||||
if ( base.get_cb_chan_width(cb_type) != cand.get_cb_chan_width(cb_type) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
enum e_side chan_side = base.get_cb_chan_side(cb_type);
|
||||
|
||||
/* check the numbers/directionality of channel rr_nodes */
|
||||
if ( false == is_chan_mirror(rr_graph, device_annotation, base.chan(chan_side), cand.chan(chan_side)) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* check the equivalence of ipins */
|
||||
std::vector<enum e_side> ipin_side = base.get_cb_ipin_sides(cb_type);
|
||||
for (size_t side = 0; side < ipin_side.size(); ++side) {
|
||||
/* Ensure we have the same number of IPINs on this side */
|
||||
if ( base.get_num_ipin_nodes(ipin_side[side]) != cand.get_num_ipin_nodes(ipin_side[side]) ) {
|
||||
return false;
|
||||
}
|
||||
for (size_t inode = 0; inode < base.get_num_ipin_nodes(ipin_side[side]); ++inode) {
|
||||
if (false == is_cb_node_mirror(rr_graph, device_annotation, base, cand, cb_type, ipin_side[side], inode)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} /* end namespace openfpga */
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
#include "rr_gsb.h"
|
||||
#include "vpr_device_annotation.h"
|
||||
|
||||
/********************************************************************
|
||||
* Function declaration
|
||||
|
@ -23,6 +24,17 @@ std::vector<RRNodeId> get_rr_gsb_chan_node_configurable_driver_nodes(const RRGra
|
|||
const e_side& chan_side,
|
||||
const size_t& track_id);
|
||||
|
||||
bool is_sb_mirror(const RRGraph& rr_graph,
|
||||
const VprDeviceAnnotation& device_annotation,
|
||||
const RRGSB& base,
|
||||
const RRGSB& cand);
|
||||
|
||||
bool is_cb_mirror(const RRGraph& rr_graph,
|
||||
const VprDeviceAnnotation& device_annotation,
|
||||
const RRGSB& base,
|
||||
const RRGSB& cand,
|
||||
const t_rr_type& cb_type);
|
||||
|
||||
} /* end namespace openfpga */
|
||||
|
||||
#endif
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
# This script is designed to test the option --no_time_stamp in related commands
|
||||
# It can NOT be used an example script to achieve other objectives
|
||||
#--write_rr_graph example_rr_graph.xml
|
||||
vpr ${VPR_ARCH_FILE} ${VPR_TESTBENCH_BLIF} --route_chan_width ${OPENFPGA_VPR_ROUTE_CHAN_WIDTH} --clock_modeling route
|
||||
vpr ${VPR_ARCH_FILE} ${VPR_TESTBENCH_BLIF} --device ${OPENFPGA_VPR_DEVICE_LAYOUT} --route_chan_width ${OPENFPGA_VPR_ROUTE_CHAN_WIDTH} --clock_modeling route
|
||||
|
||||
# Read OpenFPGA architecture definition
|
||||
read_openfpga_arch -f ${OPENFPGA_ARCH_FILE}
|
||||
|
@ -60,7 +60,7 @@ report_bitstream_distribution --file ${OPENFPGA_OUTPUT_DIR}/bitstream_distributi
|
|||
|
||||
# Write the Verilog netlist for FPGA fabric
|
||||
# - Enable the use of explicit port mapping in Verilog netlist
|
||||
write_fabric_verilog --file ${OPENFPGA_OUTPUT_DIR} --explicit_port_mapping --include_timing --print_user_defined_template --verbose --no_time_stamp
|
||||
write_fabric_verilog --file ${OPENFPGA_OUTPUT_DIR} --explicit_port_mapping --include_timing --print_user_defined_template --use_relative_path --verbose --no_time_stamp
|
||||
|
||||
# Write the Verilog testbench for FPGA fabric
|
||||
# - We suggest the use of same output directory as fabric Verilog netlists
|
||||
|
@ -69,7 +69,7 @@ write_fabric_verilog --file ${OPENFPGA_OUTPUT_DIR} --explicit_port_mapping --inc
|
|||
# - 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 ${OPENFPGA_OUTPUT_DIR} --explicit_port_mapping --no_time_stamp
|
||||
write_preconfigured_testbench --file ${OPENFPGA_OUTPUT_DIR} --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --no_time_stamp
|
||||
write_preconfigured_testbench --file ${OPENFPGA_OUTPUT_DIR} --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --use_relative_path --explicit_port_mapping --no_time_stamp
|
||||
|
||||
# Write the SDC files for PnR backend
|
||||
# - Turn on every options here
|
||||
|
|
|
@ -190,15 +190,16 @@ create-task _task_copy basic_tests/generate_fabric
|
|||
run-task _task_copy $@
|
||||
|
||||
echo -e "Testing output files without time stamp";
|
||||
run-task basic_tests/no_time_stamp $@
|
||||
run-task basic_tests/no_time_stamp/device_1x1 $@
|
||||
run-task basic_tests/no_time_stamp/device_4x4 $@
|
||||
# Run git-diff to ensure no changes on the golden netlists
|
||||
# Switch to root path in case users are running the tests in another location
|
||||
cd ${OPENFPGA_PATH}
|
||||
pwd
|
||||
git config --global --add safe.directory ${OPENFPGA_PATH}
|
||||
git log
|
||||
git diff --name-status -- ':${OPENFPGA_PATH}/openfpga_flow/tasks/basic_tests/no_time_stamp/golden_outputs_no_time_stamp/**'
|
||||
if git diff --name-status --exit-code -- ':${OPENFPGA_PATH}/openfpga_flow/tasks/basic_tests/no_time_stamp/golden_outputs_no_time_stamp/**'; then
|
||||
git diff --name-status -- ':${OPENFPGA_PATH}/openfpga_flow/tasks/basic_tests/no_time_stamp/*/golden_outputs_no_time_stamp/**'
|
||||
if git diff --name-status --exit-code -- ':${OPENFPGA_PATH}/openfpga_flow/tasks/basic_tests/no_time_stamp/*/golden_outputs_no_time_stamp/**'; then
|
||||
echo -e "Golden netlist remain unchanged"
|
||||
else
|
||||
echo -e "Detect changes in golden netlists"; exit 1;
|
||||
|
|
|
@ -19,6 +19,7 @@ fpga_flow=yosys_vpr
|
|||
openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/no_time_stamp_example_script.openfpga
|
||||
openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_cc_openfpga.xml
|
||||
openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml
|
||||
openfpga_vpr_device_layout = auto
|
||||
openfpga_vpr_route_chan_width = 26
|
||||
openfpga_output_dir=${PATH:TASK_DIR}/golden_outputs_no_time_stamp
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
//-------------------------------------------
|
||||
// FPGA Synthesizable Verilog Netlist
|
||||
// Description: Netlist Summary
|
||||
// Author: Xifan TANG
|
||||
// Organization: University of Utah
|
||||
//-------------------------------------------
|
||||
//----- Time scale -----
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
// ------ Include fabric top-level netlists -----
|
||||
`include "fabric_netlists.v"
|
||||
|
||||
`include "and2_output_verilog.v"
|
||||
|
||||
`include "and2_top_formal_verification.v"
|
||||
`include "and2_formal_random_top_tb.v"
|
|
@ -0,0 +1,53 @@
|
|||
//-------------------------------------------
|
||||
// FPGA Synthesizable Verilog Netlist
|
||||
// Description: Fabric Netlist Summary
|
||||
// Author: Xifan TANG
|
||||
// Organization: University of Utah
|
||||
//-------------------------------------------
|
||||
//----- Time scale -----
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
// ------ Include defines: preproc flags -----
|
||||
`include "fpga_defines.v"
|
||||
|
||||
// ------ Include user-defined netlists -----
|
||||
`include "/home/tangxifan/test/OpenFPGA/openfpga_flow/openfpga_cell_library/verilog/dff.v"
|
||||
`include "/home/tangxifan/test/OpenFPGA/openfpga_flow/openfpga_cell_library/verilog/gpio.v"
|
||||
// ------ Include primitive module netlists -----
|
||||
`include "sub_module/inv_buf_passgate.v"
|
||||
`include "sub_module/arch_encoder.v"
|
||||
`include "sub_module/local_encoder.v"
|
||||
`include "sub_module/mux_primitives.v"
|
||||
`include "sub_module/muxes.v"
|
||||
`include "sub_module/luts.v"
|
||||
`include "sub_module/wires.v"
|
||||
`include "sub_module/memories.v"
|
||||
`include "sub_module/shift_register_banks.v"
|
||||
|
||||
// ------ Include logic block netlists -----
|
||||
`include "lb/logical_tile_io_mode_physical__iopad.v"
|
||||
`include "lb/logical_tile_io_mode_io_.v"
|
||||
`include "lb/logical_tile_clb_mode_default__fle_mode_n1_lut4__ble4_mode_default__lut4.v"
|
||||
`include "lb/logical_tile_clb_mode_default__fle_mode_n1_lut4__ble4_mode_default__ff.v"
|
||||
`include "lb/logical_tile_clb_mode_default__fle_mode_n1_lut4__ble4.v"
|
||||
`include "lb/logical_tile_clb_mode_default__fle.v"
|
||||
`include "lb/logical_tile_clb_mode_clb_.v"
|
||||
`include "lb/grid_io_top.v"
|
||||
`include "lb/grid_io_right.v"
|
||||
`include "lb/grid_io_bottom.v"
|
||||
`include "lb/grid_io_left.v"
|
||||
`include "lb/grid_clb.v"
|
||||
|
||||
// ------ Include routing module netlists -----
|
||||
`include "routing/sb_0__0_.v"
|
||||
`include "routing/sb_0__1_.v"
|
||||
`include "routing/sb_1__0_.v"
|
||||
`include "routing/sb_1__1_.v"
|
||||
`include "routing/cbx_1__0_.v"
|
||||
`include "routing/cbx_1__1_.v"
|
||||
`include "routing/cby_0__1_.v"
|
||||
`include "routing/cby_1__1_.v"
|
||||
|
||||
// ------ Include fabric top-level netlists -----
|
||||
`include "fpga_top.v"
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
|
||||
# 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 = true
|
||||
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/no_time_stamp_example_script.openfpga
|
||||
openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_cc_openfpga.xml
|
||||
openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml
|
||||
openfpga_vpr_device_layout = 4x4
|
||||
openfpga_vpr_route_chan_width = 20
|
||||
openfpga_output_dir=${PATH:TASK_DIR}/golden_outputs_no_time_stamp
|
||||
|
||||
[ARCHITECTURES]
|
||||
arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml
|
||||
|
||||
[BENCHMARKS]
|
||||
bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v
|
||||
|
||||
[SYNTHESIS_PARAM]
|
||||
bench_read_verilog_options_common = -nolatches
|
||||
bench0_top = and2
|
||||
|
||||
[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH]
|
|
@ -0,0 +1,126 @@
|
|||
//-------------------------------------------
|
||||
// FPGA Synthesizable Verilog Netlist
|
||||
// Description: FPGA Verilog Testbench for Formal Top-level netlist of Design: and2
|
||||
// Author: Xifan TANG
|
||||
// Organization: University of Utah
|
||||
//-------------------------------------------
|
||||
//----- Time scale -----
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
//----- Default net type -----
|
||||
`default_nettype none
|
||||
|
||||
module and2_top_formal_verification_random_tb;
|
||||
// ----- Default clock port is added here since benchmark does not contain one -------
|
||||
reg [0:0] clk;
|
||||
|
||||
// ----- Shared inputs -------
|
||||
reg [0:0] a;
|
||||
reg [0:0] b;
|
||||
|
||||
// ----- FPGA fabric outputs -------
|
||||
wire [0:0] c_gfpga;
|
||||
|
||||
// ----- Benchmark outputs -------
|
||||
wire [0:0] c_bench;
|
||||
|
||||
// ----- Output vectors checking flags -------
|
||||
reg [0:0] c_flag;
|
||||
|
||||
// ----- Error counter -------
|
||||
integer nb_error= 0;
|
||||
|
||||
// ----- FPGA fabric instanciation -------
|
||||
and2_top_formal_verification FPGA_DUT(
|
||||
.a(a),
|
||||
.b(b),
|
||||
.c(c_gfpga)
|
||||
);
|
||||
// ----- End FPGA Fabric Instanication -------
|
||||
|
||||
// ----- Reference Benchmark Instanication -------
|
||||
and2 REF_DUT(
|
||||
.a(a),
|
||||
.b(b),
|
||||
.c(c_bench)
|
||||
);
|
||||
// ----- End reference Benchmark Instanication -------
|
||||
|
||||
// ----- Clock 'clk' Initialization -------
|
||||
initial begin
|
||||
clk[0] <= 1'b0;
|
||||
while(1) begin
|
||||
#0.4537859857
|
||||
clk[0] <= !clk[0];
|
||||
end
|
||||
end
|
||||
|
||||
// ----- Begin reset signal generation -----
|
||||
// ----- End reset signal generation -----
|
||||
|
||||
// ----- Input Initialization -------
|
||||
initial begin
|
||||
a <= 1'b0;
|
||||
b <= 1'b0;
|
||||
|
||||
c_flag[0] <= 1'b0;
|
||||
end
|
||||
|
||||
// ----- Input Stimulus -------
|
||||
always@(negedge clk[0]) begin
|
||||
a <= $random;
|
||||
b <= $random;
|
||||
end
|
||||
|
||||
// ----- Begin checking output vectors -------
|
||||
// ----- Skip the first falling edge of clock, it is for initialization -------
|
||||
reg [0:0] sim_start;
|
||||
|
||||
always@(negedge clk[0]) begin
|
||||
if (1'b1 == sim_start[0]) begin
|
||||
sim_start[0] <= ~sim_start[0];
|
||||
end else
|
||||
begin
|
||||
if(!(c_gfpga === c_bench) && !(c_bench === 1'bx)) begin
|
||||
c_flag <= 1'b1;
|
||||
end else begin
|
||||
c_flag<= 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always@(posedge c_flag) begin
|
||||
if(c_flag) begin
|
||||
nb_error = nb_error + 1;
|
||||
$display("Mismatch on c_gfpga at time = %t", $realtime);
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
// ----- Begin output waveform to VCD file-------
|
||||
initial begin
|
||||
$dumpfile("and2_formal.vcd");
|
||||
$dumpvars(1, and2_top_formal_verification_random_tb);
|
||||
end
|
||||
// ----- END output waveform to VCD file -------
|
||||
|
||||
initial begin
|
||||
sim_start[0] <= 1'b1;
|
||||
$timeformat(-9, 2, "ns", 20);
|
||||
$display("Simulation start");
|
||||
// ----- Can be changed by the user for his/her need -------
|
||||
#6.353003979
|
||||
if(nb_error == 0) begin
|
||||
$display("Simulation Succeed");
|
||||
end else begin
|
||||
$display("Simulation Failed with %d error(s)", nb_error);
|
||||
end
|
||||
$finish;
|
||||
end
|
||||
|
||||
endmodule
|
||||
// ----- END Verilog module for and2_top_formal_verification_random_tb -----
|
||||
|
||||
//----- Default net type -----
|
||||
`default_nettype none
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,16 @@
|
|||
//-------------------------------------------
|
||||
// FPGA Synthesizable Verilog Netlist
|
||||
// Description: Netlist Summary
|
||||
// Author: Xifan TANG
|
||||
// Organization: University of Utah
|
||||
//-------------------------------------------
|
||||
//----- Time scale -----
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
// ------ Include fabric top-level netlists -----
|
||||
`include "fabric_netlists.v"
|
||||
|
||||
`include "and2_output_verilog.v"
|
||||
|
||||
`include "and2_top_formal_verification.v"
|
||||
`include "and2_formal_random_top_tb.v"
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue