'''
'''
import csv
import math
import logging
from collections import OrderedDict
from typing import List
from xml.dom import minidom
import networkx as nx
import spydrnet as sdn
import svgwrite
from spydrnet_physical.util import ConnectPoint
from svgwrite.container import Group
DEFAULT_COLOR = " black"
logger = logging.getLogger('spydrnet_logs')
sdn.enable_file_logging(LOG_LEVEL='DEBUG')
[docs]class ConnectPointList:
''' This stores list of connection points '''
[docs] def __init__(self, sizex=None, sizey=None, point=None):
self.sizex = sizex
self.sizey = sizey
self._points: List[ConnectPoint] = []
self._cursor = []
self._cursor_state = True
if point:
self.add_connect_point(point)
@property
def points(self):
"Returns list of ConnectionPoints"
return self._points
@property
def cursor(self):
"Returns current location of cursor"
return self._cursor
@cursor.setter
def cursor(self, point):
'''
Cursor is placed at the specified point
Args:
point (int, int): (x,y) coordinates where cursor is to be placed
'''
self._cursor = point
return self._cursor
@property
def get_x(self):
" Returns location of cursor "
return self._cursor[0]
@property
def get_y(self):
''' returns y location of cursor '''
return self._cursor[1]
[docs] def set_cursor(self, x, y):
'''
Sets cursor at given x, y coordinate
Args:
x (int): point on the x-axis where cursor is to be placed
y (int): point on the y-axis where cursor is to be placed
Returns:
self: self ConnectionPointList object
'''
self._cursor = (x, y)
return self
[docs] def set_color(self, color):
'''
Set color to all the points in the connection list
Args:
color (str): Specify a color for connect point list e.g 'red', 'blue', 'green', etc.
'''
for each in self._points:
each.color = color
return self
[docs] def store_points(self, filename):
''' Stores all points and its attributes in csv format in the file '''
with open(filename, "w", encoding="UTF-8") as file_ptr:
file_ptr.write("# Generated using SpyDrNet-physical plugin\n")
file_ptr.write("# fr_x fr_y to_x to_y type\n")
file_ptr.write("= = "*10 + "\n")
for point in self.points:
file_ptr.write(str(point)+"\n")
[docs] def validate_connectivity(self):
"""
This fucntion checks following
* If there is any connection coming outside from range (0-sizex+1) or (0-sizey+1)
* If there is any redundant connections
"""
# Check if signal enter module multiple times
logger.info("Checking consistency of the connection file")
point: ConnectPoint
in_mapping = [[0 for _ in range(self.sizey+2)]
for _ in range(self.sizex+2)]
for point in self._points:
if point.to_x >= self.sizex+2:
logger.warning("Pointx out of range %d", point.to_x)
continue
if point.to_y >= self.sizey+2:
logger.warning("Pointy out of range %d", point.to_y)
continue
if in_mapping[point.to_x][point.to_y]:
logger.warning("Multiple input for instance (%d %d)",
*point.to_connection)
in_mapping[point.to_x][point.to_y] = 1
[docs] def load_points(self, filename, append=False, delimiter=" ", skiplines=3):
'''
Loads all points and its attributes from the given csv file
Format: from_x, from_y, to_x, to_y, level, color
'''
if not append:
_ = [self._points.pop(0) for _ in list(self._points)]
with open(filename, encoding="UTF-8") as pts_file:
spamreader = csv.reader(
pts_file, delimiter=delimiter, skipinitialspace=True)
_ = [next(spamreader) for _ in range(skiplines)]
for row in spamreader:
point = self.add_connection(*row[:4])
if "top" in row[-1]:
self.make_top_connection(point)
if "down" in row[-1]:
self.push_connection_down(point)
if "up" in row[-1]:
self.pull_connection_up(point)
[docs] def load_points_from_svg(self, filename, grid=6.9*2, group="markers", append=False,
same_color="black", down_color="red", up_color="green"):
'''
This method loads points from the SVG file.
enabling UI based designing of connection file.
'''
root = minidom.parse(filename)
if not append:
_ = [self._points.pop(0) for _ in list(self._points)]
x_grid = []
y_grid = []
for conn in root.getElementsByTagName("line"):
if "gridmarker" in conn.getAttribute('class'):
x1 = float(conn.getAttribute("x1"))
x2 = float(conn.getAttribute("x2"))
y1 = float(conn.getAttribute("y1"))
y2 = float(conn.getAttribute("y2"))
if y1 == y2:
y_grid.append(y1)
if x1 == x2:
x_grid.append(x1)
x_grid = sorted(x_grid)
y_grid = sorted(y_grid)
x_origin = x_grid[0]
y_origin = y_grid[0]
# x_grid= min([ abs(a-b) for a,b in zip(x_grid[:-1], x_grid[1:])])
# y_grid= min([ abs(a-b) for a,b in zip(y_grid[:-1], y_grid[1:])])
logger.debug("Found vertical markers at %s", x_grid)
logger.debug("Found horizontal markers at %s", y_grid)
x_grid = (max(x_grid)-min(x_grid))/(self.sizex)
y_grid = (max(y_grid)-min(y_grid))/(self.sizey)
logger.debug("Computed grid size is %.2f x %.2f", x_grid, y_grid)
logger.debug("origin %.2f x %.2f", x_origin, y_origin)
logger.debug(
"x1 x2 y1 y2")
for conn in root.getElementsByTagName("line"):
conn_class = conn.getAttribute('class')
if "connection" in conn_class:
x1 = 1 + \
math.floor(
((float(conn.getAttribute("x1")))-(x_origin))/x_grid)
x2 = 1 + \
math.floor(
((float(conn.getAttribute("x2")))-(x_origin))/x_grid)
y1 = 1 + \
math.floor(
((float(conn.getAttribute("y1")))-(y_origin))/y_grid)
y2 = 1 + \
math.floor(
((float(conn.getAttribute("y2")))-(y_origin))/y_grid)
if abs(y1 - y2) > abs(x1 - x2):
direction = "top" if y2 > y1 else "bottom"
elif abs(x1 - x2) > abs(y1 - y2):
direction = "right" if x2 > x1 else "left"
else:
logger.warning("Can not identify the connection direction %s [Dx %.2f, Dy %.2f]",
conn.attributes.items(), abs(x1 - x2), abs(y1 - y2))
continue
conn_type = "up" if "up" in conn_class else "down" \
if "down" in conn_class else "same"
points_info = f"{x1:8.2f}[{conn.getAttribute('x1'):8s}] " + \
f"{y1:8.2f}[{conn.getAttribute('y1'):8s}] " + \
f"{x2:8.2f}[{conn.getAttribute('x2'):8s}] " + \
f"{y2:8.2f}[{conn.getAttribute('y2'):8s}] " + \
f"-> {direction:>8s}[{conn_type:^4s}]"
try:
point = self.add_connection(abs(x1), self.sizey+1-abs(y1),
abs(x2), self.sizey+1-abs(y2))
logger.debug("%s Added", points_info)
except AssertionError as error:
logger.debug("%s Skipped (%8s, %8s) : %s", points_info,
conn.getAttribute("x1"), conn.getAttribute("y1"), error)
if "top" in conn_class:
self.make_top_connection(point)
if "down" in conn_class:
self.push_connection_down(point)
if "up" in conn_class:
self.pull_connection_up(point)
# raise NotImplementedError
[docs] def search_from_point(self, point):
'''
Search for connection going out of this point
Note: Returns the first point
Args:
point (tuple): Point to search
Returns:
ConnectionPoint:
'''
for pts in self._points:
if (pts.from_connection == point):
return pts
return None
[docs] def search_to_point(self, point):
'''
Search for connection coming into this point
Note: Returns the first point
Args:
point (tuple): Point to search
Returns:
ConnectionPoint:
'''
for pts in self._points:
if (pts.to_connection == point):
return pts
return None
[docs] def push_connection_down(self, point):
'''
Push given connection one-level down
'Push down' connection indicates that this connection is going down from
the current level
Args:
point (tuple): Connetion point to push down
Returns:
ConnectionPoint:
'''
if isinstance(point, tuple):
point = self.search_to_point(point)
point.level = "down"
return point
[docs] def pull_connection_up(self, point):
'''
Pull given connections one-level up
'Pull up' connection indicates that this connection is coming from
one level above this level
Args:
point (tuple): Connetion point to pull up
'''
if isinstance(point, tuple):
point = self.search_from_point(point)
point.level = "up"
return point
[docs] def make_top_connection(self, point):
'''
Make connection with the top layer
Args:
point (tuple): Connetion point to push down
Returns:
ConnectionPoint:
'''
if isinstance(point, tuple):
point = self.search_from_point(point)
point.level = "top"
return point
[docs] def reset_level(self, point):
'''
Resets the level of the connections
Args:
point (ConnectPoint): It is a ConnectPoint object
'''
assert isinstance(point, ConnectPoint), \
"point should be instance of ConnectPoint class not " + type(point)
point.level = "same"
[docs] def hold_cursor(self):
''' Holds the cursor at current position '''
self._cursor_state = False
[docs] def release_cursor(self):
''' Releases cursor and moves with each point addition '''
self._cursor_state = True
[docs] def flip(self, orientation="H"):
'''
Flips all the points horizontally or vertically
Args:
orientation: "H" or "V" (default="H")
'''
for point in self._points:
point.flip_connection(orientation)
return self
[docs] def sample_connections(self, max_distance=1):
'''
This method splits all the connections longer that ``max_distance`` to
at max ``max_distance`` length
Args:
max_distance (int): int to sample the connection at this value
'''
cursor_backup = self._cursor
for _, each in enumerate(self._points):
if each.distance > max_distance:
self._cursor = (each.from_x, each.from_y)
for i in range(max_distance, each.distance, max_distance):
if each.from_dir == "right":
self.move_x(value=max_distance)
elif each.from_dir == "left":
self.move_x(value=-1*max_distance)
if each.from_dir == "top":
self.move_y(value=max_distance)
elif each.from_dir == "bottom":
self.move_y(value=-1*max_distance)
each.from_x, each.from_y = self._cursor
self._cursor = cursor_backup
[docs] def crop_edges(self):
''' Crops all the connections going out of grid '''
for point in self._points:
for eachp in ('from_x', 'to_x'):
pt = getattr(point, eachp)
if pt < 0:
setattr(point, eachp, 0)
if pt > self.sizex:
setattr(point, eachp, 0)
for eachp in ('from_y', 'to_y'):
pt = getattr(point, eachp)
if pt < 0:
setattr(point, eachp, 0)
if pt > self.sizey:
setattr(point, eachp, 0)
def trim_borders(self):
for point in self._points[::-1]:
if (point.from_x > self.sizex) or (point.to_x > self.sizex) \
or (point.from_y > self.sizey) or (point.to_y > self.sizey):
self._points.remove(point)
if (point.from_x < 1) or (point.to_x < 1) \
or (point.from_y < 1) or (point.to_y < 1):
self._points.remove(point)
return self
[docs] def create_graph(self):
"""
Returns networksx object of the given connection point list
Returns:
nx.DiGraph: Returns networkx object of the given ConnectionPointList
"""
graph = nx.DiGraph(directed=True)
for conn in self._points:
from_node = "_%d_%d_" % conn.from_connection
to_node = "_%d_%d_" % conn.to_connection
graph.add_edge(from_node, to_node)
return graph
[docs] def merge(self, connectlist):
'''
Merges different ConnectPointList together into one Connect Point List
Args:
connectlist (ConnectPointList): provide with a ConnectPointList
Returns:
ConnectPointList: Return self object
'''
self._points.extend(connectlist.points)
return self
[docs] def scale(self, scale, anchor=(0, 0)):
'''
Scales the connect point list from an anchor position
Args:
scale: scale at which ConnectPointList is expanded
anchor: (x,y) coordinates of an anchor point
Returns:
ConnectPointList: Return self object
'''
for point in self._points:
point.scale_connection(scale, anchor)
return self
[docs] def translate(self, x, y):
'''
Moves the connect point list in x y coordinates
Args:
x(int): Steps in x-axis
y(int): Steps in y-axis
'''
for point in self._points:
point.translate_connection(x, y)
return self
[docs] def rotate(self, angle=0):
'''
Rotates the connect point list at right angles
Args:
angle (int): degree of rotations (0, 90, 180, 270, -90, -180, -270)
Returns:
ConnectPointList: Return self object
'''
angles = (0, 90, 180, 270, -90, -180, -270, 'CW', 'ACW')
assert angle in angles, "Supports only %s degree rotations" % angles
for point in self._points:
point.rotate_connection(angle, sizex=self.sizex, sizey=self.sizey)
return self
[docs] def add_next_point(self, x, y):
'''
Adds the next point in the connect point list
Args:
x: next point x-axis coordinate
y: next point y-axis coordinate
Returns:
ConnectPoint: Return new added point
'''
x_prev, y_prev = self._cursor
point = ConnectPoint(x_prev, y_prev, x, y)
self.add_connect_point(point)
self._update_cursor()
return point
[docs] def move_cursor_x(self, value=1):
'''
Places the cursor on the specified x coordinate without connection
Args:
value: steps cursor moves in the x-axis
'''
self._cursor = self._cursor[0]+value, self._cursor[1]
[docs] def move_cursor_y(self, value=1):
'''
Places the cursor on the specified y coordinate without connection
Args:
value: steps cursor moves in the y-axis
'''
self._cursor = self._cursor[0], self._cursor[1]+value
[docs] def move_x(self, value=1, steps=1, color=DEFAULT_COLOR):
''' Moves cursor in x direction by specified steps times by specified value
Args:
value: specified value by which cursor moves in the x-axis
steps: times cursor is moved
color: specify the color of this connection e.g red, blue, green, etc.
Returns:
ConnectPointList: Return self object
'''
x_prev, y_prev = self._cursor
for _ in range(steps):
point = ConnectPoint(x_prev, y_prev, x_prev+value, y_prev)
point.color = color
self.add_connect_point(point)
x_prev, y_prev = (x_prev+value, y_prev)
self._update_cursor()
return self
[docs] def move_y(self, value=1, steps=1, color=DEFAULT_COLOR):
'''
Moves cursor in y direction by specified steps times by specified value
Args:
value: specified value by which cursor moves in the y-axis
steps: times cursor is moved
color: specify the color of this connection e.g red, blue, green, etc.
Returns:
self: return self object
'''
x_prev, y_prev = self._cursor
for _ in range(steps):
point = ConnectPoint(x_prev, y_prev, x_prev, y_prev+value)
point.color = color
self.add_connect_point(point)
x_prev, y_prev = (x_prev, y_prev+value)
self._update_cursor()
return self
def _update_cursor(self):
if self._cursor_state:
self._cursor = self._points[-1].to_connection
return self._cursor
def __str__(self):
lines = ""
for p in self._points:
lines += str(p)
lines += "\n"
return lines
[docs] def add_connect_point(self, point):
'''
Adds a connect point in the connect point list
Args:
point (ConnectPoint): It is a cConnectPoint object
Returns:
ConnectPoint: Returns new ConnectPoint
'''
assert isinstance(point, ConnectPoint)
self._points.append(point)
self._update_cursor()
return point
[docs] def add_connection(self, from_x, from_y, to_x, to_y):
'''
Creates a new connection at the given from and to points
and add it to the connect point list
Args:
from_x (int): point on x coordinate from which connection starts
from_y (int): point on y coordinate from which connection starts
to_x (int): point on x coordinate where connection ends
to_y (int): point on y coordinate where connection ends
Returns:
ConnectionPoint: New ConnectionPoint object
'''
point = ConnectPoint(from_x, from_y, to_x, to_y)
self._points.append(point)
self._update_cursor()
return point
[docs] def render_pattern(self, scale=20):
'''
This renderes connection points list in a SVG format
Args:
connect (list): collection connection pattern
returns:
str(str): return svg string
'''
sizex = max([max(x1, x2) for x1, y1, x2, y2 in self._points])+1
sizey = max([max(y1, y2) for x1, y1, x2, y2 in self._points])+1
width = sizex*scale
height = sizey*scale
x_offset = 0
y_offset = -1*height
dwg = svgwrite.Drawing("_render.svg", size=(width, height))
dwg.viewbox(x_offset, y_offset, width, height)
dwgMarker = dwg.add(Group(id="markers", transform="scale(1,-1)"))
dwgMain = dwg.add(Group(id="main", transform="scale(1,-1)"))
# Add arrow marker
dir_marker = dwg.marker(refX="30", refY="30",
viewBox="0 0 120 120",
markerUnits="strokeWidth",
markerWidth="5", markerHeight="10", orient="auto")
dir_marker.add(dwg.path(d="M 0 0 L 60 30 L 0 60 z", fill="blue"))
dwg.defs.add(dir_marker)
# Add down connection marker
down_conn = dwg.marker(viewBox="-15 -15 30 30",
markerUnits="strokeWidth",
markerWidth="5", markerHeight="10", orient="auto")
down_conn.add(dwg.rect(insert=(-10, -10), size=(20, 20), fill="green"))
down_conn.add(dwg.path(d="M 8 0 L -8 8 L -8 -8 z", fill="blue"))
dwg.defs.add(down_conn)
# Add up conenction marker
up_conn = dwg.marker(viewBox="-15 -15 30 30",
markerUnits="strokeWidth",
markerWidth="5", markerHeight="10", orient="auto")
up_conn.add(dwg.rect(insert=(-10, -10), size=(20, 20), fill="green"))
up_conn.add(dwg.path(d="M 8 0 L -8 8 L -8 -8 z", fill="blue"))
dwg.defs.add(up_conn)
# Top connection marker
top_marker = dwg.marker(viewBox="-15 -15 30 30",
markerUnits="strokeWidth",
markerWidth="5",
markerHeight="10",
orient="auto")
top_marker.add(dwg.line(start=(0, -15), end=(0, 15),
stroke_width="5px", stroke="red"))
dwg.defs.add(top_marker)
dwg.defs.add(dwg.style("""
text{font-family: Lato;}
span{text-anchor: "middle"; alignment_baseline: "middle"}
.gridLabels{fill: grey;font-style: italic;font-weight: 900}
.gridmarker{stroke:red; stroke-width:0.2; opacity: 0.7;}
""" + f"""
.connection{{ opacity: 0.5;
marker-end:url(#{dir_marker.get_id()});
stroke-width:1.2;}}
.down{{stroke-dasharray: 2;
marker-end:url(#{up_conn.get_id()});}}
.up{{stroke-dasharray: 2;
marker-start:url(#{down_conn.get_id()});}}
.top{{stroke-dasharray: 2;
marker-start:url(#{top_marker.get_id()});}}
.buffer{{ filter: hue-rotate(90deg);
stroke-width:2; stroke-dasharray:1;}}
"""))
for conn in self._points:
conn_new = conn*scale
buffer = " buffer" if conn.buffer else ""
dwgMain.add(dwg.line(start=tuple(map(round, conn_new.from_connection)),
end=tuple(map(round, conn_new.to_connection)),
stroke=conn.color,
class_=f"connection {conn.level}{buffer}"))
return dwg
[docs] def get_reference(self, netlist, x, y):
'''
Return reference for the given tile location
'''
inst = self.get_top_instance(netlist, x, y)
return inst.reference.name if isinstance(inst, sdn.Instance) else inst
[docs] def get_top_instance(self, netlist: sdn.Netlist, x, y):
'''
Return reference for the given tile location
Returns:
sdn.Instance: Returns SpyDrNet instance
'''
if 0 in (x, y):
return "top"
instance_name = self.get_top_instance_name(x, y)
try:
return next(netlist.top_instance.reference.get_instances(instance_name))
except StopIteration:
logger.exception("Instance not found %s", instance_name)
[docs] def get_top_instance_name(self, x, y):
'''
Returns the instance from top_level design
Returns:
str: Instance name
'''
return "PlaceholderModule"
[docs] def print_port_stat(self, netlist, filename=None):
'''
This print ports generation statistics
'''
stat = self.show_stats(netlist)
output = []
format_str = "{:25s} | {:>3} {:>3} {:>3} {:>3} | {:>3} {:>3} {:>3} {:>3}"
default = {
"left": 0, "right": 0, "top": 0, "bottom": 0
}
output.append("= "*32)
output.append("{:25s} | {:^15} | {:^15}".format('Module', "In", "Out"))
output.append(format_str.format('Module',
"L", "R", "T", "B",
"L", "R", "T", "B"))
output.append("= "*32)
for module, mstat in stat.items():
output.append(format_str.format(
module,
mstat.get("in", default)["left"] or '-',
mstat.get("in", default)["right"] or '-',
mstat.get("in", default)["top"] or '-',
mstat.get("in", default)["bottom"] or '-',
mstat.get("out", default)["left"] or '-',
mstat.get("out", default)["right"] or '-',
mstat.get("out", default)["top"] or '-',
mstat.get("out", default)["bottom"] or '-'))
if filename:
with open(filename, "w", encoding="UTF-8") as fp:
fp.write("\n".join(output))
return output
[docs] def show_stats(self, netlist):
'''
Extracts the connectivity statistics for port and connection creation
'''
mstat = {}
for point in self._points:
if point.level in ["same", "down"]:
from_conn = self.get_reference(netlist, *point.from_connection)
mstat[from_conn] = mstat.get(from_conn, {})
mstat[from_conn]["out"] = mstat[from_conn].get(
"out", {"left": 0, "right": 0, "top": 0, "bottom": 0})
mstat[from_conn]["out"][point.direction(reverse=True)] += 1
if point.level in ["same", "up", "top"]:
to_conn = self.get_reference(netlist, *point.to_connection)
mstat[to_conn] = mstat.get(to_conn, {})
mstat[to_conn]["in"] = mstat[to_conn].get(
"in", {"left": 0, "right": 0, "top": 0, "bottom": 0})
mstat[to_conn]["in"][point.direction(reverse=False)] += 1
return OrderedDict((module, mstat[module]) for module in sorted(mstat))
[docs] def create_ft_ports(self, netlist: sdn.Netlist, port_name: str, cable: sdn.Cable):
'''
Create feedthrough port on the given module
Args:
netlist (Netlist): netlist
port (str): port name on each module
'''
for m_name, values in self.show_stats(netlist).items():
if m_name == "top":
continue
# Get current module
module: sdn.Definition = next(netlist.get_definitions(m_name))
# Get the signal port if it exist in the cirrect module
port: sdn.Port = next(module.get_ports(port_name), None)
# Create input ports on the module
prev_cable = None
# rotate anti-clockwise and create input connections
for inp in [k for k, v in values.get("in", {}).items() if v > 0]:
module.create_port(f"{port_name}_{inp}_in",
pins=cable.size, direction=sdn.IN)
cable = module.create_cable(f"{port_name}_{inp}_in",
wires=cable.size)
if prev_cable:
prev_cable.assign_cable(cable)
prev_cable = cable
# if the port exist (which means signal is used in this port)
# Create assignement statement fo the signal
signal_net = prev_cable
if prev_cable and port:
prev_cable.assign_cable(next(port.get_cables()))
signal_net = next(port.get_cables())
prev_cable = None
# rotate clockwise and create output connections
for outp in [k for k, v in values.get("out", {}).items() if v > 0][::-1]:
module.create_port(f"{port_name}_{outp}_out",
pins=cable.size, direction=sdn.OUT)
cable = module.create_cable(f"{port_name}_{outp}_out",
wires=cable.size)
if prev_cable:
cable.assign_cable(prev_cable)
prev_cable = cable
if prev_cable:
signal_net.assign_cable(prev_cable)
if port:
module.remove_port(port)
[docs] def create_ft_connection(self, netlist: sdn.Netlist, signal_cable: sdn.Instance,
down_port=None, up_port=None, top_cable=None):
''' Performs top level connection using connection file
Args:
netlist(sdn.Netlist): Top level netlist
signal_cable(str): Current level signal port
down_port(str) : Name of down level port
'''
signal = signal_cable.name
cable = netlist.top_instance.reference.create_cable(signal+"_ft")
for point in self._points:
logger.debug("Evaluating Point %s", point)
if point.level == "up":
continue
w = cable.create_wire()
assign_name = f"{signal}_{point.to_x}_{point.to_y}_top_assign"
if point.level == "top":
top_cable.assign_cable(cable,
upper=len(cable.wires),
lower=len(cable.wires)-1,
assign_instance_name=assign_name)
elif (0 in point.from_connection) or \
(self.sizex+1 == point.from_connection[0]) or \
(self.sizey+1 == point.from_connection[1]):
signal_cable.assign_cable(cable,
upper=w.get_index,
lower=w.get_index,
assign_instance_name=assign_name)
else:
inst = self.get_top_instance(netlist, *point.from_connection)
port_name = f"{signal}_{point.from_dir}_out"
try:
w.connect_pin(next(inst.get_port_pins(port_name)))
except AssertionError:
logger.warning("%s -> %s", inst.name,
next(inst.get_port_pins(port_name)).port.name)
w = next(inst.get_port_pins(port_name)).wire
if 0 in point.to_connection or \
(self.sizex+1 == point.to_connection[0]) or \
(self.sizey+1 == point.to_connection[1]):
signal_cable.assign_cable(
cable, upper=w.get_index, lower=w.get_index,
assign_instance_name=assign_name)
else:
inst = self.get_top_instance(netlist, *point.to_connection)
if point.level in ["same", "down"]:
assert signal, "Singal is not defined for %s connection" % point.level
port_name = {
"same": f"{signal}_{point.to_dir}_in",
"top": f"{signal}_{point.to_dir}_in",
"down": f"{down_port}_{point.to_dir}_in"}[point.level]
logger.debug("Connecting to pin %s", port_name)
w.connect_pin(next(inst.get_port_pins(port_name)))
# If the cable does not contain any wire remove it
if len(cable.wires) == 0:
netlist.top_instance.reference.remove_cable(cable)
[docs] def print_instance_grid_map(self):
""" Prints mapping beetween grid cordinates and top level instances """
for y in range(self.sizey, 0, -1):
for x in range(1, self.sizex+1):
print(f"{self.get_top_instance_name(x, y):15}", end=" ")
print("")
[docs] def print_reference_grid_map(self, netlist: sdn.Netlist):
""" Prints mapping beetween grid cordinates and top level instance refereneces """
for y in range(self.sizey, 0, -1):
for x in range(1, self.sizex+1):
print(f"{self.get_reference(netlist, x, y):15}", end=" ")
print("")
def __iter__(self):
yield from self._points
[docs] def short_through(self, through_point):
'''
Short all the incoming connections to this point with outgoing connections
Note: Connects the last found incoming and outgoing point in the list
Args:
through_point (tuple): point to short through
'''
incoming = None
outgoing = None
for point in self._points:
if point.from_connection == through_point:
outgoing = point
if point.to_connection == through_point:
incoming = point
if incoming and outgoing:
break
assert isinstance(
incoming, ConnectPoint), "Incoming connection not found"
assert isinstance(
outgoing, ConnectPoint), "Outgoing connection not found"
incoming.to_x, incoming.to_y = outgoing.to_connection
self._points.remove(outgoing)