Merge branch 'tech_migration' into dev

This commit is contained in:
mrg 2020-04-20 16:28:16 -07:00
commit 90fdaf902c
8 changed files with 195 additions and 124 deletions

View File

@ -974,6 +974,7 @@ class layout():
def create_channel_route(self, netlist, def create_channel_route(self, netlist,
offset, offset,
layer_stack, layer_stack,
layer_dirs=None,
vertical=False): vertical=False):
""" """
The net list is a list of the nets. Each net is a list of pins The net list is a list of the nets. Each net is a list of pins
@ -1012,6 +1013,7 @@ class layout():
def vcg_pin_overlap(pin1, pin2, vertical, pitch): def vcg_pin_overlap(pin1, pin2, vertical, pitch):
""" Check for vertical or horizontal overlap of the two pins """ """ Check for vertical or horizontal overlap of the two pins """
# FIXME: If the pins are not in a row, this may break. # FIXME: If the pins are not in a row, this may break.
# However, a top pin shouldn't overlap another top pin, # However, a top pin shouldn't overlap another top pin,
# for example, so the # for example, so the
@ -1025,12 +1027,24 @@ class layout():
overlaps = (not vertical and x_overlap) or (vertical and y_overlap) overlaps = (not vertical and x_overlap) or (vertical and y_overlap)
return overlaps return overlaps
if not layer_dirs:
# Use the preferred layer directions
if self.get_preferred_direction(layer_stack[0]) == "V": if self.get_preferred_direction(layer_stack[0]) == "V":
self.vertical_layer = layer_stack[0] self.vertical_layer = layer_stack[0]
self.horizontal_layer = layer_stack[2] self.horizontal_layer = layer_stack[2]
else: else:
self.vertical_layer = layer_stack[2] self.vertical_layer = layer_stack[2]
self.horizontal_layer = layer_stack[0] self.horizontal_layer = layer_stack[0]
else:
# Use the layer directions specified to the router rather than
# the preferred directions
debug.check(layer_dirs[0] != layer_dirs[1], "Must have unique layer directions.")
if layer_dirs[0] == "V":
self.vertical_layer = layer_stack[0]
self.horizontal_layer = layer_stack[2]
else:
self.horizontal_layer = layer_stack[0]
self.vertical_layer = layer_stack[2]
layer_stuff = self.get_layer_pitch(self.vertical_layer) layer_stuff = self.get_layer_pitch(self.vertical_layer)
(self.vertical_pitch, self.vertical_width, self.vertical_space) = layer_stuff (self.vertical_pitch, self.vertical_width, self.vertical_space) = layer_stuff
@ -1113,17 +1127,17 @@ class layout():
self.horizontal_pitch) self.horizontal_pitch)
offset += vector(0, self.horizontal_pitch) offset += vector(0, self.horizontal_pitch)
def create_vertical_channel_route(self, netlist, offset, layer_stack): def create_vertical_channel_route(self, netlist, offset, layer_stack, layer_dirs=None):
""" """
Wrapper to create a vertical channel route Wrapper to create a vertical channel route
""" """
self.create_channel_route(netlist, offset, layer_stack, vertical=True) self.create_channel_route(netlist, offset, layer_stack, layer_dirs, vertical=True)
def create_horizontal_channel_route(self, netlist, offset, layer_stack): def create_horizontal_channel_route(self, netlist, offset, layer_stack, layer_dirs=None):
""" """
Wrapper to create a horizontal channel route Wrapper to create a horizontal channel route
""" """
self.create_channel_route(netlist, offset, layer_stack, vertical=False) self.create_channel_route(netlist, offset, layer_stack, layer_dirs, vertical=False)
def add_boundary(self, ll=vector(0, 0), ur=None): def add_boundary(self, ll=vector(0, 0), ur=None):
""" Add boundary for debugging dimensions """ """ Add boundary for debugging dimensions """

View File

