From 82dc937768e2e88fae741600d8c604348fd7093a Mon Sep 17 00:00:00 2001 From: mrg Date: Fri, 29 May 2020 16:53:47 -0700 Subject: [PATCH 1/8] Add missing vias by using via stack function --- compiler/modules/port_data.py | 74 ++++++++++++++++----------------- compiler/pgates/precharge.py | 77 +++++++++++++---------------------- 2 files changed, 65 insertions(+), 86 deletions(-) diff --git a/compiler/modules/port_data.py b/compiler/modules/port_data.py index 8cc4e272..44bb8ed8 100644 --- a/compiler/modules/port_data.py +++ b/compiler/modules/port_data.py @@ -534,11 +534,14 @@ class port_data(design.design): else: start_bit=0 - self.channel_route_bitlines(inst1=inst1, - inst1_bls_template=inst1_bls_templ, - inst2=inst2, - num_bits=self.word_size, - inst1_start_bit=start_bit) + # This could be a channel route, but in some techs the bitlines + # are too close together. + print("SA to precharge") + self.connect_bitlines(inst1=inst1, + inst1_bls_template=inst1_bls_templ, + inst2=inst2, + num_bits=self.word_size, + inst1_start_bit=start_bit) def route_write_driver_to_column_mux_or_precharge_array(self, port): """ Routing of BL and BR between sense_amp and column mux or precharge array """ @@ -558,10 +561,13 @@ class port_data(design.design): else: start_bit=0 - self.channel_route_bitlines(inst1=inst1, inst2=inst2, - num_bits=self.word_size, - inst1_bls_template=inst1_bls_templ, - inst1_start_bit=start_bit) + # This could be a channel route, but in some techs the bitlines + # are too close together. + print("WD to precharge") + self.connect_bitlines(inst1=inst1, inst2=inst2, + num_bits=self.word_size, + inst1_bls_template=inst1_bls_templ, + inst1_start_bit=start_bit) def route_write_driver_to_sense_amp(self, port): """ Routing of BL and BR between write driver and sense amp """ @@ -569,11 +575,12 @@ class port_data(design.design): inst1 = self.write_driver_array_inst inst2 = self.sense_amp_array_inst - # These should be pitch matched in the cell library, - # but just in case, do a channel route. - self.channel_route_bitlines(inst1=inst1, - inst2=inst2, - num_bits=self.word_size) + # This could be a channel route, but in some techs the bitlines + # are too close together. + print("WD to SA") + self.connect_bitlines(inst1=inst1, + inst2=inst2, + num_bits=self.word_size) def route_bitline_pins(self): """ Add the bitline pins for the given port """ @@ -676,10 +683,9 @@ class port_data(design.design): Route the bl and br of two modules using the channel router. """ - bot_inst_group, top_inst_group = self._group_bitline_instances( - inst1, inst2, num_bits, - inst1_bls_template, inst1_start_bit, - inst2_bls_template, inst2_start_bit) + bot_inst_group, top_inst_group = self._group_bitline_instances(inst1, inst2, num_bits, + inst1_bls_template, inst1_start_bit, + inst2_bls_template, inst2_start_bit) # Channel route each mux separately since we don't minimize the number # of tracks in teh channel router yet. If we did, we could route all the bits at once! @@ -688,13 +694,8 @@ class port_data(design.design): bottom_names = self._get_bitline_pins(bot_inst_group, bit) top_names = self._get_bitline_pins(top_inst_group, bit) - if bottom_names[0].layer == "m2": - bitline_dirs = ("H", "V") - elif bottom_names[0].layer == "m1": - bitline_dirs = ("V", "H") - route_map = list(zip(bottom_names, top_names)) - self.create_horizontal_channel_route(route_map, offset, self.m1_stack, bitline_dirs) + self.create_horizontal_channel_route(route_map, offset, self.m1_stack) def connect_bitlines(self, inst1, inst2, num_bits, inst1_bls_template="{inst}_{bit}", @@ -707,26 +708,23 @@ class port_data(design.design): in the middle between the two modules (if needed). """ - bot_inst_group, top_inst_group = self._group_bitline_instances( - inst1, inst2, num_bits, - inst1_bls_template, inst1_start_bit, - inst2_bls_template, inst2_start_bit) + bot_inst_group, top_inst_group = self._group_bitline_instances(inst1, inst2, num_bits, + inst1_bls_template, inst1_start_bit, + inst2_bls_template, inst2_start_bit) for col in range(num_bits): + print(col) bot_bl_pin, bot_br_pin = self._get_bitline_pins(bot_inst_group, col) top_bl_pin, top_br_pin = self._get_bitline_pins(top_inst_group, col) bot_bl, bot_br = bot_bl_pin.uc(), bot_br_pin.uc() top_bl, top_br = top_bl_pin.bc(), top_br_pin.bc() - - yoffset = 0.5 * (top_bl.y + bot_bl.y) - self.add_path("m2", [bot_bl, - vector(bot_bl.x, yoffset), - vector(top_bl.x, yoffset), - top_bl]) - self.add_path("m2", [bot_br, - vector(bot_br.x, yoffset), - vector(top_br.x, yoffset), - top_br]) + + print("BL", bot_bl, top_bl) + print(bot_bl_pin, top_bl_pin) + print("BR", bot_br, top_br) + print(bot_br_pin, top_br_pin) + self.add_zjog(bot_bl_pin.layer, bot_bl, top_bl, "V") + self.add_zjog(bot_br_pin.layer, bot_br, top_br, "V") def graph_exclude_precharge(self): """Precharge adds a loop between bitlines, can be excluded to reduce complexity""" diff --git a/compiler/pgates/precharge.py b/compiler/pgates/precharge.py index d47e445f..ae314452 100644 --- a/compiler/pgates/precharge.py +++ b/compiler/pgates/precharge.py @@ -105,21 +105,19 @@ class precharge(design.design): # center of vdd rail pmos_vdd_pos = vector(pmos_pin.cx(), vdd_position.y) - self.add_path("m1", [pmos_pin.uc(), pmos_vdd_pos]) + self.add_path(self.bitline_layer, [pmos_pin.center(), pmos_vdd_pos]) - # if enable is not on M1, the supply can be - if self.en_layer != "m1": - self.add_via_center(layers=self.m1_stack, - offset=pmos_vdd_pos) - + self.add_via_stack_center(from_layer=self.bitline_layer, + to_layer=self.en_layer, + offset=pmos_vdd_pos) self.add_power_pin("vdd", self.well_contact_pos, directions=("V", "V")) - - # Hack for li layers - if hasattr(self, "li_stack"): - self.add_via_center(layers=self.li_stack, - offset=self.well_contact_pos) + + self.add_via_stack_center(from_layer=pmos_pin.layer, + to_layer=self.bitline_layer, + offset=pmos_pin.center(), + directions=("V", "V")) def create_ptx(self): """ @@ -199,14 +197,9 @@ class precharge(design.design): # midway in the 4 M2 tracks offset = self.lower_pmos_inst.get_pin("G").ul() \ + vector(0, 0.5 * self.m2_pitch) - self.add_via_center(layers=self.poly_stack, - offset=offset) - if self.en_layer == "m2": - self.add_via_center(layers=self.m1_stack, - offset=offset) - if hasattr(self, "li_stack"): - self.add_via_center(layers=self.li_stack, - offset=offset) + self.add_via_stack_center(from_layer="poly", + to_layer=self.en_layer, + offset=offset) # adds the en rail on metal1 self.add_layout_pin_segment_center(text="en_bar", @@ -225,13 +218,13 @@ class precharge(design.design): self.nwell_extend_active self.well_contact_pos = self.upper_pmos1_inst.get_pin("D").center().scale(1, 0) + \ vector(0, offset_height) - self.add_via_center(layers=self.active_stack, - offset=self.well_contact_pos, - implant_type="n", - well_type="n") - if hasattr(self, "li_stack"): - self.add_via_center(layers=self.li_stack, - offset=self.well_contact_pos) + self.well_contact = self.add_via_center(layers=self.active_stack, + offset=self.well_contact_pos, + implant_type="n", + well_type="n") + self.add_via_stack_center(from_layer=self.active_stack[2], + to_layer=self.bitline_layer, + offset=self.well_contact_pos) self.height = self.well_contact_pos.y + contact.active_contact.height + self.m1_space @@ -288,31 +281,19 @@ class precharge(design.design): Adds contacts/via from metal1 to metal2 for bit-lines """ - # No contacts needed if M1 - if self.bitline_layer == "m1": - return - # BL - lower_pin = self.lower_pmos_inst.get_pin("S") - self.lower_via = self.add_via_center(layers=self.m1_stack, - offset=lower_pin.center(), - directions=("V", "V")) + for lower_pin in [self.lower_pmos_inst.get_pin("S"), self.lower_pmos_inst.get_pin("D")]: + self.add_via_stack_center(from_layer=lower_pin.layer, + to_layer=self.bitline_layer, + offset=lower_pin.center(), + directions=("V", "V")) - lower_pin = self.lower_pmos_inst.get_pin("D") - self.lower_via = self.add_via_center(layers=self.m1_stack, - offset=lower_pin.center(), - directions=("V", "V")) - # BR - upper_pin = self.upper_pmos1_inst.get_pin("S") - self.upper_via2 = self.add_via_center(layers=self.m1_stack, - offset=upper_pin.center(), - directions=("V", "V")) - - upper_pin = self.upper_pmos2_inst.get_pin("D") - self.upper_via2 = self.add_via_center(layers=self.m1_stack, - offset=upper_pin.center(), - directions=("V", "V")) + for upper_pin in [self.upper_pmos1_inst.get_pin("S"), self.upper_pmos2_inst.get_pin("D")]: + self.add_via_stack_center(from_layer=upper_pin.layer, + to_layer=self.bitline_layer, + offset=upper_pin.center(), + directions=("V", "V")) def connect_pmos(self, pmos_pin, bit_xoffset): """ From 496a24389c4e95f780a71a1f73959366a9744f4d Mon Sep 17 00:00:00 2001 From: mrg Date: Fri, 29 May 2020 16:57:47 -0700 Subject: [PATCH 2/8] Remove prints --- compiler/modules/port_data.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/compiler/modules/port_data.py b/compiler/modules/port_data.py index 44bb8ed8..d544b6be 100644 --- a/compiler/modules/port_data.py +++ b/compiler/modules/port_data.py @@ -536,7 +536,6 @@ class port_data(design.design): # This could be a channel route, but in some techs the bitlines # are too close together. - print("SA to precharge") self.connect_bitlines(inst1=inst1, inst1_bls_template=inst1_bls_templ, inst2=inst2, @@ -563,7 +562,6 @@ class port_data(design.design): # This could be a channel route, but in some techs the bitlines # are too close together. - print("WD to precharge") self.connect_bitlines(inst1=inst1, inst2=inst2, num_bits=self.word_size, inst1_bls_template=inst1_bls_templ, @@ -577,7 +575,6 @@ class port_data(design.design): # This could be a channel route, but in some techs the bitlines # are too close together. - print("WD to SA") self.connect_bitlines(inst1=inst1, inst2=inst2, num_bits=self.word_size) @@ -713,16 +710,11 @@ class port_data(design.design): inst2_bls_template, inst2_start_bit) for col in range(num_bits): - print(col) bot_bl_pin, bot_br_pin = self._get_bitline_pins(bot_inst_group, col) top_bl_pin, top_br_pin = self._get_bitline_pins(top_inst_group, col) bot_bl, bot_br = bot_bl_pin.uc(), bot_br_pin.uc() top_bl, top_br = top_bl_pin.bc(), top_br_pin.bc() - print("BL", bot_bl, top_bl) - print(bot_bl_pin, top_bl_pin) - print("BR", bot_br, top_br) - print(bot_br_pin, top_br_pin) self.add_zjog(bot_bl_pin.layer, bot_bl, top_bl, "V") self.add_zjog(bot_br_pin.layer, bot_br, top_br, "V") From b3b03d4d397e82dbeb357ac01f381018226e2b27 Mon Sep 17 00:00:00 2001 From: mrg Date: Mon, 1 Jun 2020 16:46:00 -0700 Subject: [PATCH 3/8] Hard cells can accept height parameter too. --- compiler/custom/{pand2_dec.py => and2_dec.py} | 33 +++++++++++------- compiler/custom/{pand3_dec.py => and3_dec.py} | 29 ++++++++++------ compiler/custom/{pand4_dec.py => and4_dec.py} | 34 ++++++++++++------- compiler/custom/nand2_dec.py | 10 +++++- compiler/custom/nand3_dec.py | 10 +++++- compiler/custom/nand4_dec.py | 10 +++++- compiler/modules/hierarchical_decoder.py | 19 ++++------- compiler/modules/hierarchical_predecode.py | 6 ++-- compiler/pgates/wordline_driver.py | 8 ++--- ..._pand3_dec_test.py => 04_and2_dec_test.py} | 8 ++--- ..._pand4_dec_test.py => 04_and3_dec_test.py} | 8 ++--- ..._pand2_dec_test.py => 04_and4_dec_test.py} | 8 ++--- 12 files changed, 112 insertions(+), 71 deletions(-) rename compiler/custom/{pand2_dec.py => and2_dec.py} (89%) rename compiler/custom/{pand3_dec.py => and3_dec.py} (90%) rename compiler/custom/{pand4_dec.py => and4_dec.py} (89%) rename compiler/tests/{04_pand3_dec_test.py => 04_and2_dec_test.py} (85%) rename compiler/tests/{04_pand4_dec_test.py => 04_and3_dec_test.py} (85%) rename compiler/tests/{04_pand2_dec_test.py => 04_and4_dec_test.py} (85%) diff --git a/compiler/custom/pand2_dec.py b/compiler/custom/and2_dec.py similarity index 89% rename from compiler/custom/pand2_dec.py rename to compiler/custom/and2_dec.py index 0db490ff..b764bb83 100644 --- a/compiler/custom/pand2_dec.py +++ b/compiler/custom/and2_dec.py @@ -7,34 +7,37 @@ # import debug from vector import vector -import pgate +import design from sram_factory import factory from globals import OPTS +from tech import layer -class pand2_dec(pgate.pgate): +class and2_dec(design.design): """ This is an AND with configurable drive strength. """ def __init__(self, name, size=1, height=None, add_wells=True): - debug.info(1, "Creating pand2_dec {}".format(name)) + + design.design.__init__(self, name) + + debug.info(1, "Creating and2_dec {}".format(name)) self.add_comment("size: {}".format(size)) - self.size = size - - pgate.pgate.__init__(self, name, height, add_wells) - + self.height = height + + self.create_netlist() + if not OPTS.netlist_only: + self.create_layout() + def create_netlist(self): self.add_pins() self.create_modules() self.create_insts() def create_modules(self): - if OPTS.tech_name == "s8": - self.nand = factory.create(module_type="nand2_dec") - else: - self.nand = factory.create(module_type="nand2_dec", - height=self.height) + self.nand = factory.create(module_type="nand2_dec", + height=self.height) self.inv = factory.create(module_type="inv_dec", height=self.height, @@ -44,7 +47,13 @@ class pand2_dec(pgate.pgate): self.add_mod(self.inv) def create_layout(self): + + if "li" in layer: + self.route_layer = "li" + else: + self.route_layer = "m1" self.width = self.nand.width + self.inv.width + self.height = self.nand.height self.place_insts() self.add_wires() diff --git a/compiler/custom/pand3_dec.py b/compiler/custom/and3_dec.py similarity index 90% rename from compiler/custom/pand3_dec.py rename to compiler/custom/and3_dec.py index 3ec1eb45..89cc84f8 100644 --- a/compiler/custom/pand3_dec.py +++ b/compiler/custom/and3_dec.py @@ -7,22 +7,26 @@ # import debug from vector import vector -import pgate +import design from sram_factory import factory from globals import OPTS +from tech import layer -class pand3_dec(pgate.pgate): +class and3_dec(design.design): """ This is an AND with configurable drive strength. """ def __init__(self, name, size=1, height=None, add_wells=True): - debug.info(1, "Creating pand3_dec {}".format(name)) + design.design.__init__(self, name) + debug.info(1, "Creating and3_dec {}".format(name)) self.add_comment("size: {}".format(size)) - self.size = size + self.height = height - pgate.pgate.__init__(self, name, height, add_wells) + self.create_netlist() + if not OPTS.netlist_only: + self.create_layout() def create_netlist(self): self.add_pins() @@ -30,11 +34,8 @@ class pand3_dec(pgate.pgate): self.create_insts() def create_modules(self): - if OPTS.tech_name == "s8": - self.nand = factory.create(module_type="nand3_dec") - else: - self.nand = factory.create(module_type="nand3_dec", - height=self.height) + self.nand = factory.create(module_type="nand3_dec", + height=self.height) self.inv = factory.create(module_type="inv_dec", height=self.height, @@ -44,8 +45,14 @@ class pand3_dec(pgate.pgate): self.add_mod(self.inv) def create_layout(self): - self.width = self.nand.width + self.inv.width + if "li" in layer: + self.route_layer = "li" + else: + self.route_layer = "m1" + self.width = self.nand.width + self.inv.width + self.height = self.nand.height + self.place_insts() self.add_wires() self.add_layout_pins() diff --git a/compiler/custom/pand4_dec.py b/compiler/custom/and4_dec.py similarity index 89% rename from compiler/custom/pand4_dec.py rename to compiler/custom/and4_dec.py index ee65a349..f99c048f 100644 --- a/compiler/custom/pand4_dec.py +++ b/compiler/custom/and4_dec.py @@ -7,22 +7,28 @@ # import debug from vector import vector -import pgate +import design from sram_factory import factory from globals import OPTS +from tech import layer -class pand4_dec(pgate.pgate): +class and4_dec(design.design): """ This is an AND with configurable drive strength. """ def __init__(self, name, size=1, height=None, add_wells=True): - debug.info(1, "Creating pand4_dec {}".format(name)) - self.add_comment("size: {}".format(size)) - - self.size = size - pgate.pgate.__init__(self, name, height, add_wells) + design.design.__init__(self, name) + + debug.info(1, "Creating and4_dec {}".format(name)) + self.add_comment("size: {}".format(size)) + self.size = size + self.height = height + + self.create_netlist() + if not OPTS.netlist_only: + self.create_layout() def create_netlist(self): self.add_pins() @@ -30,20 +36,24 @@ class pand4_dec(pgate.pgate): self.create_insts() def create_modules(self): - if OPTS.tech_name == "s8": - self.nand = factory.create(module_type="nand4_dec") - else: - self.nand = factory.create(module_type="nand4_dec", - height=self.height) + self.nand = factory.create(module_type="nand4_dec", + height=self.height) self.inv = factory.create(module_type="inv_dec", + height=self.height, size=self.size) self.add_mod(self.nand) self.add_mod(self.inv) def create_layout(self): + if "li" in layer: + self.route_layer = "li" + else: + self.route_layer = "m1" + self.width = self.nand.width + self.inv.width + self.height = self.nand.height self.place_insts() self.add_wires() diff --git a/compiler/custom/nand2_dec.py b/compiler/custom/nand2_dec.py index 30a018a1..c806bf5a 100644 --- a/compiler/custom/nand2_dec.py +++ b/compiler/custom/nand2_dec.py @@ -6,7 +6,7 @@ # All rights reserved. # import design -from tech import GDS, layer, spice, parameter +from tech import GDS, layer, spice, parameter, drc import logical_effort import utils @@ -31,6 +31,14 @@ class nand2_dec(design.design): self.height = nand2_dec.height self.pin_map = nand2_dec.pin_map self.add_pin_types(self.type_list) + + # FIXME: For now... + size = 1 + self.size = size + self.nmos_size = 2 * size + self.pmos_size = parameter["beta"] * size + self.nmos_width = self.nmos_size * drc("minwidth_tx") + self.pmos_width = self.pmos_size * drc("minwidth_tx") def analytical_power(self, corner, load): """Returns dynamic and leakage power. Results in nW""" diff --git a/compiler/custom/nand3_dec.py b/compiler/custom/nand3_dec.py index d700062c..5eea68de 100644 --- a/compiler/custom/nand3_dec.py +++ b/compiler/custom/nand3_dec.py @@ -6,7 +6,7 @@ # All rights reserved. # import design -from tech import GDS, layer, spice, parameter +from tech import GDS, layer, spice, parameter, drc import logical_effort import utils @@ -31,6 +31,14 @@ class nand3_dec(design.design): self.height = nand3_dec.height self.pin_map = nand3_dec.pin_map self.add_pin_types(self.type_list) + + # FIXME: For now... + size = 1 + self.size = size + self.nmos_size = 2 * size + self.pmos_size = parameter["beta"] * size + self.nmos_width = self.nmos_size * drc("minwidth_tx") + self.pmos_width = self.pmos_size * drc("minwidth_tx") def analytical_power(self, corner, load): """Returns dynamic and leakage power. Results in nW""" diff --git a/compiler/custom/nand4_dec.py b/compiler/custom/nand4_dec.py index 5c2bb882..df3eee14 100644 --- a/compiler/custom/nand4_dec.py +++ b/compiler/custom/nand4_dec.py @@ -6,7 +6,7 @@ # All rights reserved. # import design -from tech import GDS, layer, spice, parameter +from tech import GDS, layer, spice, parameter, drc import logical_effort import utils @@ -31,6 +31,14 @@ class nand4_dec(design.design): self.height = nand4_dec.height self.pin_map = nand4_dec.pin_map self.add_pin_types(self.type_list) + + # FIXME: For now... + size = 1 + self.size = size + self.nmos_size = 2 * size + self.pmos_size = parameter["beta"] * size + self.nmos_width = self.nmos_size * drc("minwidth_tx") + self.pmos_width = self.pmos_size * drc("minwidth_tx") def analytical_power(self, corner, load): """Returns dynamic and leakage power. Results in nW""" diff --git a/compiler/modules/hierarchical_decoder.py b/compiler/modules/hierarchical_decoder.py index 3cb5d35c..8b711031 100644 --- a/compiler/modules/hierarchical_decoder.py +++ b/compiler/modules/hierarchical_decoder.py @@ -57,21 +57,15 @@ class hierarchical_decoder(design.design): self.DRC_LVS() def add_modules(self): - if OPTS.tech_name == "s8": - self.and2 = factory.create(module_type="pand2_dec") - else: - self.and2 = factory.create(module_type="pand2_dec", - height=self.cell_height) + self.and2 = factory.create(module_type="and2_dec", + height=self.cell_height) self.add_mod(self.and2) - if OPTS.tech_name == "s8": - self.and3 = factory.create(module_type="pand3_dec") - else: - self.and3 = factory.create(module_type="pand3_dec", - height=self.cell_height) - + + self.and3 = factory.create(module_type="and3_dec", + height=self.cell_height) self.add_mod(self.and3) # TBD - # self.and4 = factory.create(module_type="pand4_dec") + # self.and4 = factory.create(module_type="and4_dec") # self.add_mod(self.and4) self.add_decoders() @@ -180,6 +174,7 @@ class hierarchical_decoder(design.design): # Two extra pitches between modules on left and right self.internal_routing_width = self.total_number_of_predecoder_outputs * self.bus_pitch + self.bus_pitch self.row_decoder_height = self.and2.height * self.num_outputs + # Extra bus space for supply contacts self.input_routing_width = self.num_inputs * self.bus_pitch + self.bus_space diff --git a/compiler/modules/hierarchical_predecode.py b/compiler/modules/hierarchical_predecode.py index 8244028e..fa44b080 100644 --- a/compiler/modules/hierarchical_predecode.py +++ b/compiler/modules/hierarchical_predecode.py @@ -42,13 +42,13 @@ class hierarchical_predecode(design.design): # FIXME: Default parms are required for hard cells for now. if self.number_of_inputs == 2: - self.and_mod = factory.create(module_type="pand2_dec", + self.and_mod = factory.create(module_type="and2_dec", height=self.cell_height) elif self.number_of_inputs == 3: - self.and_mod = factory.create(module_type="pand3_dec", + self.and_mod = factory.create(module_type="and3_dec", height=self.cell_height) elif self.number_of_inputs == 4: - self.and_mod = factory.create(module_type="pand4_dec", + self.and_mod = factory.create(module_type="and4_dec", height=self.cell_height) else: debug.error("Invalid number of predecode inputs: {}".format(self.number_of_inputs), -1) diff --git a/compiler/pgates/wordline_driver.py b/compiler/pgates/wordline_driver.py index 1b035e20..a817941b 100644 --- a/compiler/pgates/wordline_driver.py +++ b/compiler/pgates/wordline_driver.py @@ -40,12 +40,8 @@ class wordline_driver(design.design): self.create_insts() def create_modules(self): - if OPTS.tech_name == "s8": - self.nand = factory.create(module_type="nand2_dec") - self.height = self.nand.height - else: - self.nand = factory.create(module_type="nand2_dec", - height=self.height) + self.nand = factory.create(module_type="nand2_dec", + height=self.height) self.driver = factory.create(module_type="inv_dec", size=self.size, diff --git a/compiler/tests/04_pand3_dec_test.py b/compiler/tests/04_and2_dec_test.py similarity index 85% rename from compiler/tests/04_pand3_dec_test.py rename to compiler/tests/04_and2_dec_test.py index 78e576ed..355d3b15 100755 --- a/compiler/tests/04_pand3_dec_test.py +++ b/compiler/tests/04_and2_dec_test.py @@ -15,7 +15,7 @@ from globals import OPTS from sram_factory import factory import debug -class pand3_dec_test(openram_test): +class and2_dec_test(openram_test): def runTest(self): config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME")) @@ -23,10 +23,10 @@ class pand3_dec_test(openram_test): global verify import verify - import pand3_dec + import and2_dec - debug.info(2, "Testing pand3 gate 4x") - a = pand3_dec.pand3_dec(name="pand3x4", size=4) + debug.info(2, "Testing and2 gate 4x") + a = and2_dec.and2_dec(name="and2x4", size=4) self.local_check(a) globals.end_openram() diff --git a/compiler/tests/04_pand4_dec_test.py b/compiler/tests/04_and3_dec_test.py similarity index 85% rename from compiler/tests/04_pand4_dec_test.py rename to compiler/tests/04_and3_dec_test.py index 78e576ed..7794f36b 100755 --- a/compiler/tests/04_pand4_dec_test.py +++ b/compiler/tests/04_and3_dec_test.py @@ -15,7 +15,7 @@ from globals import OPTS from sram_factory import factory import debug -class pand3_dec_test(openram_test): +class and3_dec_test(openram_test): def runTest(self): config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME")) @@ -23,10 +23,10 @@ class pand3_dec_test(openram_test): global verify import verify - import pand3_dec + import and3_dec - debug.info(2, "Testing pand3 gate 4x") - a = pand3_dec.pand3_dec(name="pand3x4", size=4) + debug.info(2, "Testing and3 gate 4x") + a = and3_dec.and3_dec(name="and3x4", size=4) self.local_check(a) globals.end_openram() diff --git a/compiler/tests/04_pand2_dec_test.py b/compiler/tests/04_and4_dec_test.py similarity index 85% rename from compiler/tests/04_pand2_dec_test.py rename to compiler/tests/04_and4_dec_test.py index 92b80203..7794f36b 100755 --- a/compiler/tests/04_pand2_dec_test.py +++ b/compiler/tests/04_and4_dec_test.py @@ -15,7 +15,7 @@ from globals import OPTS from sram_factory import factory import debug -class pand2_dec_test(openram_test): +class and3_dec_test(openram_test): def runTest(self): config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME")) @@ -23,10 +23,10 @@ class pand2_dec_test(openram_test): global verify import verify - import pand2_dec + import and3_dec - debug.info(2, "Testing pand2 gate 4x") - a = pand2_dec.pand2_dec(name="pand2x4", size=4) + debug.info(2, "Testing and3 gate 4x") + a = and3_dec.and3_dec(name="and3x4", size=4) self.local_check(a) globals.end_openram() From 9ecf98a4c32c52bde08010d2abb0e8b26ac38054 Mon Sep 17 00:00:00 2001 From: mrg Date: Mon, 1 Jun 2020 16:46:22 -0700 Subject: [PATCH 4/8] SRAM factory uses default name for first instance even if it has arguments. --- compiler/sram_factory.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/compiler/sram_factory.py b/compiler/sram_factory.py index df6b9d99..46eed3d4 100644 --- a/compiler/sram_factory.py +++ b/compiler/sram_factory.py @@ -111,11 +111,12 @@ class sram_factory: return obj_item # If no prefered module name is provided, we generate one. - if module_name is None: - # Use the default name if there are default arguments + if not module_name: + # Use the default name for the first cell. # This is especially for library cells so that the # spice and gds files can be found. - if len(kwargs) > 0: + # Subsequent objects will get unique names to help with GDS limitation. + if len(self.objects[real_module_type]) > 0: # Create a unique name and increment the index module_name = "{0}_{1}".format(real_module_type, self.module_indices[real_module_type]) From b0aa70ffda436e9b22f5f51c249671e2660c0ed6 Mon Sep 17 00:00:00 2001 From: mrg Date: Tue, 2 Jun 2020 09:23:27 -0700 Subject: [PATCH 5/8] Fix precharge vdd route layer --- compiler/pgates/precharge.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/compiler/pgates/precharge.py b/compiler/pgates/precharge.py index ae314452..8b84a1b8 100644 --- a/compiler/pgates/precharge.py +++ b/compiler/pgates/precharge.py @@ -105,17 +105,14 @@ class precharge(design.design): # center of vdd rail pmos_vdd_pos = vector(pmos_pin.cx(), vdd_position.y) - self.add_path(self.bitline_layer, [pmos_pin.center(), pmos_vdd_pos]) + self.add_path(self.en_layer, [pmos_pin.center(), pmos_vdd_pos]) - self.add_via_stack_center(from_layer=self.bitline_layer, - to_layer=self.en_layer, - offset=pmos_vdd_pos) self.add_power_pin("vdd", self.well_contact_pos, directions=("V", "V")) self.add_via_stack_center(from_layer=pmos_pin.layer, - to_layer=self.bitline_layer, + to_layer=self.en_layer, offset=pmos_pin.center(), directions=("V", "V")) From e69b665689c0b2b29ba0a124b15e6ba505199fca Mon Sep 17 00:00:00 2001 From: mrg Date: Tue, 2 Jun 2020 09:31:43 -0700 Subject: [PATCH 6/8] Flatten pbitcell_1 too --- technology/scn4m_subm/mag_lib/setup.tcl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/technology/scn4m_subm/mag_lib/setup.tcl b/technology/scn4m_subm/mag_lib/setup.tcl index 95e7dbea..09bbea27 100644 --- a/technology/scn4m_subm/mag_lib/setup.tcl +++ b/technology/scn4m_subm/mag_lib/setup.tcl @@ -6,7 +6,7 @@ equate class {-circuit1 pfet} {-circuit2 p} flatten class {-circuit1 dummy_cell_6t} flatten class {-circuit1 dummy_cell_1rw_1r} flatten class {-circuit1 dummy_cell_1w_1r} -flatten class {-circuit1 bitcell_array_0} +flatten class {-circuit1 pbitcell} flatten class {-circuit1 pbitcell_0} flatten class {-circuit1 pbitcell_1} property {-circuit1 nfet} remove as ad ps pd From 620604603c9949627df77b5f887f04e334d84e40 Mon Sep 17 00:00:00 2001 From: mrg Date: Tue, 2 Jun 2020 10:08:37 -0700 Subject: [PATCH 7/8] Fixed offset jogs --- compiler/base/hierarchy_layout.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/compiler/base/hierarchy_layout.py b/compiler/base/hierarchy_layout.py index 4d0345a3..f659aed4 100644 --- a/compiler/base/hierarchy_layout.py +++ b/compiler/base/hierarchy_layout.py @@ -450,7 +450,7 @@ class layout(): path=coordinates, layer_widths=layer_widths) - def add_zjog(self, layer, start, end, first_direction="H"): + def add_zjog(self, layer, start, end, first_direction="H", fixed_offset=None): """ Add a simple jog at the halfway point. If layer is a single value, it is a path. @@ -459,11 +459,17 @@ class layout(): # vertical first if first_direction == "V": - mid1 = vector(start.x, 0.5 * start.y + 0.5 * end.y) + if fixed_offset: + mid1 = vector(start.x, fixed_offset) + else: + mid1 = vector(start.x, 0.5 * start.y + 0.5 * end.y) mid2 = vector(end.x, mid1.y) # horizontal first elif first_direction == "H": - mid1 = vector(0.5 * start.x + 0.5 * end.x, start.y) + if fixed_offset: + mid1 = vector(fixed_offset, start.y) + else: + mid1 = vector(0.5 * start.x + 0.5 * end.x, start.y) mid2 = vector(mid1, end.y) else: debug.error("Invalid direction for jog -- must be H or V.") From a1c7474f80aaa35060f503b7bcb886e14f88b2c7 Mon Sep 17 00:00:00 2001 From: mrg Date: Tue, 2 Jun 2020 10:08:53 -0700 Subject: [PATCH 8/8] Revert to channel route of bitlines --- compiler/modules/port_data.py | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/compiler/modules/port_data.py b/compiler/modules/port_data.py index d544b6be..0ad0dd86 100644 --- a/compiler/modules/port_data.py +++ b/compiler/modules/port_data.py @@ -536,11 +536,11 @@ class port_data(design.design): # This could be a channel route, but in some techs the bitlines # are too close together. - self.connect_bitlines(inst1=inst1, - inst1_bls_template=inst1_bls_templ, - inst2=inst2, - num_bits=self.word_size, - inst1_start_bit=start_bit) + self.channel_route_bitlines(inst1=inst1, + inst1_bls_template=inst1_bls_templ, + inst2=inst2, + num_bits=self.word_size, + inst1_start_bit=start_bit) def route_write_driver_to_column_mux_or_precharge_array(self, port): """ Routing of BL and BR between sense_amp and column mux or precharge array """ @@ -562,10 +562,10 @@ class port_data(design.design): # This could be a channel route, but in some techs the bitlines # are too close together. - self.connect_bitlines(inst1=inst1, inst2=inst2, - num_bits=self.word_size, - inst1_bls_template=inst1_bls_templ, - inst1_start_bit=start_bit) + self.channel_route_bitlines(inst1=inst1, inst2=inst2, + num_bits=self.word_size, + inst1_bls_template=inst1_bls_templ, + inst1_start_bit=start_bit) def route_write_driver_to_sense_amp(self, port): """ Routing of BL and BR between write driver and sense amp """ @@ -714,9 +714,10 @@ class port_data(design.design): top_bl_pin, top_br_pin = self._get_bitline_pins(top_inst_group, col) bot_bl, bot_br = bot_bl_pin.uc(), bot_br_pin.uc() top_bl, top_br = top_bl_pin.bc(), top_br_pin.bc() - - self.add_zjog(bot_bl_pin.layer, bot_bl, top_bl, "V") - self.add_zjog(bot_br_pin.layer, bot_br, top_br, "V") + + layer_pitch = getattr(self, "{}_pitch".format(top_bl_pin.layer)) + self.add_zjog(bot_bl_pin.layer, bot_bl, top_bl, "V", top_bl_pin.by() - layer_pitch) + self.add_zjog(bot_br_pin.layer, bot_br, top_br, "V", top_bl_pin.by() - 2 * layer_pitch) def graph_exclude_precharge(self): """Precharge adds a loop between bitlines, can be excluded to reduce complexity"""