blob: b32a2004cce8ed2f72e80bccf3740392c700ea5e [file] [log] [blame]
#include "clock_connection_builders.h"
#include "globals.h"
#include "rr_graph2.h"
#include "vtr_assert.h"
#include "vtr_log.h"
#include "vtr_error.h"
#include <random>
#include <math.h>
/*
* RoutingToClockConnection (setters)
*/
void RoutingToClockConnection::set_clock_name_to_connect_to(std::string clock_name) {
clock_to_connect_to = clock_name;
}
void RoutingToClockConnection::set_clock_switch_point_name(std::string clock_switch_point_name) {
switch_point_name = clock_switch_point_name;
}
void RoutingToClockConnection::set_switch_location(int x, int y) {
switch_location.x = x;
switch_location.y = y;
}
void RoutingToClockConnection::set_switch(int rr_switch_index) {
rr_switch_idx = rr_switch_index;
}
void RoutingToClockConnection::set_fc_val(float fc_val) {
fc = fc_val;
}
/*
* RoutingToClockConnection (member functions)
*/
void RoutingToClockConnection::create_switches(const ClockRRGraphBuilder& clock_graph) {
// Initialize random seed
// Must be done durring every call inorder for restored rr_graphs after a binary
// search to be consistant
std::srand(seed);
auto& device_ctx = g_vpr_ctx.mutable_device();
auto& rr_nodes = device_ctx.rr_nodes;
auto& rr_node_indices = device_ctx.rr_node_indices;
// rr_node indices for x and y channel routing wires and clock wires to connect to
auto x_wire_indices = get_rr_node_chan_wires_at_location(
rr_node_indices, CHANX, switch_location.x, switch_location.y);
auto y_wire_indices = get_rr_node_chan_wires_at_location(
rr_node_indices, CHANY, switch_location.x, switch_location.y);
auto clock_indices = clock_graph.get_rr_node_indices_at_switch_location(
clock_to_connect_to, switch_point_name, switch_location.x, switch_location.y);
for (auto clock_index : clock_indices) {
// Select wires to connect to at random
std::random_shuffle(x_wire_indices.begin(), x_wire_indices.end());
std::random_shuffle(y_wire_indices.begin(), y_wire_indices.end());
// Connect to x-channel wires
unsigned num_wires_x = x_wire_indices.size() * fc;
for (size_t i = 0; i < num_wires_x; i++) {
rr_nodes[x_wire_indices[i]].add_edge(clock_index, rr_switch_idx);
}
// Connect to y-channel wires
unsigned num_wires_y = y_wire_indices.size() * fc;
for (size_t i = 0; i < num_wires_y; i++) {
rr_nodes[y_wire_indices[i]].add_edge(clock_index, rr_switch_idx);
}
}
}
/*
* ClockToClockConneciton (setters)
*/
void ClockToClockConneciton::set_from_clock_name(std::string clock_name) {
from_clock = clock_name;
}
void ClockToClockConneciton::set_from_clock_switch_point_name(std::string switch_point_name) {
from_switch = switch_point_name;
}
void ClockToClockConneciton::set_to_clock_name(std::string clock_name) {
to_clock = clock_name;
}
void ClockToClockConneciton::set_to_clock_switch_point_name(std::string switch_point_name) {
to_switch = switch_point_name;
}
void ClockToClockConneciton::set_switch(int rr_switch_index) {
rr_switch_idx = rr_switch_index;
}
void ClockToClockConneciton::set_fc_val(float fc_val) {
fc = fc_val;
}
/*
* ClockToClockConneciton (member functions)
*/
void ClockToClockConneciton::create_switches(const ClockRRGraphBuilder& clock_graph) {
auto& device_ctx = g_vpr_ctx.mutable_device();
auto& grid = device_ctx.grid;
auto& rr_nodes = device_ctx.rr_nodes;
auto to_locations = clock_graph.get_switch_locations(to_clock, to_switch);
for (auto location : to_locations) {
auto x = location.first;
auto y = location.second;
auto to_rr_node_indices = clock_graph.get_rr_node_indices_at_switch_location(
to_clock,
to_switch,
x,
y);
// boundry conditions:
// y at gird height and height -1 connections share the same drive point
if (y == int(grid.height() - 2)) {
y = y - 1;
}
// y at 0 and y at 1 share the same drive point
if (y == 0) {
y = 1;
}
auto from_rr_node_indices = clock_graph.get_rr_node_indices_at_switch_location(
from_clock,
from_switch,
x,
y);
auto from_itter = from_rr_node_indices.begin();
size_t num_connections = ceil(from_rr_node_indices.size() * fc);
// Create a one to one connection from each chanx wire to the chany wire
// or vice versa. If there are more chanx wire than chany wire or vice versa
// then wrap around and start a one to one connection starting with the first node.
// This ensures that each wire gets a connection.
for (auto to_index : to_rr_node_indices) {
for (size_t i = 0; i < num_connections; i++) {
if (from_itter == from_rr_node_indices.end()) {
from_itter = from_rr_node_indices.begin();
}
rr_nodes[*from_itter].add_edge(to_index, rr_switch_idx);
from_itter++;
}
}
}
}
/*
* ClockToPinsConnection (setters)
*/
void ClockToPinsConnection::set_clock_name_to_connect_from(std::string clock_name) {
clock_to_connect_from = clock_name;
}
void ClockToPinsConnection::set_clock_switch_point_name(
std::string connection_switch_point_name) {
switch_point_name = connection_switch_point_name;
}
void ClockToPinsConnection::set_switch(int rr_switch_index) {
rr_switch_idx = rr_switch_index;
}
void ClockToPinsConnection::set_fc_val(float fc_val) {
fc = fc_val;
}
/*
* ClockToPinsConnection (member functions)
*/
void ClockToPinsConnection::create_switches(const ClockRRGraphBuilder& clock_graph) {
auto& device_ctx = g_vpr_ctx.mutable_device();
auto& rr_nodes = device_ctx.rr_nodes;
auto& rr_node_indices = device_ctx.rr_node_indices;
auto& grid = device_ctx.grid;
for (size_t x = 0; x < grid.width(); x++) {
for (size_t y = 0; y < grid.height(); y++) {
//Avoid boundry
if ((y == 0 && x == 0) || (x == grid.width() - 1 && y == grid.height() - 1)) {
continue;
}
auto type = grid[x][y].type;
auto width_offset = grid[x][y].width_offset;
auto height_offset = grid[x][y].height_offset;
// Ignore gird locations that do not have blocks
if (!logical_block_type(type)->pb_type) {
continue;
}
for (e_side side : SIDES) {
//Don't connect pins which are not adjacent to channels around the perimeter
if ((x == 0 && side != RIGHT) || (x == grid.width() - 1 && side != LEFT) || (y == 0 && side != TOP) || (y == grid.height() - 1 && side != BOTTOM)) {
continue;
}
for (auto clock_pin_idx : type->get_clock_pins_indices()) {
//Can't do anything if pin isn't at this location
if (0 == type->pinloc[width_offset][height_offset][side][clock_pin_idx]) {
continue;
}
//Adjust boundry connections (TODO: revisist if chany connections)
int clock_x_offset = 0;
int clock_y_offset = 0;
if (x == 0) {
clock_x_offset = 1; // chanx clock always starts at 1 offset
clock_y_offset = -1; // pick the chanx below the block
} else if (x == grid.width() - 1) {
clock_x_offset = -1; // chanx clock always ends at 1 offset
clock_y_offset = -1; // pick the chanx below the block
} else if (y == 0) {
clock_y_offset = 0; // pick chanx above the block, no offset needed
} else {
clock_y_offset = -1; // pick the chanx below the block
}
auto clock_pin_node_idx = get_rr_node_index(
rr_node_indices,
x,
y,
IPIN,
clock_pin_idx,
side);
auto clock_network_indices = clock_graph.get_rr_node_indices_at_switch_location(
clock_to_connect_from,
switch_point_name,
x + clock_x_offset,
y + clock_y_offset);
//Create edges depending on Fc
for (size_t i = 0; i < clock_network_indices.size() * fc; i++) {
rr_nodes[clock_network_indices[i]].add_edge(clock_pin_node_idx, rr_switch_idx);
}
}
}
}
}
}