@ -28,7 +28,6 @@ class bitcell_array(bitcell_base_array):
# the replica bitcell in the control logic # the replica bitcell in the control logic
# self.offset_all_coordinates() # self.offset_all_coordinates()
def create_netlist(self): def create_netlist(self):
""" Create and connect the netlist """ """ Create and connect the netlist """
self.add_modules() self.add_modules()
@ -62,7 +61,6 @@ class bitcell_array(bitcell_base_array):
def analytical_power(self, corner, load): def analytical_power(self, corner, load):
"""Power of Bitcell array and bitline in nW.""" """Power of Bitcell array and bitline in nW."""
from tech import drc, parameter
# Dynamic Power from Bitline # Dynamic Power from Bitline
bl_wire = self.gen_bl_wire() bl_wire = self.gen_bl_wire()

View File

@ -699,8 +699,13 @@ class port_data(design.design):
bottom_names = self._get_bitline_pins(bot_inst_group, bit) bottom_names = self._get_bitline_pins(bot_inst_group, bit)
top_names = self._get_bitline_pins(top_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)) route_map = list(zip(bottom_names, top_names))
self.create_horizontal_channel_route(route_map, offset, self.m1_stack) self.create_horizontal_channel_route(route_map, offset, self.m1_stack, bitline_dirs)
def connect_bitlines(self, inst1, inst2, num_bits, def connect_bitlines(self, inst1, inst2, num_bits,
inst1_bls_template="{inst}_{bit}", inst1_bls_template="{inst}_{bit}",

View File

@ -5,17 +5,14 @@
# (acting for and on behalf of Oklahoma State University) # (acting for and on behalf of Oklahoma State University)
# All rights reserved. # All rights reserved.
# #
from math import log
import design import design
import contact
from tech import drc
import debug import debug
import math
from vector import vector from vector import vector
from sram_factory import factory from sram_factory import factory
from globals import OPTS from globals import OPTS
import logical_effort import logical_effort
class single_level_column_mux_array(design.design): class single_level_column_mux_array(design.design):
""" """
Dynamically generated column mux array. Dynamically generated column mux array.
@ -74,23 +71,19 @@ class single_level_column_mux_array(design.design):
self.add_pin("br_out_{}".format(i)) self.add_pin("br_out_{}".format(i))
self.add_pin("gnd") self.add_pin("gnd")
def add_modules(self): def add_modules(self):
self.mux = factory.create(module_type="single_level_column_mux", self.mux = factory.create(module_type="single_level_column_mux",
bitcell_bl=self.bitcell_bl, bitcell_bl=self.bitcell_bl,
bitcell_br=self.bitcell_br) bitcell_br=self.bitcell_br)
self.add_mod(self.mux) self.add_mod(self.mux)
def setup_layout_constants(self): def setup_layout_constants(self):
self.column_addr_size = num_of_inputs = int(self.words_per_row / 2) self.column_addr_size = int(self.words_per_row / 2)
self.width = self.columns * self.mux.width 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 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 # one extra route pitch is to space from the sense amp
self.route_height = (self.words_per_row + 3) * self.m1_pitch self.route_height = (self.words_per_row + 3) * self.m1_pitch
def create_array(self): def create_array(self):
self.mux_inst = [] self.mux_inst = []
# For every column, add a pass gate # For every column, add a pass gate
@ -117,11 +110,9 @@ class single_level_column_mux_array(design.design):
else: else:
mirror = "" mirror = ""
name = "XMUX{0}".format(col_num)
offset = vector(xoffset, self.route_height) offset = vector(xoffset, self.route_height)
self.mux_inst[col_num].place(offset=offset, mirror=mirror) self.mux_inst[col_num].place(offset=offset, mirror=mirror)
def add_layout_pins(self): def add_layout_pins(self):
""" Add the pins after we determine the height. """ """ Add the pins after we determine the height. """
# For every column, add a pass gate # For every column, add a pass gate
@ -142,7 +133,6 @@ class single_level_column_mux_array(design.design):
for inst in self.mux_inst: for inst in self.mux_inst:
self.copy_layout_pin(inst, "gnd") self.copy_layout_pin(inst, "gnd")
def add_routing(self): def add_routing(self):
self.add_horizontal_input_rail() self.add_horizontal_input_rail()
self.add_vertical_poly_rail() self.add_vertical_poly_rail()
@ -167,9 +157,10 @@ class single_level_column_mux_array(design.design):
# Add the column x offset to find the right select bit # Add the column x offset to find the right select bit
gate_offset = self.mux_inst[col].get_pin("sel").bc() gate_offset = self.mux_inst[col].get_pin("sel").bc()
# height to connect the gate to the correct horizontal row # height to connect the gate to the correct horizontal row
sel_height = self.get_pin("sel_{}".format(sel_index)).by() # sel_height = self.get_pin("sel_{}".format(sel_index)).by()
# use the y offset from the sel pin and the x offset from the gate # use the y offset from the sel pin and the x offset from the gate
offset = vector(gate_offset.x,self.get_pin("sel_{}".format(sel_index)).cy()) offset = vector(gate_offset.x,
self.get_pin("sel_{}".format(sel_index)).cy())
# Add the poly contact with a shift to account for the rotation # Add the poly contact with a shift to account for the rotation
self.add_via_center(layers=("m1", "contact", "poly"), self.add_via_center(layers=("m1", "contact", "poly"),
offset=offset) offset=offset)
@ -221,7 +212,6 @@ class single_level_column_mux_array(design.design):
start=br_out_offset, start=br_out_offset,
end=tmp_br_out_end) end=tmp_br_out_end)
# This via is on the right of the wire # This via is on the right of the wire
self.add_via_center(layers=self.m1_stack, self.add_via_center(layers=self.m1_stack,
offset=bl_out_offset) offset=bl_out_offset)
@ -231,7 +221,6 @@ class single_level_column_mux_array(design.design):
offset=br_out_offset) offset=br_out_offset)
else: else:
self.add_path("m2", [bl_out_offset, tmp_bl_out_end]) self.add_path("m2", [bl_out_offset, tmp_bl_out_end])
self.add_path("m2", [br_out_offset, tmp_br_out_end]) self.add_path("m2", [br_out_offset, tmp_br_out_end])

