Merge branch 'dev' into wlbuffer

This commit is contained in:
mrg
2020-09-10 13:05:14 -07:00
63 changed files with 639 additions and 935 deletions
+130
View File
@@ -12,6 +12,8 @@ import debug
from vector import vector
import tech
import math
import copy
import numpy as np
from globals import OPTS
from utils import round_to_grid
@@ -269,6 +271,134 @@ class instance(geometry):
p.transform(self.offset, self.mirror, self.rotate)
new_pins.append(p)
return new_pins
def calculate_transform(self, node):
#set up the rotation matrix
angle = math.radians(float(node.rotate))
mRotate = np.array([[math.cos(angle),-math.sin(angle),0.0],
[math.sin(angle),math.cos(angle),0.0],
[0.0,0.0,1.0]])
#set up translation matrix
translateX = float(node.offset[0])
translateY = float(node.offset[1])
mTranslate = np.array([[1.0,0.0,translateX],
[0.0,1.0,translateY],
[0.0,0.0,1.0]])
#set up the scale matrix (handles mirror X)
scaleX = 1.0
if(node.mirror == 'MX'):
scaleY = -1.0
else:
scaleY = 1.0
mScale = np.array([[scaleX,0.0,0.0],
[0.0,scaleY,0.0],
[0.0,0.0,1.0]])
return (mRotate, mScale, mTranslate)
def apply_transform(self, mtransforms, uVector, vVector, origin):
origin = np.dot(mtransforms[0], origin) #rotate
uVector = np.dot(mtransforms[0], uVector) #rotate
vVector = np.dot(mtransforms[0], vVector) #rotate
origin = np.dot(mtransforms[1], origin) #scale
uVector = np.dot(mtransforms[1], uVector) #scale
vVector = np.dot(mtransforms[1], vVector) #scale
origin = np.dot(mtransforms[2], origin)
return(uVector, vVector, origin)
def apply_path_transform(self, path):
uVector = np.array([[1.0],[0.0],[0.0]])
vVector = np.array([[0.0],[1.0],[0.0]])
origin = np.array([[0.0],[0.0],[1.0]])
while(path):
instance = path.pop(-1)
mtransforms = self.calculate_transform(instance)
(uVector, vVector, origin) = self.apply_transform(mtransforms, uVector, vVector, origin)
return (uVector, vVector, origin)
def reverse_transformation_bitcell(self, cell_name):
path = [] # path currently follwed in bitcell search
cell_paths = [] # saved paths to bitcells
origin_offsets = [] # cell to bank offset
Q_offsets = [] # Q to cell offet
Q_bar_offsets = [] # Q_bar to cell offset
bl_offsets = [] # bl to cell offset
br_offsets = [] # br to cell offset
bl_meta = [] # bl offset metadata (row,col,name)
br_meta = [] #br offset metadata (row,col,name)
def walk_subtree(node):
path.append(node)
if node.mod.name == cell_name:
cell_paths.append(copy.copy(path))
inst_name = path[-1].name
# get the row and col names from the path
row = int(path[-1].name.split('_')[-2][1:])
col = int(path[-1].name.split('_')[-1][1:])
cell_bl_meta = []
cell_br_meta = []
normalized_storage_nets = node.mod.get_normalized_storage_nets_offset()
(normalized_bl_offsets, normalized_br_offsets, bl_names, br_names) = node.mod.get_normalized_bitline_offset()
for offset in range(len(normalized_bl_offsets)):
for port in range(len(bl_names)):
cell_bl_meta.append([bl_names[offset], row, col, port])
for offset in range(len(normalized_br_offsets)):
for port in range(len(br_names)):
cell_br_meta.append([br_names[offset], row, col, port])
Q_x = normalized_storage_nets[0][0]
Q_y = normalized_storage_nets[0][1]
Q_bar_x = normalized_storage_nets[1][0]
Q_bar_y = normalized_storage_nets[1][1]
if node.mirror == 'MX':
Q_y = -1 * Q_y
Q_bar_y = -1 * Q_bar_y
for pair in range(len(normalized_bl_offsets)):
normalized_bl_offsets[pair] = (normalized_bl_offsets[pair][0],
-1 * normalized_bl_offsets[pair][1])
for pair in range(len(normalized_br_offsets)):
normalized_br_offsets[pair] = (normalized_br_offsets[pair][0],
-1 * normalized_br_offsets[pair][1])
Q_offsets.append([Q_x, Q_y])
Q_bar_offsets.append([Q_bar_x, Q_bar_y])
bl_offsets.append(normalized_bl_offsets)
br_offsets.append(normalized_br_offsets)
bl_meta.append(cell_bl_meta)
br_meta.append(cell_br_meta)
elif node.mod.insts is not []:
for instance in node.mod.insts:
walk_subtree(instance)
path.pop(-1)
walk_subtree(self)
for path in cell_paths:
vector_spaces = self.apply_path_transform(path)
origin = vector_spaces[2]
origin_offsets.append([origin[0], origin[1]])
return(origin_offsets, Q_offsets, Q_bar_offsets, bl_offsets, br_offsets, bl_meta, br_meta)
def __str__(self):
""" override print function output """
-56
View File
@@ -177,62 +177,6 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout):
name_dict[si_port.lower()] = mod_info
subinst.mod.build_names(name_dict, subinst_name, subinst_ports)
def find_aliases(self, inst_name, port_nets, path_nets, alias, alias_mod, exclusion_set=None):
"""Given a list of nets, will compare the internal alias of a mod to determine
if the nets have a connection to this mod's net (but not inst).
"""
if not exclusion_set:
exclusion_set = set()
try:
self.name_dict
except AttributeError:
self.name_dict = {}
self.build_names(self.name_dict, inst_name, port_nets)
aliases = []
for net in path_nets:
net = net.lower()
int_net = self.name_dict[net]['int_net']
int_mod = self.name_dict[net]['mod']
if int_mod.is_net_alias(int_net, alias, alias_mod, exclusion_set):
aliases.append(net)
return aliases
def is_net_alias(self, known_net, net_alias, mod, exclusion_set):
"""Checks if the alias_net in input mod is the same as the input net for this mod (self)."""
if self in exclusion_set:
return False
# Check ports of this mod
for pin in self.pins:
if self.is_net_alias_name_check(known_net, pin, net_alias, mod):
return True
# Check connections of all other subinsts
mod_set = set()
for subinst, inst_conns in zip(self.insts, self.conns):
for inst_conn, mod_pin in zip(inst_conns, subinst.mod.pins):
if self.is_net_alias_name_check(known_net, inst_conn, net_alias, mod):
return True
elif inst_conn.lower() == known_net.lower() and subinst.mod not in mod_set:
if subinst.mod.is_net_alias(mod_pin, net_alias, mod, exclusion_set):
return True
mod_set.add(subinst.mod)
return False
def is_net_alias_name_check(self, parent_net, child_net, alias_net, mod):
"""Utility function for checking single net alias."""
return self == mod and \
child_net.lower() == alias_net.lower() and \
parent_net.lower() == alias_net.lower()
def get_mod_net(self, parent_net, child_inst, child_conns):
"""
Given an instance and net, returns the internal net in the mod
corresponding to input net.
"""
for conn, pin in zip(child_conns, child_inst.mod.pins):
if parent_net.lower() == conn.lower():
return pin
return None
def translate_nets(self, subinst_ports, port_dict, inst_name):
"""Converts connection names to their spice hierarchy equivalent"""
converted_conns = []
+2
View File
@@ -1324,6 +1324,8 @@ class layout():
pdf.drawLayout()
pdf.writeToFile(pdf_name)
def print_attr(self):
"""Prints a list of attributes for the current layout object"""
debug.info(0,
+45
View File
@@ -499,3 +499,48 @@ class spice():
def return_power(self, dynamic=0.0, leakage=0.0):
return power_data(dynamic, leakage)
def find_aliases(self, inst_name, port_nets, path_nets, alias, alias_mod, exclusion_set=None):
"""Given a list of nets, will compare the internal alias of a mod to determine
if the nets have a connection to this mod's net (but not inst).
"""
if not exclusion_set:
exclusion_set = set()
try:
self.name_dict
except AttributeError:
self.name_dict = {}
self.build_names(self.name_dict, inst_name, port_nets)
aliases = []
for net in path_nets:
net = net.lower()
int_net = self.name_dict[net]['int_net']
int_mod = self.name_dict[net]['mod']
if int_mod.is_net_alias(int_net, alias, alias_mod, exclusion_set):
aliases.append(net)
return aliases
def is_net_alias(self, known_net, net_alias, mod, exclusion_set):
"""Checks if the alias_net in input mod is the same as the input net for this mod (self)."""
if self in exclusion_set:
return False
# Check ports of this mod
for pin in self.pins:
if self.is_net_alias_name_check(known_net, pin, net_alias, mod):
return True
# Check connections of all other subinsts
mod_set = set()
for subinst, inst_conns in zip(self.insts, self.conns):
for inst_conn, mod_pin in zip(inst_conns, subinst.mod.pins):
if self.is_net_alias_name_check(known_net, inst_conn, net_alias, mod):
return True
elif inst_conn.lower() == known_net.lower() and subinst.mod not in mod_set:
if subinst.mod.is_net_alias(mod_pin, net_alias, mod, exclusion_set):
return True
mod_set.add(subinst.mod)
return False
def is_net_alias_name_check(self, parent_net, child_net, alias_net, mod):
"""Utility function for checking single net alias."""
return self == mod and \
child_net.lower() == alias_net.lower() and \
parent_net.lower() == alias_net.lower()