From 712eeb13402bdf163ad0952e9ed898aff0bdb732 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 23 Feb 2020 22:09:46 -0700 Subject: [PATCH] bring bitstream generator for routing modules online --- .../fpga_bitstream/build_device_bitstream.cpp | 13 +- .../fpga_bitstream/build_mux_bitstream.cpp | 7 +- .../build_routing_bitstream.cpp | 442 ++++++++++++++++++ .../fpga_bitstream/build_routing_bitstream.h | 39 ++ .../fpga_bitstream/mux_bitstream_constants.h | 15 + 5 files changed, 508 insertions(+), 8 deletions(-) create mode 100644 openfpga/src/fpga_bitstream/build_routing_bitstream.cpp create mode 100644 openfpga/src/fpga_bitstream/build_routing_bitstream.h create mode 100644 openfpga/src/fpga_bitstream/mux_bitstream_constants.h diff --git a/openfpga/src/fpga_bitstream/build_device_bitstream.cpp b/openfpga/src/fpga_bitstream/build_device_bitstream.cpp index 997c83fb6..0b6d01d39 100644 --- a/openfpga/src/fpga_bitstream/build_device_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/build_device_bitstream.cpp @@ -14,7 +14,7 @@ #include "openfpga_naming.h" //#include "build_grid_bitstream.h" -//#include "build_routing_bitstream.h" +#include "build_routing_bitstream.h" #include "build_device_bitstream.h" /* begin namespace openfpga */ @@ -60,9 +60,18 @@ BitstreamManager build_device_bitstream(const VprContext& vpr_ctx, /* Create bitstream from routing architectures */ VTR_LOGV(verbose, "Building routing bitstream...\n"); - //build_routing_bitstream(bitstream_manager, top_block, module_manager, circuit_lib, mux_lib, rr_switches, L_rr_node, L_device_rr_gsb); + build_routing_bitstream(bitstream_manager, top_block, + openfpga_ctx.module_graph(), + openfpga_ctx.arch().circuit_lib, + openfpga_ctx.mux_lib(), + openfpga_ctx.vpr_device_annotation(), + openfpga_ctx.vpr_routing_annotation(), + vpr_ctx.device().rr_graph, + openfpga_ctx.device_rr_gsb()); VTR_LOGV(verbose, "Done\n"); + VTR_LOGV(verbose, "Decoded %lu configuration bits\n", bitstream_manager.bits().size()); + return bitstream_manager; } diff --git a/openfpga/src/fpga_bitstream/build_mux_bitstream.cpp b/openfpga/src/fpga_bitstream/build_mux_bitstream.cpp index 3b7e06354..5de0e3d0e 100644 --- a/openfpga/src/fpga_bitstream/build_mux_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/build_mux_bitstream.cpp @@ -13,17 +13,12 @@ #include "mux_utils.h" #include "decoder_library_utils.h" +#include "mux_bitstream_constants.h" #include "build_mux_bitstream.h" /* begin namespace openfpga */ namespace openfpga { -/* Default path ID of a unused multiplexer */ -#define DEFAULT_PATH_ID -1 - -/* Default path ID of a unused multiplexer when there are no constant inputs*/ -#define DEFAULT_MUX_PATH_ID 0 - /******************************************************************** * Find the default path id of a MUX * This is applied when the path id specified is DEFAULT_PATH_ID, diff --git a/openfpga/src/fpga_bitstream/build_routing_bitstream.cpp b/openfpga/src/fpga_bitstream/build_routing_bitstream.cpp new file mode 100644 index 000000000..e0dd75c2a --- /dev/null +++ b/openfpga/src/fpga_bitstream/build_routing_bitstream.cpp @@ -0,0 +1,442 @@ +/******************************************************************** + * This file includes functions to build bitstream from global routing + * architecture of a mapped FPGA fabric + * We decode the bitstream from configuration of routing multiplexers + * which locate in global routing architecture + *******************************************************************/ +#include + +/* Headers from vtrutil library */ +#include "vtr_assert.h" +#include "vtr_log.h" + +/* Headers from openfpgautil library */ +#include "openfpga_side_manager.h" + +#include "mux_utils.h" +#include "rr_gsb_utils.h" +#include "openfpga_reserved_words.h" +#include "openfpga_naming.h" +#include "openfpga_rr_graph_utils.h" + +#include "mux_bitstream_constants.h" +#include "build_mux_bitstream.h" +#include "build_routing_bitstream.h" + +/* begin namespace openfpga */ +namespace openfpga { + +/******************************************************************** + * This function generates bitstream for a routing multiplexer + * This function will identify if a node indicates a routing multiplexer + * If not a routing multiplexer, no bitstream is needed here + * If yes, we will generate the bitstream for the routing multiplexer + *******************************************************************/ +static +void build_switch_block_mux_bitstream(BitstreamManager& bitstream_manager, + const ConfigBlockId& mux_mem_block, + const ModuleManager& module_manager, + const CircuitLibrary& circuit_lib, + const MuxLibrary& mux_lib, + const RRGraph& rr_graph, + const RRNodeId& cur_rr_node, + const std::vector& drive_rr_nodes, + const VprDeviceAnnotation& device_annotation, + const VprRoutingAnnotation& routing_annotation) { + /* Check current rr_node is CHANX or CHANY*/ + VTR_ASSERT( (CHANX == rr_graph.node_type(cur_rr_node)) + || (CHANY == rr_graph.node_type(cur_rr_node))); + + /* Find the input size of the implementation of a routing multiplexer */ + size_t datapath_mux_size = drive_rr_nodes.size(); + + /* Find out which routing path is used in this MUX */ + int path_id = DEFAULT_PATH_ID; + for (size_t inode = 0; inode < drive_rr_nodes.size(); ++inode) { + if (routing_annotation.rr_node_net(drive_rr_nodes[inode]) == routing_annotation.rr_node_net(cur_rr_node)) { + path_id = (int)inode; + break; + } + } + + /* Ensure that our path id makes sense! */ + VTR_ASSERT( (DEFAULT_PATH_ID == path_id) + || ( (DEFAULT_PATH_ID < path_id) && (path_id < (int)datapath_mux_size) ) + ); + + /* Find the circuit model id of the mux, we need its design technology which matters the bitstream generation */ + std::vector driver_switches = get_rr_graph_driver_switches(rr_graph, cur_rr_node); + VTR_ASSERT(1 == driver_switches.size()); + CircuitModelId mux_model = device_annotation.rr_switch_circuit_model(driver_switches[0]); + + /* Generate bitstream depend on both technology and structure of this MUX */ + std::vector mux_bitstream = build_mux_bitstream(circuit_lib, mux_model, mux_lib, datapath_mux_size, path_id); + + /* Find the module in module manager and ensure the bitstream size matches! */ + std::string mem_module_name = generate_mux_subckt_name(circuit_lib, mux_model, datapath_mux_size, std::string(MEMORY_MODULE_POSTFIX)); + ModuleId mux_mem_module = module_manager.find_module(mem_module_name); + VTR_ASSERT (true == module_manager.valid_module_id(mux_mem_module)); + ModulePortId mux_mem_out_port_id = module_manager.find_module_port(mux_mem_module, generate_configuration_chain_data_out_name()); + VTR_ASSERT(mux_bitstream.size() == module_manager.module_port(mux_mem_module, mux_mem_out_port_id).get_width()); + + /* Add the bistream to the bitstream manager */ + for (const bool& bit : mux_bitstream) { + ConfigBitId config_bit = bitstream_manager.add_bit(bit); + /* Link the memory bits to the mux mem block */ + bitstream_manager.add_bit_to_block(mux_mem_block, config_bit); + } +} + +/******************************************************************** + * This function generates bitstream for an interconnection, + * i.e., a routing multiplexer, in a Switch Block + * This function will identify if a node indicates a routing multiplexer + * If not a routing multiplexer, no bitstream is needed here + * If yes, we will generate the bitstream for the routing multiplexer + *******************************************************************/ +static +void build_switch_block_interc_bitstream(BitstreamManager& bitstream_manager, + const ConfigBlockId& sb_configurable_block, + const ModuleManager& module_manager, + const CircuitLibrary& circuit_lib, + const MuxLibrary& mux_lib, + const RRGraph& rr_graph, + const VprDeviceAnnotation& device_annotation, + const VprRoutingAnnotation& routing_annotation, + const RRGSB& rr_gsb, + const e_side& chan_side, + const size_t& chan_node_id) { + + std::vector driver_rr_nodes; + + /* Get the node */ + const RRNodeId& cur_rr_node = rr_gsb.get_chan_node(chan_side, chan_node_id); + + /* Determine if the interc lies inside a channel wire, that is interc between segments */ + if (false == rr_gsb.is_sb_node_passing_wire(rr_graph, chan_side, chan_node_id)) { + driver_rr_nodes = get_rr_graph_configurable_driver_nodes(rr_graph, cur_rr_node); + /* Special: if there are zero-driver nodes. We skip here */ + if (0 == driver_rr_nodes.size()) { + return; + } + } + + if ( (0 == driver_rr_nodes.size()) + || (0 == driver_rr_nodes.size()) ) { + /* No bitstream generation required by a special direct connection*/ + return; + } else if (1 < driver_rr_nodes.size()) { + /* Create the block denoting the memory instances that drives this node in Switch Block */ + std::string mem_block_name = generate_sb_memory_instance_name(SWITCH_BLOCK_MEM_INSTANCE_PREFIX, chan_side, chan_node_id, std::string("")); + ConfigBlockId mux_mem_block = bitstream_manager.add_block(mem_block_name); + bitstream_manager.add_child_block(sb_configurable_block, mux_mem_block); + /* This is a routing multiplexer! Generate bitstream */ + build_switch_block_mux_bitstream(bitstream_manager, mux_mem_block, module_manager, + circuit_lib, mux_lib, rr_graph, + cur_rr_node, driver_rr_nodes, + device_annotation, routing_annotation); + } /*Nothing should be done else*/ +} + +/******************************************************************** + * This function generates bitstream for a Switch Block + * and add it to the bitstream manager + * This function will spot all the routing multiplexers in a Switch Block + * using a simple but effective rule: + * The fan-in of each output node. + * If there are more than 2 fan-in, there is a routing multiplexer + * + * Note that the output nodes typically spread over all the sides of a Switch Block + * So, we will iterate over that. + *******************************************************************/ +static +void build_switch_block_bitstream(BitstreamManager& bitstream_manager, + const ConfigBlockId& sb_config_block, + const ModuleManager& module_manager, + const CircuitLibrary& circuit_lib, + const MuxLibrary& mux_lib, + const VprDeviceAnnotation& device_annotation, + const VprRoutingAnnotation& routing_annotation, + const RRGraph& rr_graph, + const RRGSB& rr_gsb) { + + /* Iterate over all the multiplexers */ + for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) { + SideManager side_manager(side); + for (size_t itrack = 0; itrack < rr_gsb.get_chan_width(side_manager.get_side()); ++itrack) { + VTR_ASSERT( (CHANX == rr_graph.node_type(rr_gsb.get_chan_node(side_manager.get_side(), itrack))) + || (CHANY == rr_graph.node_type(rr_gsb.get_chan_node(side_manager.get_side(), itrack))) ); + /* Only output port indicates a routing multiplexer */ + if (OUT_PORT != rr_gsb.get_chan_node_direction(side_manager.get_side(), itrack)) { + continue; + } + build_switch_block_interc_bitstream(bitstream_manager, sb_config_block, + module_manager, + circuit_lib, mux_lib, rr_graph, + device_annotation, routing_annotation, + rr_gsb, side_manager.get_side(), itrack); + } + } +} + +/******************************************************************** + * This function generates bitstream for a routing multiplexer + * in a Connection block + * This function will identify if a node indicates a routing multiplexer + * If not a routing multiplexer, no bitstream is needed here + * If yes, we will generate the bitstream for the routing multiplexer + *******************************************************************/ +static +void build_connection_block_mux_bitstream(BitstreamManager& bitstream_manager, + const ConfigBlockId& mux_mem_block, + const ModuleManager& module_manager, + const CircuitLibrary& circuit_lib, + const MuxLibrary& mux_lib, + const VprDeviceAnnotation& device_annotation, + const VprRoutingAnnotation& routing_annotation, + const RRGraph& rr_graph, + const RRNodeId& src_rr_node) { + + /* Find drive_rr_nodes*/ + size_t datapath_mux_size = rr_graph.node_fan_in(src_rr_node); + + /* Configuration bits for MUX*/ + int path_id = DEFAULT_PATH_ID; + int edge_index = 0; + for (const RREdgeId& edge : rr_graph.node_in_edges(src_rr_node)) { + RRNodeId driver_node = rr_graph.edge_src_node(edge); + if (routing_annotation.rr_node_net(driver_node) == routing_annotation.rr_node_net(src_rr_node)) { + path_id = edge_index; + break; + } + edge_index++; + } + + /* Ensure that our path id makes sense! */ + VTR_ASSERT( (DEFAULT_PATH_ID == path_id) + || ( (DEFAULT_PATH_ID < path_id) && (path_id < (int)datapath_mux_size) ) + ); + + + /* Find the circuit model id of the mux, we need its design technology which matters the bitstream generation */ + std::vector driver_switches = get_rr_graph_driver_switches(rr_graph, src_rr_node); + VTR_ASSERT(1 == driver_switches.size()); + CircuitModelId mux_model = device_annotation.rr_switch_circuit_model(driver_switches[0]); + + /* Generate bitstream depend on both technology and structure of this MUX */ + std::vector mux_bitstream = build_mux_bitstream(circuit_lib, mux_model, mux_lib, datapath_mux_size, path_id); + + /* Find the module in module manager and ensure the bitstream size matches! */ + std::string mem_module_name = generate_mux_subckt_name(circuit_lib, mux_model, datapath_mux_size, std::string(MEMORY_MODULE_POSTFIX)); + ModuleId mux_mem_module = module_manager.find_module(mem_module_name); + VTR_ASSERT (true == module_manager.valid_module_id(mux_mem_module)); + ModulePortId mux_mem_out_port_id = module_manager.find_module_port(mux_mem_module, generate_configuration_chain_data_out_name()); + VTR_ASSERT(mux_bitstream.size() == module_manager.module_port(mux_mem_module, mux_mem_out_port_id).get_width()); + + /* Add the bistream to the bitstream manager */ + for (const bool& bit : mux_bitstream) { + ConfigBitId config_bit = bitstream_manager.add_bit(bit); + /* Link the memory bits to the mux mem block */ + bitstream_manager.add_bit_to_block(mux_mem_block, config_bit); + } +} + + +/******************************************************************** + * This function generates bitstream for an interconnection, + * i.e., a routing multiplexer, in a Connection Block + * This function will identify if a node indicates a routing multiplexer + * If not a routing multiplexer, no bitstream is needed here + * If yes, we will generate the bitstream for the routing multiplexer + *******************************************************************/ +static +void build_connection_block_interc_bitstream(BitstreamManager& bitstream_manager, + const ConfigBlockId& cb_configurable_block, + const ModuleManager& module_manager, + const CircuitLibrary& circuit_lib, + const MuxLibrary& mux_lib, + const VprDeviceAnnotation& device_annotation, + const VprRoutingAnnotation& routing_annotation, + const RRGraph& rr_graph, + const RRGSB& rr_gsb, + const e_side& cb_ipin_side, + const size_t& ipin_index) { + + RRNodeId src_rr_node = rr_gsb.get_ipin_node(cb_ipin_side, ipin_index); + + /* Consider configurable edges only */ + std::vector driver_rr_nodes = get_rr_graph_configurable_driver_nodes(rr_graph, src_rr_node); + + if (1 == driver_rr_nodes.size()) { + /* No bitstream generation required by a special direct connection*/ + } else if (1 < driver_rr_nodes.size()) { + /* Create the block denoting the memory instances that drives this node in Switch Block */ + std::string mem_block_name = generate_cb_memory_instance_name(CONNECTION_BLOCK_MEM_INSTANCE_PREFIX, rr_graph.node_side(src_rr_node), ipin_index, std::string("")); + ConfigBlockId mux_mem_block = bitstream_manager.add_block(mem_block_name); + bitstream_manager.add_child_block(cb_configurable_block, mux_mem_block); + /* This is a routing multiplexer! Generate bitstream */ + build_connection_block_mux_bitstream(bitstream_manager, mux_mem_block, + module_manager, circuit_lib, mux_lib, + device_annotation, routing_annotation, + rr_graph, src_rr_node); + } /*Nothing should be done else*/ +} + +/******************************************************************** + * This function generates bitstream for a Connection Block + * and add it to the bitstream manager + * This function will spot all the routing multiplexers in a Connection Block + * using a simple but effective rule: + * The fan-in of each output node. + * If there are more than 2 fan-in, there is a routing multiplexer + * + * Note that the output nodes are the IPIN rr node in a Connection Block + * So, we will iterate over that. + *******************************************************************/ +static +void build_connection_block_bitstream(BitstreamManager& bitstream_manager, + const ConfigBlockId& cb_configurable_block, + const ModuleManager& module_manager, + const CircuitLibrary& circuit_lib, + const MuxLibrary& mux_lib, + const VprDeviceAnnotation& device_annotation, + const VprRoutingAnnotation& routing_annotation, + const RRGraph& rr_graph, + const RRGSB& rr_gsb, + const t_rr_type& cb_type) { + + /* Find routing multiplexers on the sides of a Connection block where IPIN nodes locate */ + std::vector cb_sides = rr_gsb.get_cb_ipin_sides(cb_type); + + for (size_t side = 0; side < cb_sides.size(); ++side) { + enum e_side cb_ipin_side = cb_sides[side]; + SideManager side_manager(cb_ipin_side); + for (size_t inode = 0; inode < rr_gsb.get_num_ipin_nodes(cb_ipin_side); ++inode) { + build_connection_block_interc_bitstream(bitstream_manager, cb_configurable_block, + module_manager, circuit_lib, mux_lib, + device_annotation, routing_annotation, + rr_graph, rr_gsb, + cb_ipin_side, inode); + } + } +} + +/******************************************************************** + * Create bitstream for a X-direction or Y-direction Connection Blocks + *******************************************************************/ +static +void build_connection_block_bitstreams(BitstreamManager& bitstream_manager, + const ConfigBlockId& top_configurable_block, + const ModuleManager& module_manager, + const CircuitLibrary& circuit_lib, + const MuxLibrary& mux_lib, + const VprDeviceAnnotation& device_annotation, + const VprRoutingAnnotation& routing_annotation, + const RRGraph& rr_graph, + const DeviceRRGSB& device_rr_gsb, + const t_rr_type& cb_type) { + + vtr::Point cb_range = device_rr_gsb.get_gsb_range(); + + for (size_t ix = 0; ix < cb_range.x(); ++ix) { + for (size_t iy = 0; iy < cb_range.y(); ++iy) { + const RRGSB& rr_gsb = device_rr_gsb.get_gsb(ix, iy); + /* Check if the connection block exists in the device! + * Some of them do NOT exist due to heterogeneous blocks (height > 1) + * We will skip those modules + */ + if (false == rr_gsb.is_cb_exist(cb_type)) { + continue; + } + /* Skip if the cb does not contain any configuration bits! */ + if (true == connection_block_contain_only_routing_tracks(rr_gsb, cb_type)) { + continue; + } + /* Create a block for the bitstream which corresponds to the Switch block */ + vtr::Point cb_coord(rr_gsb.get_cb_x(cb_type), rr_gsb.get_cb_y(cb_type)); + ConfigBlockId cb_configurable_block = bitstream_manager.add_block(generate_connection_block_module_name(cb_type, cb_coord)); + /* Set switch block as a child of top block */ + bitstream_manager.add_child_block(top_configurable_block, cb_configurable_block); + + build_connection_block_bitstream(bitstream_manager, cb_configurable_block, module_manager, + circuit_lib, mux_lib, + device_annotation, routing_annotation, + rr_graph, + rr_gsb, cb_type); + } + } +} + +/******************************************************************** + * Top-level function to create bitstream for global routing architecture + * Two major tasks: + * 1. Generate bitstreams for Switch Blocks + * 2. Generate bitstreams for both X-direction and Y-direction Connection Blocks + *******************************************************************/ +void build_routing_bitstream(BitstreamManager& bitstream_manager, + const ConfigBlockId& top_configurable_block, + const ModuleManager& module_manager, + const CircuitLibrary& circuit_lib, + const MuxLibrary& mux_lib, + const VprDeviceAnnotation& device_annotation, + const VprRoutingAnnotation& routing_annotation, + const RRGraph& rr_graph, + const DeviceRRGSB& device_rr_gsb) { + + /* Generate bitstream for each switch blocks + * To organize the bitstream in blocks, we create a block for each switch block + * and give names which are same as they are in top-level module managers + */ + VTR_LOG("Generating bitstream for Switch blocks..."); + vtr::Point sb_range = device_rr_gsb.get_gsb_range(); + for (size_t ix = 0; ix < sb_range.x(); ++ix) { + for (size_t iy = 0; iy < sb_range.y(); ++iy) { + const RRGSB& rr_gsb = device_rr_gsb.get_gsb(ix, iy); + /* Check if the switch block exists in the device! + * Some of them do NOT exist due to heterogeneous blocks (width > 1) + * We will skip those modules + */ + if (false == rr_gsb.is_sb_exist()) { + continue; + } + + /* Create a block for the bitstream which corresponds to the Switch block */ + vtr::Point sb_coord(rr_gsb.get_sb_x(), rr_gsb.get_sb_y()); + ConfigBlockId sb_configurable_block = bitstream_manager.add_block(generate_switch_block_module_name(sb_coord)); + /* Set switch block as a child of top block */ + bitstream_manager.add_child_block(top_configurable_block, sb_configurable_block); + + build_switch_block_bitstream(bitstream_manager, sb_configurable_block, module_manager, + circuit_lib, mux_lib, + device_annotation, routing_annotation, + rr_graph, + rr_gsb); + } + } + VTR_LOG("Done\n"); + + /* Generate bitstream for each connection blocks + * To organize the bitstream in blocks, we create a block for each connection block + * and give names which are same as they are in top-level module managers + */ + VTR_LOG("Generating bitstream for X-direction Connection blocks ..."); + + build_connection_block_bitstreams(bitstream_manager, top_configurable_block, module_manager, + circuit_lib, mux_lib, + device_annotation, routing_annotation, + rr_graph, + device_rr_gsb, CHANX); + VTR_LOG("Done\n"); + + VTR_LOG("Generating bitstream for Y-direction Connection blocks ..."); + + build_connection_block_bitstreams(bitstream_manager, top_configurable_block, module_manager, + circuit_lib, mux_lib, + device_annotation, routing_annotation, + rr_graph, + device_rr_gsb, CHANY); + VTR_LOG("Done"); + +} + +} /* end namespace openfpga */ diff --git a/openfpga/src/fpga_bitstream/build_routing_bitstream.h b/openfpga/src/fpga_bitstream/build_routing_bitstream.h new file mode 100644 index 000000000..2337601fe --- /dev/null +++ b/openfpga/src/fpga_bitstream/build_routing_bitstream.h @@ -0,0 +1,39 @@ +/******************************************************************** + * Header file for build_routing_bitstream.cpp + *******************************************************************/ +#ifndef BUILD_ROUTING_BITSTREAM_H +#define BUILD_ROUTING_BITSTREAM_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ +#include +#include "bitstream_manager.h" +#include "vpr_context.h" +#include "module_manager.h" +#include "circuit_library.h" +#include "mux_library.h" +#include "device_rr_gsb.h" +#include "vpr_device_annotation.h" +#include "vpr_routing_annotation.h" + +/******************************************************************** + * Function declaration + *******************************************************************/ + +/* begin namespace openfpga */ +namespace openfpga { + +void build_routing_bitstream(BitstreamManager& bitstream_manager, + const ConfigBlockId& top_configurable_block, + const ModuleManager& module_manager, + const CircuitLibrary& circuit_lib, + const MuxLibrary& mux_lib, + const VprDeviceAnnotation& device_annotation, + const VprRoutingAnnotation& routing_annotation, + const RRGraph& rr_graph, + const DeviceRRGSB& device_rr_gsb); + +} /* end namespace openfpga */ + +#endif diff --git a/openfpga/src/fpga_bitstream/mux_bitstream_constants.h b/openfpga/src/fpga_bitstream/mux_bitstream_constants.h new file mode 100644 index 000000000..73d707ad5 --- /dev/null +++ b/openfpga/src/fpga_bitstream/mux_bitstream_constants.h @@ -0,0 +1,15 @@ +#ifndef MUX_BITSTREAM_CONSTANTS_H +#define MUX_BITSTREAM_CONSTANTS_H + +/* begin namespace openfpga */ +namespace openfpga { + +/* Default path ID of a unused multiplexer */ +#define DEFAULT_PATH_ID -1 + +/* Default path ID of a unused multiplexer when there are no constant inputs*/ +#define DEFAULT_MUX_PATH_ID 0 + +} /* end namespace openfpga */ + +#endif