From 8e151553e43b1fd71ef20d7ff8c50eafeb0bc527 Mon Sep 17 00:00:00 2001 From: Matthew Guthaus Date: Tue, 17 Dec 2019 23:45:07 +0000 Subject: [PATCH] Update contact types. Use preferred directions in tech files. Programmatically generate based on interconnect stacks. --- compiler/base/contact.py | 50 ++++++++++-------------------- compiler/base/design.py | 45 +++++++++++++++++---------- technology/freepdk45/tech/tech.py | 7 +++++ technology/scn4m_subm/tech/tech.py | 6 ++++ 4 files changed, 58 insertions(+), 50 deletions(-) diff --git a/compiler/base/contact.py b/compiler/base/contact.py index 24b0e866..0a7ace88 100644 --- a/compiler/base/contact.py +++ b/compiler/base/contact.py @@ -11,6 +11,7 @@ from tech import drc import tech from vector import vector from sram_factory import factory +import sys class contact(hierarchy_design.hierarchy_design): @@ -28,7 +29,7 @@ class contact(hierarchy_design.hierarchy_design): """ - def __init__(self, layer_stack, dimensions=(1, 1), directions=("V", "V"), + def __init__(self, layer_stack, dimensions=(1, 1), directions=None, implant_type=None, well_type=None, name=""): # This will ignore the name parameter since # we can guarantee a unique name here @@ -43,7 +44,11 @@ class contact(hierarchy_design.hierarchy_design): self.layer_stack = layer_stack self.dimensions = dimensions - self.directions = directions + if directions: + self.directions = directions + else: + self.directions = (tech.preferred_directions[layer_stack[0]], + tech.preferred_directions[layer_stack[2]]) self.offset = vector(0, 0) self.implant_type = implant_type self.well_type = well_type @@ -228,35 +233,14 @@ class contact(hierarchy_design.hierarchy_design): """ Get total power of a module """ return self.return_power() - -# This is not instantiated and used for calculations only. -# These are static 1x1 contacts to reuse in all the design modules. -well = factory.create(module_type="contact", - layer_stack=tech.active_stack, - directions=("H", "V")) -active = factory.create(module_type="contact", - layer_stack=tech.active_stack, - directions=("H", "V")) -poly = factory.create(module_type="contact", - layer_stack=tech.poly_stack, - directions=("V", "H")) -if "li" in tech.layer.keys(): - lim1 = factory.create(module_type="contact", - layer_stack=tech.li_stack, - directions=("V", "H")) -else: - lim1 = None - -m1m2 = factory.create(module_type="contact", - layer_stack=tech.m1_stack, - directions=("H", "V")) -m2m3 = factory.create(module_type="contact", - layer_stack=tech.m2_stack, - directions=("V", "H")) -if "m4" in tech.layer.keys(): - m3m4 = factory.create(module_type="contact", - layer_stack=tech.m3_stack, - directions=("H", "V")) -else: - m3m4 = None + +# Set up a static for each layer to be used for measurements +for layer_stack in tech.layer_stacks: + (layer1, via, layer2) = layer_stack + cont = factory.create(module_type="contact", + layer_stack=layer_stack) + module = sys.modules[__name__] + # Create the contact as just the concat of the layer names + setattr(module, layer1 + layer2, cont) + diff --git a/compiler/base/design.py b/compiler/base/design.py index 1066cbc0..2e1488f9 100644 --- a/compiler/base/design.py +++ b/compiler/base/design.py @@ -26,30 +26,41 @@ class design(hierarchy_design): self.setup_multiport_constants() def setup_layer_constants(self): - """ + """ These are some layer constants used in many places in the compiler. """ import tech + for key in dir(tech): + # Single layer width rules + match = re.match(r".*_stack$", key) + if match: + layer_stack = getattr(tech, key) - # This is contact direction independent pitch, - # i.e. we take the maximum contact dimension - max_m1m2_contact = max(contact.m1m2.width, contact.m1m2.height) - self.m1_pitch = max_m1m2_contact + max(self.m1_space, self.m2_space) - max_m2m3_contact = max(contact.m2m3.width, contact.m2m3.height) - self.m2_pitch = max_m2m3_contact + max(self.m2_space, self.m3_space) - if "m4" in tech.layer: - max_m3m4_contact = max(contact.m3m4.width, contact.m3m4.height) - self.m3_pitch = max_m3m4_contact + max(self.m3_space, self.m4_space) - else: - self.m3_pitch = self.m2_pitch + # Set the stack as a local helper + setattr(self, key, layer_stack) - self.poly_stack = tech.poly_stack - self.active_stack = tech.active_stack - self.m1_stack = tech.m1_stack - self.m2_stack = tech.m2_stack - self.m3_stack = tech.m3_stack + # Add the pitch + setattr(self, + "{}_pitch".format(layer_stack[0]), + self.compute_pitch(layer_stack)) + + def compute_pitch(self, layer_stack): + + """ + This is contact direction independent pitch, + i.e. we take the maximum contact dimension + """ + (layer1, via, layer2) = layer_stack + + contact1 = getattr(contact, layer1 + layer2) + max_contact = max(contact1.width, contact1.height) + layer1_space = getattr(self, layer1+"_space") + layer2_space = getattr(self, layer2+"_space") + pitch = max_contact + max(layer1_space, layer2_space) + + return pitch def setup_drc_constants(self): """ diff --git a/technology/freepdk45/tech/tech.py b/technology/freepdk45/tech/tech.py index d87e98f1..3eba1a58 100644 --- a/technology/freepdk45/tech/tech.py +++ b/technology/freepdk45/tech/tech.py @@ -56,6 +56,13 @@ beol_stacks = [m1_stack, layer_stacks = feol_stacks + beol_stacks +preferred_directions = {"poly": "V", + "active": "H", + "m1": "H", + "m2": "V", + "m3": "H", + "m4": "V"} + ################################################### # GDS Layer Map ################################################### diff --git a/technology/scn4m_subm/tech/tech.py b/technology/scn4m_subm/tech/tech.py index 349310f6..44ffe9be 100644 --- a/technology/scn4m_subm/tech/tech.py +++ b/technology/scn4m_subm/tech/tech.py @@ -56,6 +56,12 @@ beol_stacks = [m1_stack, layer_stacks = feol_stacks + beol_stacks +preferred_directions = {"poly": "V", + "active": "H", + "m1": "H", + "m2": "V", + "m3": "H", + "m4": "V"} ################################################### ##GDS Layer Map