diff --git a/compiler/modules/base_array.py b/compiler/modules/base_array.py new file mode 100644 index 00000000..08a52c21 --- /dev/null +++ b/compiler/modules/base_array.py @@ -0,0 +1,131 @@ +# See LICENSE for licensing information. +# +# Copyright (c) 2016-2019 Regents of the University of California and The Board +# of Regents for the Oklahoma Agricultural and Mechanical College +# (acting for and on behalf of Oklahoma State University) +# All rights reserved. +# +import debug +import design +from tech import cell_properties + +class bitcell_base_array(design.design): + """ + Abstract base class for bitcell-arrays -- bitcell, dummy + """ + def __init__(self, cols, rows, name, column_offset): + design.design.__init__(self, name) + debug.info(1, "Creating {0} {1} x {2}".format(self.name, rows, cols)) + self.add_comment("rows: {0} cols: {1}".format(rows, cols)) + + self.column_size = cols + self.row_size = rows + self.column_offset = column_offset + + def add_pins(self): + row_list = self.cell.get_all_wl_names() + column_list = self.cell.get_all_bitline_names() + for col in range(self.column_size): + for cell_column in column_list: + self.add_pin(cell_column+"_{0}".format(col), "INOUT") + for row in range(self.row_size): + for cell_row in row_list: + self.add_pin(cell_row+"_{0}".format(row), "INPUT") + self.add_pin("vdd", "POWER") + self.add_pin("gnd", "GROUND") + + def get_bitcell_pins(self, col, row): + """ Creates a list of connections in the bitcell, + indexed by column and row, for instance use in bitcell_array """ + + bitcell_pins = [] + + pin_names = self.cell.get_all_bitline_names() + for pin in pin_names: + bitcell_pins.append(pin+"_{0}".format(col)) + pin_names = self.cell.get_all_wl_names() + for pin in pin_names: + bitcell_pins.append(pin+"_{0}".format(row)) + bitcell_pins.append("vdd") + bitcell_pins.append("gnd") + + return bitcell_pins + + def add_layout_pins(self): + """ Add the layout pins """ + + row_list = self.cell.get_all_wl_names() + column_list = self.cell.get_all_bitline_names() + + for col in range(self.column_size): + for cell_column in column_list: + bl_pin = self.cell_inst[0,col].get_pin(cell_column) + self.add_layout_pin(text=cell_column+"_{0}".format(col), + layer=bl_pin.layer, + offset=bl_pin.ll().scale(1,0), + width=bl_pin.width(), + height=self.height) + + for row in range(self.row_size): + for cell_row in row_list: + wl_pin = self.cell_inst[row,0].get_pin(cell_row) + self.add_layout_pin(text=cell_row+"_{0}".format(row), + layer=wl_pin.layer, + offset=wl_pin.ll().scale(0,1), + width=self.width, + height=wl_pin.height()) + + # For every second row and column, add a via for gnd and vdd + for row in range(self.row_size): + for col in range(self.column_size): + inst = self.cell_inst[row,col] + for pin_name in ["vdd", "gnd"]: + for pin in inst.get_pins(pin_name): + self.add_power_pin(name=pin_name, loc=pin.center(), vertical=True, start_layer=pin.layer) + + def _adjust_x_offset(self, xoffset, col, col_offset): + tempx = xoffset + dir_y = False + # If we mirror the current cell on the y axis adjust the x position + if cell_properties.bitcell.mirror.y and (col + col_offset) % 2: + tempx = xoffset + self.cell.width + dir_y = True + return (tempx, dir_y) + + def _adjust_y_offset(self, yoffset, row, row_offset): + tempy = yoffset + dir_x = False + # If we mirror the current cell on the x axis adjust the y position + if cell_properties.bitcell.mirror.x and (row + row_offset) % 2: + tempy = yoffset + self.cell.height + dir_x = True + return (tempy, dir_x) + + + def place_array(self, name_template, row_offset=0): + # We increase it by a well enclosure so the precharges don't overlap our wells + self.height = self.row_size*self.cell.height + self.width = self.column_size*self.cell.width + + xoffset = 0.0 + for col in range(self.column_size): + yoffset = 0.0 + tempx, dir_y = self._adjust_x_offset(xoffset, col, self.column_offset) + + for row in range(self.row_size): + name = name_template.format(row, col) + tempy, dir_x = self._adjust_y_offset(yoffset, row, row_offset) + + if dir_x and dir_y: + dir_key = "XY" + elif dir_x: + dir_key = "MX" + elif dir_y: + dir_key = "MY" + else: + dir_key = "" + + self.cell_inst[row,col].place(offset=[tempx, tempy], + mirror=dir_key) + yoffset += self.cell.height + xoffset += self.cell.width diff --git a/compiler/modules/bitcell_array.py b/compiler/modules/bitcell_array.py index bf43736b..636408df 100644 --- a/compiler/modules/bitcell_array.py +++ b/compiler/modules/bitcell_array.py @@ -7,25 +7,21 @@ # import debug import design +from base_array import bitcell_base_array from tech import drc, spice from vector import vector from globals import OPTS from sram_factory import factory import logical_effort -class bitcell_array(design.design): +class bitcell_array(bitcell_base_array): """ Creates a rows x cols array of memory cells. Assumes bit-lines and word line is connected by abutment. Connects the word lines and bit lines. """ - def __init__(self, cols, rows, name): - design.design.__init__(self, name) - debug.info(1, "Creating {0} {1} x {2}".format(self.name, rows, cols)) - self.add_comment("rows: {0} cols: {1}".format(rows, cols)) - - self.column_size = cols - self.row_size = rows + def __init__(self, cols, rows, name, column_offset=0): + super().__init__(cols, rows, name, column_offset) self.create_netlist() if not OPTS.netlist_only: @@ -44,27 +40,7 @@ class bitcell_array(design.design): def create_layout(self): - # We increase it by a well enclosure so the precharges don't overlap our wells - self.height = self.row_size*self.cell.height - self.width = self.column_size*self.cell.width - - xoffset = 0.0 - for col in range(self.column_size): - yoffset = 0.0 - for row in range(self.row_size): - name = "bit_r{0}_c{1}".format(row, col) - - if row % 2: - tempy = yoffset + self.cell.height - dir_key = "MX" - else: - tempy = yoffset - dir_key = "" - - self.cell_inst[row,col].place(offset=[xoffset, tempy], - mirror=dir_key) - yoffset += self.cell.height - xoffset += self.cell.width + self.place_array("bit_r{0}_c{1}") self.add_layout_pins() @@ -72,41 +48,13 @@ class bitcell_array(design.design): self.DRC_LVS() - def add_pins(self): - row_list = self.cell.get_all_wl_names() - column_list = self.cell.get_all_bitline_names() - for col in range(self.column_size): - for cell_column in column_list: - self.add_pin(cell_column+"_{0}".format(col), "INOUT") - for row in range(self.row_size): - for cell_row in row_list: - self.add_pin(cell_row+"_{0}".format(row), "INPUT") - self.add_pin("vdd", "POWER") - self.add_pin("gnd", "GROUND") def add_modules(self): """ Add the modules used in this design """ self.cell = factory.create(module_type="bitcell") self.add_mod(self.cell) - def get_bitcell_pins(self, col, row): - """ Creates a list of connections in the bitcell, - indexed by column and row, for instance use in bitcell_array """ - - bitcell_pins = [] - - pin_names = self.cell.get_all_bitline_names() - for pin in pin_names: - bitcell_pins.append(pin+"_{0}".format(col)) - pin_names = self.cell.get_all_wl_names() - for pin in pin_names: - bitcell_pins.append(pin+"_{0}".format(row)) - bitcell_pins.append("vdd") - bitcell_pins.append("gnd") - - return bitcell_pins - def create_instances(self): """ Create the module instances used in this design """ self.cell_inst = {} @@ -117,37 +65,6 @@ class bitcell_array(design.design): mod=self.cell) self.connect_inst(self.get_bitcell_pins(col, row)) - def add_layout_pins(self): - """ Add the layout pins """ - - row_list = self.cell.get_all_wl_names() - column_list = self.cell.get_all_bitline_names() - - for col in range(self.column_size): - for cell_column in column_list: - bl_pin = self.cell_inst[0,col].get_pin(cell_column) - self.add_layout_pin(text=cell_column+"_{0}".format(col), - layer=bl_pin.layer, - offset=bl_pin.ll().scale(1,0), - width=bl_pin.width(), - height=self.height) - - for row in range(self.row_size): - for cell_row in row_list: - wl_pin = self.cell_inst[row,0].get_pin(cell_row) - self.add_layout_pin(text=cell_row+"_{0}".format(row), - layer=wl_pin.layer, - offset=wl_pin.ll().scale(0,1), - width=self.width, - height=wl_pin.height()) - - # For every second row and column, add a via for gnd and vdd - for row in range(self.row_size): - for col in range(self.column_size): - inst = self.cell_inst[row,col] - for pin_name in ["vdd", "gnd"]: - for pin in inst.get_pins(pin_name): - self.add_power_pin(name=pin_name, loc=pin.center(), vertical=True, start_layer=pin.layer) def analytical_power(self, corner, load): """Power of Bitcell array and bitline in nW.""" diff --git a/compiler/modules/custom_cell_properties.py b/compiler/modules/custom_cell_properties.py new file mode 100644 index 00000000..085527fc --- /dev/null +++ b/compiler/modules/custom_cell_properties.py @@ -0,0 +1,28 @@ +# See LICENSE for licensing information. +# +# Copyright (c) 2016-2020 Regents of the University of California and The Board +# of Regents for the Oklahoma Agricultural and Mechanical College +# (acting for and on behalf of Oklahoma State University) +# All rights reserved. +# + +class _MirrorAxis: + def __init__(self, x, y): + self.x = x + self.y = y + +class _Bitcell: + def __init__(self, mirror): + self.mirror = mirror + +class CellProperties(): + """ + TODO + """ + def __init__(self): + self.names = {} + self._bitcell = _Bitcell(_MirrorAxis(True, False)) + + @property + def bitcell(self): + return self._bitcell diff --git a/compiler/modules/dummy_array.py b/compiler/modules/dummy_array.py index 1e5a2121..997330e1 100644 --- a/compiler/modules/dummy_array.py +++ b/compiler/modules/dummy_array.py @@ -5,23 +5,19 @@ # import debug import design +from base_array import bitcell_base_array from tech import drc import contact from sram_factory import factory from vector import vector from globals import OPTS -class dummy_array(design.design): +class dummy_array(bitcell_base_array): """ Generate a dummy row/column for the replica array. """ - def __init__(self, cols, rows, mirror=0, name=""): - design.design.__init__(self, name) - debug.info(1, "Creating {0} {1} x {2}".format(self.name, rows, cols)) - self.add_comment("rows: {0} cols: {1}".format(rows, cols)) - - self.column_size = cols - self.row_size = rows + def __init__(self, cols, rows, column_offset=0, mirror=0, name=""): + super().__init__(cols, rows, name, column_offset) self.mirror = mirror self.create_netlist() @@ -37,27 +33,7 @@ class dummy_array(design.design): def create_layout(self): - # We increase it by a well enclosure so the precharges don't overlap our wells - self.height = self.row_size*self.dummy_cell.height - self.width = self.column_size*self.dummy_cell.width - - xoffset = 0.0 - for col in range(self.column_size): - yoffset = 0.0 - for row in range(self.row_size): - name = "dummy_r{0}_c{1}".format(row, col) - - if (row+self.mirror) % 2: - tempy = yoffset + self.dummy_cell.height - dir_key = "MX" - else: - tempy = yoffset - dir_key = "" - - self.cell_inst[row,col].place(offset=[xoffset, tempy], - mirror=dir_key) - yoffset += self.dummy_cell.height - xoffset += self.dummy_cell.width + self.place_array("dummy_r{0}_c{1}", self.mirror) self.add_layout_pins() @@ -65,18 +41,6 @@ class dummy_array(design.design): self.DRC_LVS() - def add_pins(self): - row_list = self.cell.get_all_wl_names() - column_list = self.cell.get_all_bitline_names() - for col in range(self.column_size): - for cell_column in column_list: - self.add_pin(cell_column+"_{0}".format(col), "INOUT") - for row in range(self.row_size): - for cell_row in row_list: - self.add_pin(cell_row+"_{0}".format(row), "INPUT") - self.add_pin("vdd", "POWER") - self.add_pin("gnd", "GROUND") - def add_modules(self): """ Add the modules used in this design """ self.dummy_cell = factory.create(module_type="dummy_bitcell") @@ -84,23 +48,6 @@ class dummy_array(design.design): self.cell = factory.create(module_type="bitcell") - def get_bitcell_pins(self, col, row): - """ Creates a list of connections in the bitcell, - indexed by column and row, for instance use in bitcell_array """ - - bitcell_pins = [] - - pin_names = self.cell.get_all_bitline_names() - for pin in pin_names: - bitcell_pins.append(pin+"_{0}".format(col)) - pin_names = self.cell.get_all_wl_names() - for pin in pin_names: - bitcell_pins.append(pin+"_{0}".format(row)) - bitcell_pins.append("vdd") - bitcell_pins.append("gnd") - - return bitcell_pins - def create_instances(self): """ Create the module instances used in this design """ @@ -111,39 +58,6 @@ class dummy_array(design.design): self.cell_inst[row,col]=self.add_inst(name=name, mod=self.dummy_cell) self.connect_inst(self.get_bitcell_pins(col, row)) - - def add_layout_pins(self): - """ Add the layout pins """ - - row_list = self.cell.get_all_wl_names() - column_list = self.cell.get_all_bitline_names() - - for col in range(self.column_size): - for cell_column in column_list: - bl_pin = self.cell_inst[0,col].get_pin(cell_column) - self.add_layout_pin(text=cell_column+"_{0}".format(col), - layer="m2", - offset=bl_pin.ll(), - width=bl_pin.width(), - height=self.height) - - for row in range(self.row_size): - for cell_row in row_list: - wl_pin = self.cell_inst[row,0].get_pin(cell_row) - self.add_layout_pin(text=cell_row+"_{0}".format(row), - layer="m1", - offset=wl_pin.ll(), - width=self.width, - height=wl_pin.height()) - - # For every second row and column, add a via for gnd and vdd - for row in range(self.row_size): - for col in range(self.column_size): - inst = self.cell_inst[row,col] - for pin_name in ["vdd", "gnd"]: - for pin in inst.get_pins(pin_name): - self.add_power_pin(name=pin_name, loc=pin.center(), vertical=True, start_layer=pin.layer) - def input_load(self): wl_wire = self.gen_wl_wire() diff --git a/compiler/modules/precharge_array.py b/compiler/modules/precharge_array.py index c2617f50..54ed2690 100644 --- a/compiler/modules/precharge_array.py +++ b/compiler/modules/precharge_array.py @@ -107,9 +107,19 @@ class precharge_array(design.design): def place_insts(self): """ Places precharge array by horizontally tiling the precharge cell""" + from tech import cell_properties + xoffset = 0 for i in range(self.columns): - offset = vector(self.pc_cell.width * i, 0) - self.local_insts[i].place(offset) + tempx = xoffset + if cell_properties.bitcell.mirror.y and (i + 1) % 2: + mirror = "MY" + tempx = tempx + self.pc_cell.width + else: + mirror = "" + + offset = vector(tempx, 0) + self.local_insts[i].place(offset=offset, mirror=mirror) + xoffset = xoffset + self.pc_cell.width def get_en_cin(self): """Get the relative capacitance of all the clk connections in the precharge array""" diff --git a/compiler/modules/replica_bitcell_array.py b/compiler/modules/replica_bitcell_array.py index 74962ba2..9cf5c5a2 100644 --- a/compiler/modules/replica_bitcell_array.py +++ b/compiler/modules/replica_bitcell_array.py @@ -86,6 +86,7 @@ class replica_bitcell_array(design.design): # Bitcell array self.bitcell_array = factory.create(module_type="bitcell_array", + column_offset=1 + self.left_rbl, cols=self.column_size, rows=self.row_size) self.add_mod(self.bitcell_array) @@ -95,12 +96,17 @@ class replica_bitcell_array(design.design): for bit in range(self.left_rbl+self.right_rbl): if bit=self.total_size-right_rbl-1, @@ -92,18 +94,35 @@ class replica_column(design.design): self.connect_inst(self.get_bitcell_pins(0, row)) def place_instances(self): - + from tech import cell_properties # Flip the mirrors if we have an odd number of replica+dummy rows at the bottom # so that we will start with mirroring rather than not mirroring rbl_offset = (self.left_rbl+1)%2 - + + # if our bitcells are mirrored on the y axis, check if we are in global + # column that needs to be flipped. + dir_y = False + xoffset = 0 + if cell_properties.bitcell.mirror.y and self.column_offset % 2: + dir_y = True + xoffset = self.replica_cell.width + for row in range(self.total_size): + dir_x = False name = "bit_r{0}_{1}".format(row,"rbl") - offset = vector(0,self.cell.height*(row+(row+rbl_offset)%2)) - if (row+rbl_offset)%2: + if cell_properties.bitcell.mirror.x and (row+rbl_offset)%2: + dir_x = True + + offset = vector(xoffset,self.cell.height*(row+(row+rbl_offset)%2)) + + if dir_x and dir_y: + dir_key = "XY" + elif dir_x: dir_key = "MX" + elif dir_y: + dir_key = "MY" else: - dir_key = "R0" + dir_key = "" self.cell_inst[row].place(offset=offset, mirror=dir_key) diff --git a/compiler/modules/sense_amp_array.py b/compiler/modules/sense_amp_array.py index ca5afc47..44639017 100644 --- a/compiler/modules/sense_amp_array.py +++ b/compiler/modules/sense_amp_array.py @@ -84,14 +84,27 @@ class sense_amp_array(design.design): "en", "vdd", "gnd"]) def place_sense_amp_array(self): - + from tech import cell_properties if self.bitcell.width > self.amp.width: amp_spacing = self.bitcell.width * self.words_per_row else: amp_spacing = self.amp.width * self.words_per_row + for i in range(0,self.word_size): - amp_position = vector(amp_spacing * i, 0) - self.local_insts[i].place(amp_position) + xoffset = amp_spacing * i + + # align the xoffset to the grid of bitcells. This way we + # know when to do the mirroring. + grid_x = int(xoffset / self.amp.width) + + if cell_properties.bitcell.mirror.y and grid_x % 2: + mirror = "MY" + xoffset = xoffset + self.amp.width + else: + mirror = "" + + amp_position = vector(xoffset, 0) + self.local_insts[i].place(offset=amp_position,mirror=mirror) def add_layout_pins(self): diff --git a/compiler/modules/single_level_column_mux_array.py b/compiler/modules/single_level_column_mux_array.py index 09f21cfa..24510015 100644 --- a/compiler/modules/single_level_column_mux_array.py +++ b/compiler/modules/single_level_column_mux_array.py @@ -99,11 +99,19 @@ class single_level_column_mux_array(design.design): "gnd"]) def place_array(self): + from tech import cell_properties # For every column, add a pass gate for col_num in range(self.columns): + xoffset = col_num * self.mux.width + if cell_properties.bitcell.mirror.y and col_num % 2: + mirror = "MY" + xoffset = xoffset + self.mux.width + else: + mirror = "" + name = "XMUX{0}".format(col_num) - x_off = vector(col_num * self.mux.width, self.route_height) - self.mux_inst[col_num].place(x_off) + offset = vector(xoffset, self.route_height) + self.mux_inst[col_num].place(offset=offset, mirror=mirror) def add_layout_pins(self): @@ -161,6 +169,7 @@ class single_level_column_mux_array(design.design): def route_bitlines(self): """ Connect the output bit-lines to form the appropriate width mux """ + from tech import cell_properties for j in range(self.columns): bl_offset = self.mux_inst[j].get_pin("bl_out").bc() br_offset = self.mux_inst[j].get_pin("br_out").bc() @@ -171,23 +180,38 @@ class single_level_column_mux_array(design.design): bl_out_offset_end = bl_out_offset + vector(0,self.route_height) br_out_offset_end = br_out_offset + vector(0,self.route_height) + if cell_properties.bitcell.mirror.y and j % 2: + tmp_bl_out_end = br_out_offset_end + tmp_br_out_end = bl_out_offset_end + else: + tmp_bl_out_end = bl_out_offset_end + tmp_br_out_end = br_out_offset_end + if (j % self.words_per_row) == 0: # Create the metal1 to connect the n-way mux output from the pass gate # These will be located below the select lines. Yes, these are M2 width # to ensure vias are enclosed and M1 min width rules. width = self.m2_width + self.mux.width * (self.words_per_row - 1) - self.add_path("m1", [bl_out_offset, bl_out_offset+vector(width,0)]) - self.add_path("m1", [br_out_offset, br_out_offset+vector(width,0)]) + + if cell_properties.bitcell.mirror.y and (j % 2) == 0: + bl = self.mux.get_pin("bl") + br = self.mux.get_pin("br") + dist = abs(bl.ll().x - br.ll().x) + else: + dist = 0 + + self.add_path("m1", [bl_out_offset, bl_out_offset+vector(width+dist,0)]) + self.add_path("m1", [br_out_offset, br_out_offset+vector(width-dist,0)]) # 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="m2", start=bl_out_offset, - end=bl_out_offset_end) + end=tmp_bl_out_end) self.add_layout_pin_segment_center(text="br_out_{}".format(int(j/self.words_per_row)), layer="m2", start=br_out_offset, - end=br_out_offset_end) + end=tmp_br_out_end) # This via is on the right of the wire @@ -200,8 +224,8 @@ class single_level_column_mux_array(design.design): else: - self.add_path("m2", [ bl_out_offset, bl_out_offset_end]) - self.add_path("m2", [ br_out_offset, br_out_offset_end]) + self.add_path("m2", [ bl_out_offset, tmp_bl_out_end]) + self.add_path("m2", [ br_out_offset, tmp_br_out_end]) # This via is on the right of the wire self.add_via_center(layers=self.m1_stack, diff --git a/compiler/modules/write_driver_array.py b/compiler/modules/write_driver_array.py index 900a8294..e9b0ac1b 100644 --- a/compiler/modules/write_driver_array.py +++ b/compiler/modules/write_driver_array.py @@ -106,14 +106,23 @@ class write_driver_array(design.design): def place_write_array(self): + from tech import cell_properties if self.bitcell.width > self.driver.width: self.driver_spacing = self.bitcell.width else: self.driver_spacing = self.driver.width for i in range(0,self.columns,self.words_per_row): index = int(i/self.words_per_row) - base = vector(i * self.driver_spacing, 0) - self.driver_insts[index].place(base) + xoffset = i * self.driver_spacing + + if cell_properties.bitcell.mirror.y and i % 2: + mirror = "MY" + xoffset = xoffset + self.driver.width + else: + mirror = "" + + base = vector(xoffset, 0) + self.driver_insts[index].place(offset=base, mirror=mirror) def add_layout_pins(self): diff --git a/technology/freepdk45/tech/tech.py b/technology/freepdk45/tech/tech.py index 00ab4b9b..ffc981b8 100644 --- a/technology/freepdk45/tech/tech.py +++ b/technology/freepdk45/tech/tech.py @@ -8,6 +8,7 @@ import os from design_rules import * from module_type import * +from custom_cell_properties import CellProperties """ File containing the process technology parameters for FreePDK 45nm. @@ -24,6 +25,12 @@ File containing the process technology parameters for FreePDK 45nm. # For example: tech_modules['contact'] = 'contact_freepdk45' tech_modules = ModuleType() +################################################### +# Custom cell properties +################################################### +cell_properties = CellProperties() +cell_properties.bitcell.mirror.x = True +cell_properties.bitcell.mirror.y = False ################################################### # GDS file info diff --git a/technology/scn3me_subm/tech/tech.py b/technology/scn3me_subm/tech/tech.py index cb476df5..9e6f370b 100755 --- a/technology/scn3me_subm/tech/tech.py +++ b/technology/scn3me_subm/tech/tech.py @@ -1,6 +1,7 @@ import os from design_rules import * from module_type import * +from custom_cell_properties import CellProperties """ File containing the process technology parameters for SCMOS 3me, subm, 180nm. @@ -12,6 +13,13 @@ File containing the process technology parameters for SCMOS 3me, subm, 180nm. # For example: tech_modules['contact'] = 'contact_scn3me' tech_modules = ModuleType() +################################################### +# Custom cell properties +################################################### +cell_properties = CellProperties() +cell_properties.bitcell.mirror.x = True +cell_properties.bitcell.mirror.y = False + #GDS file info GDS={} # gds units diff --git a/technology/scn4m_subm/tech/tech.py b/technology/scn4m_subm/tech/tech.py index 87c1d830..965306a3 100644 --- a/technology/scn4m_subm/tech/tech.py +++ b/technology/scn4m_subm/tech/tech.py @@ -8,6 +8,7 @@ import os from design_rules import * from module_type import * +from custom_cell_properties import CellProperties """ File containing the process technology parameters for SCMOS 4m, 0.35um @@ -24,6 +25,12 @@ File containing the process technology parameters for SCMOS 4m, 0.35um # For example: tech_modules['contact'] = 'contact_scn4m' tech_modules = ModuleType() +################################################### +# Custom cell properties +################################################### +cell_properties = CellProperties() +cell_properties.bitcell.mirror.x = True +cell_properties.bitcell.mirror.y = False ################################################### # GDS file info