diff --git a/openfpga/src/base/openfpga_naming.cpp b/openfpga/src/base/openfpga_naming.cpp index d61405b24..84366b1ab 100644 --- a/openfpga/src/base/openfpga_naming.cpp +++ b/openfpga/src/base/openfpga_naming.cpp @@ -388,19 +388,32 @@ std::string generate_sb_module_track_port_name(const t_rr_type& chan_type, * Instead, we use the relative location of the pins in the context of routing modules * so that each module can be instanciated across the fabric * Even though, port direction must be provided! + * + * Upper_location: specify if an upper/lower prefix to be added. + * The location indicates where the bus port should be + * placed on the perimeter of the connection block + * - For X-directional CB: + * - upper is the left side + * - lower is the right side + * - For Y-directional CB: + * - upper is the bottom side + * - lower is the top side *********************************************************************/ std::string generate_cb_module_track_port_name(const t_rr_type& chan_type, - const PORTS& port_direction) { + const PORTS& port_direction, + const bool& upper_location) { /* Channel must be either CHANX or CHANY */ VTR_ASSERT( (CHANX == chan_type) || (CHANY == chan_type) ); /* Create a map between chan_type and module_prefix */ - std::map module_prefix_map; + std::map> module_prefix_map; /* TODO: use a constexpr string to replace the fixed name? */ - module_prefix_map[CHANX] = std::string("chanx"); - module_prefix_map[CHANY] = std::string("chany"); + module_prefix_map[CHANX][true] = std::string("chanx_left"); + module_prefix_map[CHANX][false] = std::string("chanx_right"); + module_prefix_map[CHANY][true] = std::string("chany_bottom"); + module_prefix_map[CHANY][false] = std::string("chany_top"); - std::string port_name = module_prefix_map[chan_type]; + std::string port_name = module_prefix_map[chan_type][upper_location]; port_name += std::string("_"); switch (port_direction) { diff --git a/openfpga/src/base/openfpga_naming.h b/openfpga/src/base/openfpga_naming.h index fc5f1f866..3f374b8e5 100644 --- a/openfpga/src/base/openfpga_naming.h +++ b/openfpga/src/base/openfpga_naming.h @@ -94,7 +94,8 @@ std::string generate_sb_module_track_port_name(const t_rr_type& chan_type, const PORTS& port_direction); std::string generate_cb_module_track_port_name(const t_rr_type& chan_type, - const PORTS& port_direction); + const PORTS& port_direction, + const bool& upper_location); std::string generate_routing_track_middle_output_port_name(const t_rr_type& chan_type, const vtr::Point& coordinate, diff --git a/openfpga/src/fabric/build_routing_module_utils.cpp b/openfpga/src/fabric/build_routing_module_utils.cpp index b341adbc0..320823ec2 100644 --- a/openfpga/src/fabric/build_routing_module_utils.cpp +++ b/openfpga/src/fabric/build_routing_module_utils.cpp @@ -148,10 +148,11 @@ ModulePinInfo find_connection_block_module_chan_port(const ModuleManager& module int chan_node_track_id = rr_gsb.get_cb_chan_node_index(cb_type, chan_rr_node); /* Create a port description for the middle output */ std::string input_port_name = generate_cb_module_track_port_name(cb_type, - IN_PORT); + IN_PORT, + 0 == chan_node_track_id % 2); /* Must find a valid port id in the Switch Block module */ input_port_info.first = module_manager.find_module_port(cb_module, input_port_name); - input_port_info.second = chan_node_track_id; + input_port_info.second = chan_node_track_id / 2; VTR_ASSERT(true == module_manager.valid_module_port_id(cb_module, input_port_info.first)); break; } diff --git a/openfpga/src/fabric/build_routing_modules.cpp b/openfpga/src/fabric/build_routing_modules.cpp index 7d8c85419..dda29cdc5 100644 --- a/openfpga/src/fabric/build_routing_modules.cpp +++ b/openfpga/src/fabric/build_routing_modules.cpp @@ -743,15 +743,47 @@ void build_connection_block_module(ModuleManager& module_manager, /* Add the input and output ports of routing tracks in the channel * Routing tracks pass through the connection blocks */ - std::string chan_input_port_name = generate_cb_module_track_port_name(cb_type, - IN_PORT); - BasicPort chan_input_port(chan_input_port_name, rr_gsb.get_cb_chan_width(cb_type)); - ModulePortId chan_input_port_id = module_manager.add_port(cb_module, chan_input_port, ModuleManager::MODULE_INPUT_PORT); + VTR_ASSERT(0 == rr_gsb.get_cb_chan_width(cb_type) % 2); - std::string chan_output_port_name = generate_cb_module_track_port_name(cb_type, - OUT_PORT); - BasicPort chan_output_port(chan_output_port_name, rr_gsb.get_cb_chan_width(cb_type)); - ModulePortId chan_output_port_id = module_manager.add_port(cb_module, chan_output_port, ModuleManager::MODULE_OUTPUT_PORT); + /* Upper input port: W/2 == 0 tracks */ + std::string chan_upper_input_port_name = generate_cb_module_track_port_name(cb_type, + IN_PORT, + true); + BasicPort chan_upper_input_port(chan_upper_input_port_name, + rr_gsb.get_cb_chan_width(cb_type) / 2); + ModulePortId chan_upper_input_port_id = module_manager.add_port(cb_module, + chan_upper_input_port, + ModuleManager::MODULE_INPUT_PORT); + + /* Lower input port: W/2 == 1 tracks */ + std::string chan_lower_input_port_name = generate_cb_module_track_port_name(cb_type, + IN_PORT, + false); + BasicPort chan_lower_input_port(chan_lower_input_port_name, + rr_gsb.get_cb_chan_width(cb_type) / 2); + ModulePortId chan_lower_input_port_id = module_manager.add_port(cb_module, + chan_lower_input_port, + ModuleManager::MODULE_INPUT_PORT); + + /* Upper output port: W/2 == 0 tracks */ + std::string chan_upper_output_port_name = generate_cb_module_track_port_name(cb_type, + OUT_PORT, + true); + BasicPort chan_upper_output_port(chan_upper_output_port_name, + rr_gsb.get_cb_chan_width(cb_type) / 2); + ModulePortId chan_upper_output_port_id = module_manager.add_port(cb_module, + chan_upper_output_port, + ModuleManager::MODULE_OUTPUT_PORT); + + /* Lower output port: W/2 == 1 tracks */ + std::string chan_lower_output_port_name = generate_cb_module_track_port_name(cb_type, + OUT_PORT, + false); + BasicPort chan_lower_output_port(chan_lower_output_port_name, + rr_gsb.get_cb_chan_width(cb_type) / 2); + ModulePortId chan_lower_output_port_id = module_manager.add_port(cb_module, + chan_lower_output_port, + ModuleManager::MODULE_OUTPUT_PORT); /* Add the input pins of grids, which are output ports of the connection block */ std::vector cb_ipin_sides = rr_gsb.get_cb_ipin_sides(cb_type); @@ -774,15 +806,24 @@ void build_connection_block_module(ModuleManager& module_manager, /* Generate short-wire connection for each routing track : * Each input port is short-wired to its output port * - * in[i] ----------> out[i] + * upper_in[i] ----------> lower_out[i] + * lower_in[i] <---------- upper_out[i] */ /* Create short-wires: input port ---> output port */ - VTR_ASSERT(chan_input_port.get_width() == chan_output_port.get_width()); - for (size_t pin_id = 0; pin_id < chan_input_port.pins().size(); ++pin_id) { - ModuleNetId net = create_module_source_pin_net(module_manager, cb_module, cb_module, 0, chan_input_port_id, chan_input_port.pins()[pin_id]); - module_manager.add_module_net_sink(cb_module, net, cb_module, 0, chan_output_port_id, chan_output_port.pins()[pin_id]); + VTR_ASSERT(chan_upper_input_port.get_width() == chan_lower_output_port.get_width()); + for (size_t pin_id = 0; pin_id < chan_upper_input_port.pins().size(); ++pin_id) { + ModuleNetId net = create_module_source_pin_net(module_manager, cb_module, cb_module, 0, chan_upper_input_port_id, chan_upper_input_port.pins()[pin_id]); + module_manager.add_module_net_sink(cb_module, net, cb_module, 0, chan_lower_output_port_id, chan_lower_output_port.pins()[pin_id]); /* Cache the module net */ - input_port_to_module_nets[ModulePinInfo(chan_input_port_id, chan_input_port.pins()[pin_id])] = net; + input_port_to_module_nets[ModulePinInfo(chan_upper_input_port_id, chan_upper_input_port.pins()[pin_id])] = net; + } + + VTR_ASSERT(chan_lower_input_port.get_width() == chan_upper_output_port.get_width()); + for (size_t pin_id = 0; pin_id < chan_lower_input_port.pins().size(); ++pin_id) { + ModuleNetId net = create_module_source_pin_net(module_manager, cb_module, cb_module, 0, chan_lower_input_port_id, chan_lower_input_port.pins()[pin_id]); + module_manager.add_module_net_sink(cb_module, net, cb_module, 0, chan_upper_output_port_id, chan_upper_output_port.pins()[pin_id]); + /* Cache the module net */ + input_port_to_module_nets[ModulePinInfo(chan_lower_input_port_id, chan_lower_input_port.pins()[pin_id])] = net; } /* Add sub modules of routing multiplexers or direct interconnect*/ diff --git a/openfpga/src/fabric/build_top_module_connection.cpp b/openfpga/src/fabric/build_top_module_connection.cpp index 960a1499b..4fc98f78f 100644 --- a/openfpga/src/fabric/build_top_module_connection.cpp +++ b/openfpga/src/fabric/build_top_module_connection.cpp @@ -570,8 +570,10 @@ void add_top_module_nets_connect_sb_and_cb(ModuleManager& module_manager, } else { VTR_ASSERT(IN_PORT == module_sb.get_chan_node_direction(side_manager.get_side(), itrack)); } + bool use_cb_upper_port = (TOP == side_manager.get_side()) || (RIGHT == side_manager.get_side()); std::string cb_port_name = generate_cb_module_track_port_name(cb_type, - cb_port_direction); + cb_port_direction, + use_cb_upper_port); ModulePortId cb_port_id = module_manager.find_module_port(cb_module_id, cb_port_name); VTR_ASSERT(true == module_manager.valid_module_port_id(cb_module_id, cb_port_id)); BasicPort cb_port = module_manager.module_port(cb_module_id, cb_port_id); @@ -582,10 +584,10 @@ void add_top_module_nets_connect_sb_and_cb(ModuleManager& module_manager, */ if (OUT_PORT == module_sb.get_chan_node_direction(side_manager.get_side(), itrack)) { ModuleNetId net = create_module_source_pin_net(module_manager, top_module, sb_module_id, sb_instance, sb_port_id, itrack / 2); - module_manager.add_module_net_sink(top_module, net, cb_module_id, cb_instance, cb_port_id, itrack); + module_manager.add_module_net_sink(top_module, net, cb_module_id, cb_instance, cb_port_id, itrack / 2); } else { VTR_ASSERT(IN_PORT == module_sb.get_chan_node_direction(side_manager.get_side(), itrack)); - ModuleNetId net = create_module_source_pin_net(module_manager, top_module, cb_module_id, cb_instance, cb_port_id, itrack); + ModuleNetId net = create_module_source_pin_net(module_manager, top_module, cb_module_id, cb_instance, cb_port_id, itrack / 2); module_manager.add_module_net_sink(top_module, net, sb_module_id, sb_instance, sb_port_id, itrack / 2); } } diff --git a/openfpga/src/fpga_sdc/analysis_sdc_routing_writer.cpp b/openfpga/src/fpga_sdc/analysis_sdc_routing_writer.cpp index 23e6d3b6e..22495d31a 100644 --- a/openfpga/src/fpga_sdc/analysis_sdc_routing_writer.cpp +++ b/openfpga/src/fpga_sdc/analysis_sdc_routing_writer.cpp @@ -76,13 +76,14 @@ void print_analysis_sdc_disable_cb_unused_resources(std::fstream& fp, /* Disable both input of the routing track if it is not used! */ std::string port_name = generate_cb_module_track_port_name(cb_type, - IN_PORT); + IN_PORT, + 0 == itrack % 2); /* Ensure we have this port in the module! */ ModulePortId module_port = module_manager.find_module_port(cb_module, port_name); VTR_ASSERT(true == module_manager.valid_module_port_id(cb_module, module_port)); BasicPort chan_port(module_manager.module_port(cb_module, module_port).get_name(), - itrack, itrack); + itrack / 2, itrack / 2); fp << "set_disable_timing "; fp << cb_instance_name << "/"; @@ -100,13 +101,14 @@ void print_analysis_sdc_disable_cb_unused_resources(std::fstream& fp, /* Disable both input of the routing track if it is not used! */ std::string port_name = generate_cb_module_track_port_name(cb_type, - OUT_PORT); + OUT_PORT, + 0 == itrack % 2); /* Ensure we have this port in the module! */ ModulePortId module_port = module_manager.find_module_port(cb_module, port_name); VTR_ASSERT(true == module_manager.valid_module_port_id(cb_module, module_port)); BasicPort chan_port(module_manager.module_port(cb_module, module_port).get_name(), - itrack, itrack); + itrack / 2, itrack / 2); fp << "set_disable_timing "; fp << cb_instance_name << "/"; @@ -183,7 +185,8 @@ void print_analysis_sdc_disable_cb_unused_resources(std::fstream& fp, /* Disable both input of the routing track if it is not used! */ std::string port_name = generate_cb_module_track_port_name(cb_type, - OUT_PORT); + OUT_PORT, + 0 == itrack % 2); /* Ensure we have this port in the module! */ ModulePortId module_port = module_manager.find_module_port(cb_module, port_name); @@ -193,7 +196,7 @@ void print_analysis_sdc_disable_cb_unused_resources(std::fstream& fp, disable_analysis_module_input_pin_net_sinks(fp, module_manager, cb_module, cb_instance_name, - module_port, itrack, + module_port, itrack / 2, mapped_atom_net, mux_instance_to_net_map); diff --git a/openfpga/src/fpga_sdc/pnr_sdc_routing_writer.cpp b/openfpga/src/fpga_sdc/pnr_sdc_routing_writer.cpp index 4c0cb1a07..2b4f232b7 100644 --- a/openfpga/src/fpga_sdc/pnr_sdc_routing_writer.cpp +++ b/openfpga/src/fpga_sdc/pnr_sdc_routing_writer.cpp @@ -436,17 +436,19 @@ void print_pnr_sdc_constrain_cb_timing(const std::string& sdc_dir, for (size_t itrack = 0; itrack < rr_gsb.get_cb_chan_width(cb_type); ++itrack) { /* Create a port description for the input */ std::string input_port_name = generate_cb_module_track_port_name(cb_type, - IN_PORT); + IN_PORT, + 0 == itrack % 2); ModulePortId input_port_id = module_manager.find_module_port(cb_module, input_port_name); BasicPort input_port(module_manager.module_port(cb_module, input_port_id).get_name(), - itrack, itrack); + itrack / 2, itrack / 2); /* Create a port description for the output */ std::string output_port_name = generate_cb_module_track_port_name(cb_type, - OUT_PORT); + OUT_PORT, + 0 == itrack % 2); ModulePortId output_port_id = module_manager.find_module_port(cb_module, output_port_name); BasicPort output_port(module_manager.module_port(cb_module, output_port_id).get_name(), - itrack, itrack); + itrack / 2, itrack / 2); /* Connection block routing segment ids for each track */ RRSegmentId segment_id = rr_gsb.get_chan_node_segment(rr_gsb.get_cb_chan_side(cb_type), itrack);