From 459e3789b815ddf7c3332d3a555dc0c912bdf6f4 Mon Sep 17 00:00:00 2001 From: mrg Date: Mon, 29 Jun 2020 16:23:25 -0700 Subject: [PATCH] Change control layers in sky130. --- compiler/modules/bank.py | 32 +++++++---- compiler/modules/precharge_array.py | 28 +++++----- compiler/modules/sense_amp_array.py | 25 ++++++--- .../modules/single_level_column_mux_array.py | 56 ++++++++++--------- 4 files changed, 84 insertions(+), 57 deletions(-) diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index e18660e3..5716986f 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -592,6 +592,18 @@ class bank(design.design): self.copy_power_pins(inst, "vdd", add_vias=False) self.copy_power_pins(inst, "gnd", add_vias=False) + # If we use the pinvbuf as the decoder, we need to add power pins. + # Other decoders already have them. + if self.col_addr_size == 1: + for port in self.all_ports: + inst = self.column_decoder_inst[port] + for pin_name in ["vdd", "gnd"]: + pin_list = inst.get_pins(pin_name) + for pin in pin_list: + self.add_power_pin(pin_name, + pin.center(), + start_layer=pin.layer) + def route_bank_select(self, port): """ Route the bank select logic. """ @@ -862,6 +874,13 @@ class bank(design.design): if not self.col_addr_size>0: return + if OPTS.tech_name == "sky130": + stack = self.m2_stack + pitch = self.m3_pitch + else: + stack = self.m1_stack + pitch = self.m2_pitch + if self.col_addr_size == 1: # Connect to sel[0] and sel[1] @@ -881,9 +900,9 @@ class bank(design.design): self.copy_layout_pin(self.column_decoder_inst[port], decoder_name, addr_name) if port % 2: - offset = self.column_decoder_inst[port].ll() - vector(self.num_col_addr_lines * self.m2_nonpref_pitch, 0) + offset = self.column_decoder_inst[port].ll() - vector(self.num_col_addr_lines * pitch, 0) else: - offset = self.column_decoder_inst[port].lr() + vector(self.m2_nonpref_pitch, 0) + offset = self.column_decoder_inst[port].lr() + vector(pitch, 0) decode_pins = [self.column_decoder_inst[port].get_pin(x) for x in decode_names] @@ -891,16 +910,9 @@ class bank(design.design): column_mux_pins = [self.port_data_inst[port].get_pin(x) for x in sel_names] route_map = list(zip(decode_pins, column_mux_pins)) - if "li" in layer: - stack = self.li_stack - directions = "pref" - else: - stack = self.m1_stack - directions = "pref" self.create_vertical_channel_route(route_map, offset, - stack, - directions=directions) + stack) def add_lvs_correspondence_points(self): """ diff --git a/compiler/modules/precharge_array.py b/compiler/modules/precharge_array.py index 3a3b8c8b..d37de64f 100644 --- a/compiler/modules/precharge_array.py +++ b/compiler/modules/precharge_array.py @@ -30,6 +30,11 @@ class precharge_array(design.design): self.bitcell_br = bitcell_br self.column_offset = column_offset + if OPTS.tech_name == "sky130": + self.en_bar_layer = "m3" + else: + self.en_bar_layer = "m1" + self.create_netlist() if not OPTS.netlist_only: self.create_layout() @@ -74,21 +79,18 @@ class precharge_array(design.design): def add_layout_pins(self): - en_bar_pin = self.pc_cell.get_pin("en_bar") - if en_bar_pin.layer =="li": - en_bar_layer = "m3" - else: - en_bar_layer = en_bar_pin.layer - r = self.add_layout_pin(text="en_bar", - layer=en_bar_layer, - offset=en_bar_pin.ll(), - width=self.width, - height=en_bar_pin.height()) - self.add_via_stack_center(from_layer=en_bar_pin.layer, - to_layer=en_bar_layer, - offset = r.center()) + en_pin = self.pc_cell.get_pin("en_bar") + start_offset = en_pin.lc().scale(0, 1) + end_offset = start_offset + vector(self.width, 0) + self.add_layout_pin_segment_center(text="en_bar", + layer=self.en_bar_layer, + start=start_offset, + end=end_offset) for inst in self.local_insts: + self.add_via_stack_center(from_layer=en_pin.layer, + to_layer=self.en_bar_layer, + offset=inst.get_pin("en_bar").center()) self.copy_layout_pin(inst, "vdd") for i in range(len(self.local_insts)): diff --git a/compiler/modules/sense_amp_array.py b/compiler/modules/sense_amp_array.py index 5d41b2a0..98cbee66 100644 --- a/compiler/modules/sense_amp_array.py +++ b/compiler/modules/sense_amp_array.py @@ -37,6 +37,11 @@ class sense_amp_array(design.design): self.column_offset = column_offset self.row_size = self.word_size * self.words_per_row + if OPTS.tech_name == "sky130": + self.en_layer = "m3" + else: + self.en_layer = "m1" + self.create_netlist() if not OPTS.netlist_only: self.create_layout() @@ -173,14 +178,18 @@ class sense_amp_array(design.design): height=dout_pin.height()) def route_rails(self): - # add sclk rail across entire array - sclk = self.amp.get_pin(self.amp.en_name) - sclk_offset = self.amp.get_pin(self.amp.en_name).ll().scale(0, 1) - self.add_layout_pin(text=self.en_name, - layer=sclk.layer, - offset=sclk_offset, - width=self.width, - height=drc("minwidth_" + sclk.layer)) + # Add enable across the array + en_pin = self.amp.get_pin(self.amp.en_name) + start_offset = en_pin.lc().scale(0, 1) + end_offset = start_offset + vector(self.width, 0) + self.add_layout_pin_segment_center(text=self.en_name, + layer=self.en_layer, + start=start_offset, + end=end_offset) + for inst in self.local_insts: + self.add_via_stack_center(from_layer=en_pin.layer, + to_layer=self.en_layer, + offset=inst.get_pin(self.amp.en_name).center()) def input_load(self): return self.amp.input_load() diff --git a/compiler/modules/single_level_column_mux_array.py b/compiler/modules/single_level_column_mux_array.py index 37fd4dc1..8b01d111 100644 --- a/compiler/modules/single_level_column_mux_array.py +++ b/compiler/modules/single_level_column_mux_array.py @@ -32,14 +32,16 @@ class single_level_column_mux_array(design.design): self.bitcell_br = bitcell_br self.column_offset = column_offset - if "li" in layer: - self.col_mux_stack = self.m1_stack[::-1] - self.col_mux_stack_pitch = self.m2_pitch + if OPTS.tech_name == "sky130": + self.sel_layer = "m3" + self.sel_pitch = self.m3_pitch + self.bitline_layer = "m1" else: - self.col_mux_stack = self.m1_stack - self.col_mux_stack_pitch = self.m1_pitch + self.sel_layer = "m1" + self.sel_pitch = self.m2_pitch + self.bitline_layer = "m2" - if preferred_directions[self.col_mux_stack[0]] == "V": + if preferred_directions[self.sel_layer] == "V": self.via_directions = ("H", "H") else: self.via_directions = "pref" @@ -96,7 +98,7 @@ class single_level_column_mux_array(design.design): self.width = self.columns * self.mux.width # one set of metal1 routes for select signals and a pair to interconnect the mux outputs bl/br # one extra route pitch is to space from the sense amp - self.route_height = (self.words_per_row + 3) * self.col_mux_stack_pitch + self.route_height = (self.words_per_row + 3) * self.sel_pitch def create_array(self): self.mux_inst = [] @@ -157,9 +159,9 @@ class single_level_column_mux_array(design.design): def add_horizontal_input_rail(self): """ Create address input rails below the mux transistors """ for j in range(self.words_per_row): - offset = vector(0, self.route_height + (j - self.words_per_row) * self.col_mux_stack_pitch) + offset = vector(0, self.route_height + (j - self.words_per_row) * self.sel_pitch) self.add_layout_pin(text="sel_{}".format(j), - layer=self.col_mux_stack[0], + layer=self.sel_layer, offset=offset, width=self.mux.width * self.columns) @@ -178,7 +180,7 @@ class single_level_column_mux_array(design.design): offset = vector(gate_offset.x, self.get_pin("sel_{}".format(sel_index)).cy()) self.add_via_stack_center(from_layer="poly", - to_layer=self.col_mux_stack[0], + to_layer=self.sel_layer, offset=offset, directions=self.via_directions) self.add_path("poly", [offset, gate_offset]) @@ -190,42 +192,44 @@ class single_level_column_mux_array(design.design): bl_offset_begin = self.mux_inst[j].get_pin("bl_out").bc() br_offset_begin = self.mux_inst[j].get_pin("br_out").bc() - bl_out_offset_begin = bl_offset_begin - vector(0, (self.words_per_row + 1) * self.col_mux_stack_pitch) - br_out_offset_begin = br_offset_begin - vector(0, (self.words_per_row + 2) * self.col_mux_stack_pitch) + bl_out_offset_begin = bl_offset_begin - vector(0, (self.words_per_row + 1) * self.sel_pitch) + br_out_offset_begin = br_offset_begin - vector(0, (self.words_per_row + 2) * self.sel_pitch) # Add the horizontal wires for the first bit if j % self.words_per_row == 0: bl_offset_end = self.mux_inst[j + self.words_per_row - 1].get_pin("bl_out").bc() br_offset_end = self.mux_inst[j + self.words_per_row - 1].get_pin("br_out").bc() - bl_out_offset_end = bl_offset_end - vector(0, (self.words_per_row + 1) * self.col_mux_stack_pitch) - br_out_offset_end = br_offset_end - vector(0, (self.words_per_row + 2) * self.col_mux_stack_pitch) + bl_out_offset_end = bl_offset_end - vector(0, (self.words_per_row + 1) * self.sel_pitch) + br_out_offset_end = br_offset_end - vector(0, (self.words_per_row + 2) * self.sel_pitch) - self.add_path(self.col_mux_stack[0], [bl_out_offset_begin, bl_out_offset_end]) - self.add_path(self.col_mux_stack[0], [br_out_offset_begin, br_out_offset_end]) + self.add_path(self.sel_layer, [bl_out_offset_begin, bl_out_offset_end]) + self.add_path(self.sel_layer, [br_out_offset_begin, br_out_offset_end]) # Extend the bitline output rails and gnd downward on the first bit of each n-way mux self.add_layout_pin_segment_center(text="bl_out_{}".format(int(j / self.words_per_row)), - layer=self.col_mux_stack[2], + layer=self.bitline_layer, start=bl_offset_begin, end=bl_out_offset_begin) self.add_layout_pin_segment_center(text="br_out_{}".format(int(j / self.words_per_row)), - layer=self.col_mux_stack[2], + layer=self.bitline_layer, start=br_offset_begin, end=br_out_offset_begin) else: - self.add_path(self.col_mux_stack[2], [bl_out_offset_begin, bl_offset_begin]) - self.add_path(self.col_mux_stack[2], [br_out_offset_begin, br_offset_begin]) + self.add_path(self.bitline_layer, [bl_out_offset_begin, bl_offset_begin]) + self.add_path(self.bitline_layer, [br_out_offset_begin, br_offset_begin]) # This via is on the right of the wire - self.add_via_center(layers=self.col_mux_stack, - offset=bl_out_offset_begin, - directions=self.via_directions) + self.add_via_stack_center(from_layer=self.bitline_layer, + to_layer=self.sel_layer, + offset=bl_out_offset_begin, + directions=self.via_directions) # This via is on the left of the wire - self.add_via_center(layers=self.col_mux_stack, - offset=br_out_offset_begin, - directions=self.via_directions) + self.add_via_stack_center(from_layer=self.bitline_layer, + to_layer=self.sel_layer, + offset=br_out_offset_begin, + directions=self.via_directions) def get_drain_cin(self): """Get the relative capacitance of the drain of the NMOS pass TX"""