View File

@ -0,0 +1,49 @@
#!/usr/bin/env python3
# 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 unittest
from testutils import *
import sys,os
sys.path.append(os.getenv("OPENRAM_HOME"))
import globals
from globals import OPTS
from sram_factory import factory
import debug
#@unittest.skip("SKIPPING 04_driver_test")
class single_level_column_mux_pbitcell_test(openram_test):
def runTest(self):
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
globals.init_openram(config_file)
# check single level column mux in multi-port
OPTS.bitcell = "pbitcell"
OPTS.num_rw_ports = 1
OPTS.num_r_ports = 1
OPTS.num_w_ports = 1
factory.reset()
debug.info(2, "Checking column mux for pbitcell (innermost connections)")
tx = factory.create(module_type="single_level_column_mux", tx_size=8, bitcell_bl="bl0", bitcell_br="br0")
self.local_check(tx)
factory.reset()
debug.info(2, "Checking column mux for pbitcell (outermost connections)")
tx = factory.create(module_type="single_level_column_mux",tx_size=8, bitcell_bl="bl2", bitcell_br="br2")
self.local_check(tx)
globals.end_openram()
# run the test from the command line
if __name__ == "__main__":
(OPTS, args) = globals.parse_args()
del sys.argv[1:]
header(__file__, OPTS.tech_name)
unittest.main(testRunner=debugTestRunner())

View File

@ -28,22 +28,6 @@ class single_level_column_mux_test(openram_test):
tx = factory.create(module_type="single_level_column_mux", tx_size=8) tx = factory.create(module_type="single_level_column_mux", tx_size=8)
self.local_check(tx) self.local_check(tx)
# check single level column mux in multi-port
OPTS.bitcell = "pbitcell"
OPTS.num_rw_ports = 1
OPTS.num_r_ports = 1
OPTS.num_w_ports = 1
factory.reset()
debug.info(2, "Checking column mux for pbitcell (innermost connections)")
tx = factory.create(module_type="single_level_column_mux", tx_size=8, bitcell_bl="bl0", bitcell_br="br0")
self.local_check(tx)
factory.reset()
debug.info(2, "Checking column mux for pbitcell (outermost connections)")
tx = factory.create(module_type="single_level_column_mux",tx_size=8, bitcell_bl="bl2", bitcell_br="br2")
self.local_check(tx)
globals.end_openram() globals.end_openram()
# run the test from the command line # run the test from the command line

View File

@ -0,0 +1,78 @@
#!/usr/bin/env python3
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California
# All rights reserved.
#
import unittest
from testutils import *
import sys,os
sys.path.append(os.getenv("OPENRAM_HOME"))
import globals
from globals import OPTS
from sram_factory import factory
import debug
class port_data_1rw_1r_test(openram_test):
def runTest(self):
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
globals.init_openram(config_file)
from sram_config import sram_config
OPTS.bitcell = "bitcell_1w_1r"
OPTS.num_rw_ports = 0
OPTS.num_r_ports = 1
OPTS.num_w_ports = 1
c = sram_config(word_size=4,
num_words=16)
c.words_per_row=1
factory.reset()
c.recompute_sizes()
debug.info(1, "No column mux")
a = factory.create("port_data", sram_config=c, port=0)
self.local_check(a)
a = factory.create("port_data", sram_config=c, port=1)
self.local_check(a)
c.num_words=32
c.words_per_row=2
factory.reset()
c.recompute_sizes()
debug.info(1, "Two way column mux")
a = factory.create("port_data", sram_config=c, port=0)
self.local_check(a)
a = factory.create("port_data", sram_config=c, port=1)
self.local_check(a)
c.num_words=64
c.words_per_row=4
factory.reset()
c.recompute_sizes()
debug.info(1, "Four way column mux")
a = factory.create("port_data", sram_config=c, port=0)
self.local_check(a)
a = factory.create("port_data", sram_config=c, port=1)
self.local_check(a)
c.word_size=2
c.num_words=128
c.words_per_row=8
factory.reset()
c.recompute_sizes()
debug.info(1, "Eight way column mux")
a = factory.create("port_data", sram_config=c, port=0)
self.local_check(a)
a = factory.create("port_data", sram_config=c, port=1)
self.local_check(a)
globals.end_openram()
# run the test from the command line
if __name__ == "__main__":
(OPTS, args) = globals.parse_args()
del sys.argv[1:]
header(__file__, OPTS.tech_name)
unittest.main(testRunner=debugTestRunner())

View File

@ -55,52 +55,6 @@ class port_data_test(openram_test):
a = factory.create("port_data", sram_config=c, port=0) a = factory.create("port_data", sram_config=c, port=0)
self.local_check(a) self.local_check(a)
OPTS.bitcell = "bitcell_1w_1r"
OPTS.num_rw_ports = 0
OPTS.num_r_ports = 1
OPTS.num_w_ports = 1
c.num_words=16
c.words_per_row=1
factory.reset()
c.recompute_sizes()
debug.info(1, "No column mux")
a = factory.create("port_data", sram_config=c, port=0)
self.local_check(a)
a = factory.create("port_data", sram_config=c, port=1)
self.local_check(a)
c.num_words=32
c.words_per_row=2
factory.reset()
c.recompute_sizes()
debug.info(1, "Two way column mux")
a = factory.create("port_data", sram_config=c, port=0)
self.local_check(a)
a = factory.create("port_data", sram_config=c, port=1)
self.local_check(a)
c.num_words=64
c.words_per_row=4
factory.reset()
c.recompute_sizes()
debug.info(1, "Four way column mux")
a = factory.create("port_data", sram_config=c, port=0)
self.local_check(a)
a = factory.create("port_data", sram_config=c, port=1)
self.local_check(a)
c.word_size=2
c.num_words=128
c.words_per_row=8
factory.reset()
c.recompute_sizes()
debug.info(1, "Eight way column mux")
a = factory.create("port_data", sram_config=c, port=0)
self.local_check(a)
a = factory.create("port_data", sram_config=c, port=1)
self.local_check(a)
globals.end_openram() globals.end_openram()
# run the test from the command line # run the test from the command line