fix the conflicts for merge

This commit is contained in:
Bin wu 2016-11-17 17:19:48 -08:00
commit a22ba2087b
85 changed files with 988 additions and 692 deletions

Binary file not shown.

2
README
View File

@ -3,7 +3,7 @@ BASIC SETUP
-The OpenRAM compiler has very few dependencies: -The OpenRAM compiler has very few dependencies:
1) ngspice v20 or later or HSpice I-2013.12-1 or later 1) ngspice-25 or later or HSpice I-2013.12-1 or later
2) Python 2.7 and higher (currently excludes Python 3 and up) 2) Python 2.7 and higher (currently excludes Python 3 and up)
3) a setup script for each technology 3) a setup script for each technology
4) a technology directory for each technology with the base cells 4) a technology directory for each technology with the base cells

View File

@ -30,3 +30,11 @@ Fix stimuli.py to be more readable.
Change the delay measurement to be from the negative clock edge to Change the delay measurement to be from the negative clock edge to
remove the dependency on the clock period. remove the dependency on the clock period.
Remove duplicate clock inverter in MS flop.
Make lib file have delay relative to negedge for DATA. Must update
timing code too.
Convert characterizer into a Python package

View File

@ -867,7 +867,7 @@ class bank(design.design):
for i in range(2): for i in range(2):
ff_index = i + self.row_addr_size ff_index = i + self.row_addr_size
current_dout = self.msf_address.dout_positions[ff_index] current_dout = self.msf_address.dout_positions[ff_index]
msf_row_addr_line_position = (current_dout.rotate().scale(1,-1) msf_row_addr_line_position = (current_dout.rotate_scale(1,-1)
+ self.msf_address_offset) + self.msf_address_offset)
line_index = self.num_central_bus - 2 + i line_index = self.num_central_bus - 2 + i
@ -913,7 +913,7 @@ class bank(design.design):
mid2 = col_decoder_out_position + vector(connection_width, mid2 = col_decoder_out_position + vector(connection_width,
-self.central_line_y_offset) -self.central_line_y_offset)
self.add_wire(layers=("metal2", "via1", "metal1"), self.add_wire(layers=("metal1", "via1", "metal2"),
coordinates=[col_decoder_out_position,mid1,mid2], coordinates=[col_decoder_out_position,mid1,mid2],
offset=col_decoder_out_position) offset=col_decoder_out_position)
@ -922,9 +922,9 @@ class bank(design.design):
elif(self.col_addr_size == 1): elif(self.col_addr_size == 1):
ff_index = self.row_addr_size ff_index = self.row_addr_size
base = self.msf_address_offset - vector(0, 0.5 * drc["minwidth_metal3"]) base = self.msf_address_offset - vector(0, 0.5 * drc["minwidth_metal3"])
dout_position = (self.msf_address.dout_positions[ff_index].rotate().scale(1,-1) dout_position = (self.msf_address.dout_positions[ff_index].rotate_scale(1,-1)
+ base) + base)
dout_bar_position = (self.msf_address.dout_bar_positions[ff_index].rotate().scale(1,-1) dout_bar_position = (self.msf_address.dout_bar_positions[ff_index].rotate_scale(1,-1)
+ base) + base)
y_offset = self.msf_address_offset.y - self.msf_address.width y_offset = self.msf_address_offset.y - self.msf_address.width
@ -988,7 +988,7 @@ class bank(design.design):
# addres translation should take care of the 270 degree CCW rotation # addres translation should take care of the 270 degree CCW rotation
# addres translation should take care of the 270 degree CCW rotation # addres translation should take care of the 270 degree CCW rotation
msf_row_addr_line_position = (self.msf_address.dout_positions[i].rotate().scale(1,-1) msf_row_addr_line_position = (self.msf_address.dout_positions[i].rotate_scale(1,-1)
+ self.msf_address_offset + self.msf_address_offset
- vector(0, 0.5 * drc["minwidth_metal3"])) - vector(0, 0.5 * drc["minwidth_metal3"]))
connection_width = (self.central_line_xoffset[line_index] + drc["minwidth_metal2"] connection_width = (self.central_line_xoffset[line_index] + drc["minwidth_metal2"]
@ -1008,7 +1008,7 @@ class bank(design.design):
for i in range(self.addr_size): for i in range(self.addr_size):
# Route msf address inputs # Route msf address inputs
msf_din_position = (self.msf_address.din_positions[i].rotate().scale(1,-1) msf_din_position = (self.msf_address.din_positions[i].rotate_scale(1,-1)
+ self.msf_address_offset + self.msf_address_offset
- vector(0, 0.5 * drc["minwidth_metal3"])) - vector(0, 0.5 * drc["minwidth_metal3"]))
address_position = vector(self.left_vdd_x_offset, address_position = vector(self.left_vdd_x_offset,
@ -1083,7 +1083,7 @@ class bank(design.design):
""" CLK connection from central bus to MSF address """ CLK connection from central bus to MSF address
should we move this somewhere else hard to find when modify""" should we move this somewhere else hard to find when modify"""
msf_address_clk_position = (self.msf_address_offset msf_address_clk_position = (self.msf_address_offset
+ self.msf_address.clk_positions[0].rotate().scale(1,-1) + self.msf_address.clk_positions[0].rotate_scale(1,-1)
+ vector(- 0.5 * drc["minwidth_metal1"], + vector(- 0.5 * drc["minwidth_metal1"],
2 * drc["minwidth_metal2"])) 2 * drc["minwidth_metal2"]))
clk_connection_position = (self.msf_address_offset clk_connection_position = (self.msf_address_offset
@ -1150,7 +1150,7 @@ class bank(design.design):
start = self.bank_select_inv_position + self.inv4x.A_position start = self.bank_select_inv_position + self.inv4x.A_position
end = vector(self.left_vdd_x_offset, start.y + 3 * drc["minwidth_metal3"]) end = vector(self.left_vdd_x_offset, start.y + 3 * drc["minwidth_metal3"])
mid = vector(start.x, end.y) mid = vector(start.x, end.y)
self.add_wire(("metal1", "via1", "metal2"), [start, mid, end]) self.add_wire(("metal2", "via1", "metal1"), [start, mid, end])
# save position # save position
self.bank_select_position = end - vector(0, 0.5 * drc["minwidth_metal2"]) self.bank_select_position = end - vector(0, 0.5 * drc["minwidth_metal2"])
@ -1235,7 +1235,7 @@ class bank(design.design):
correct_y = (2 * self.NOR2.A_position.y + drc["minwidth_metal1"] correct_y = (2 * self.NOR2.A_position.y + drc["minwidth_metal1"]
- self.m1m2_via.width) - self.m1m2_via.width)
end = start + vector(0, correct_y) end = start + vector(0, correct_y)
self.add_wire(("metal2", "via2", "metal3"), [start, mid, end]) self.add_wire(("metal3", "via2", "metal2"), [start, mid, end])
# Save position # Save position
setattr(self,"{0}_position".format(self.control_signals[i]), setattr(self,"{0}_position".format(self.control_signals[i]),

View File

@ -90,6 +90,7 @@ def run_drc(name, gds_name):
f.close() f.close()
# run drc # run drc
cwd = os.getcwd()
os.chdir(OPTS.openram_temp) os.chdir(OPTS.openram_temp)
errfile = "%s%s.drc.err" % (OPTS.openram_temp, name) errfile = "%s%s.drc.err" % (OPTS.openram_temp, name)
outfile = "%s%s.drc.out" % (OPTS.openram_temp, name) outfile = "%s%s.drc.out" % (OPTS.openram_temp, name)
@ -98,6 +99,7 @@ def run_drc(name, gds_name):
OPTS.calibre_exe, OPTS.openram_temp, errfile, outfile) OPTS.calibre_exe, OPTS.openram_temp, errfile, outfile)
debug.info(1, cmd) debug.info(1, cmd)
os.system(cmd) os.system(cmd)
os.chdir(cwd)
# check the result for these lines in the summary: # check the result for these lines in the summary:
# TOTAL Original Layer Geometries: 106 (157) # TOTAL Original Layer Geometries: 106 (157)
@ -163,6 +165,7 @@ def run_lvs(name, gds_name, sp_name):
f.close() f.close()
# run LVS # run LVS
cwd = os.getcwd()
os.chdir(OPTS.openram_temp) os.chdir(OPTS.openram_temp)
errfile = "%s%s.lvs.err" % (OPTS.openram_temp, name) errfile = "%s%s.lvs.err" % (OPTS.openram_temp, name)
outfile = "%s%s.lvs.out" % (OPTS.openram_temp, name) outfile = "%s%s.lvs.out" % (OPTS.openram_temp, name)
@ -171,6 +174,7 @@ def run_lvs(name, gds_name, sp_name):
OPTS.openram_temp, errfile, outfile) OPTS.openram_temp, errfile, outfile)
debug.info(2, cmd) debug.info(2, cmd)
os.system(cmd) os.system(cmd)
os.chdir(cwd)
# check the result for these lines in the summary: # check the result for these lines in the summary:
f = open(lvs_runset['lvsReportFile'], "r") f = open(lvs_runset['lvsReportFile'], "r")
@ -265,6 +269,7 @@ def run_pex(name, gds_name, sp_name, output=None):
f.close() f.close()
# run pex # run pex
cwd = os.getcwd()
os.chdir(OPTS.openram_temp) os.chdir(OPTS.openram_temp)
errfile = "{0}{1}.pex.err".format(OPTS.openram_temp, name) errfile = "{0}{1}.pex.err".format(OPTS.openram_temp, name)
outfile = "{0}{1}.pex.out".format(OPTS.openram_temp, name) outfile = "{0}{1}.pex.out".format(OPTS.openram_temp, name)
@ -275,6 +280,7 @@ def run_pex(name, gds_name, sp_name, output=None):
outfile) outfile)
debug.info(2, cmd) debug.info(2, cmd)
os.system(cmd) os.system(cmd)
os.chdir(cwd)
# also check the output file # also check the output file
f = open(outfile, "r") f = open(outfile, "r")

View File

@ -27,7 +27,11 @@ def relative_compare(value1,value2):
def parse_output(filename, key): def parse_output(filename, key):
"""Parses a hspice output.lis file for a key value""" """Parses a hspice output.lis file for a key value"""
f = open("{0}/{1}.lis".format(OPTS.openram_temp, filename), "r") full_filename="{0}{1}.lis".format(OPTS.openram_temp, filename)
try:
f = open(full_filename, "r")
except IOError:
debug.error("Unable to open spice output file: {0}".format(full_filename),1)
contents = f.read() contents = f.read()
val = re.search(r"{0}\s*=\s*(-?\d+.?\d*\S*)\s+.*".format(key), contents) val = re.search(r"{0}\s*=\s*(-?\d+.?\d*\S*)\s+.*".format(key), contents)
if val != None: if val != None:

View File

@ -6,6 +6,7 @@ import tech
import math import math
import stimuli import stimuli
import charutils as ch import charutils as ch
import utils
OPTS = globals.get_opts() OPTS = globals.get_opts()
@ -262,20 +263,11 @@ class delay():
# run until the last cycle time # run until the last cycle time
end_time = self.cycle_times[-1] end_time = self.cycle_times[-1]
self.sf.write(".TRAN 5p {0}n\n".format(end_time)) self.sf.write(".TRAN 5p {0}n\n".format(end_time))
self.sf.write(".OPTIONS POST=1 PROBE\n")
if OPTS.spice_version == "hspice": # create plots for all signals
# create plots for all signals self.sf.write(".probe V(*)\n")
self.sf.write(".OPTIONS POST=1 PROBE\n") # end the stimulus file
self.sf.write(".probe V(*)\n") self.sf.write(".end\n")
# end the stimulus file
self.sf.write(".end\n")
self.sf.close()
else:
self.sf.write(".control\n")
self.sf.write("run\n")
self.sf.write("quit\n")
self.sf.write(".endc\n")
self.sf.write(".end\n")
@ -353,20 +345,19 @@ class delay():
target_period = 0.5 * (ub_period + lb_period) target_period = 0.5 * (ub_period + lb_period)
debug.info(1, "MinPeriod Search: {0}ns (ub: {1} lb: {2})".format(target_period, debug.info(1, "MinPeriod Search: {0}ns (ub: {1} lb: {2})".format(target_period,
ub_period, ub_period,
lb_period)) lb_period))
(success, delay_out) = self.try_period(feasible_period, target_period, data_value) (success, delay_out) = self.try_period(feasible_period, target_period, data_value)
if success: if success:
if ch.relative_compare(ub_period, target_period):
# use the two values to compare, but only return the ub since it is guaranteed feasible
(success, delay_out) = self.try_period(feasible_period, ub_period, data_value)
return (ub_period, delay_out)
fail_flag = False
ub_period = target_period ub_period = target_period
else: else:
lb_period = target_period lb_period = target_period
if ch.relative_compare(ub_period, lb_period):
# use the two values to compare, but only return the ub since it is guaranteed feasible
(success, delay_out) = self.try_period(feasible_period, ub_period, data_value)
return (ub_period, delay_out)
self.error("Should not reach here.",-1) self.error("Should not reach here.",-1)
return (target_period, delay_out) return (target_period, delay_out)

View File

@ -165,20 +165,12 @@ class setup_hold():
def write_control(self, period): def write_control(self, period):
# transient window # transient window
end_time = 2 * period end_time = 2 * period
self.sf.write(".TRAN 1n {0}n\n".format(end_time)) self.sf.write(".TRAN 5p {0}n\n".format(end_time))
self.sf.write(".OPTIONS POST=1 PROBE\n") self.sf.write(".OPTIONS POST=1 PROBE\n")
# create plots for all signals
if OPTS.spice_version == "hspice": self.sf.write(".probe V(*)\n")
self.sf.write(".probe V(*)\n") # end the stimulus file
# end the stimulus file self.sf.write(".end\n")
self.sf.write(".end\n")
else:
self.sf.write(".control\n")
self.sf.write("run\n")
self.sf.write("quit\n")
self.sf.write(".endc\n")
self.sf.write(".end\n")
def bidir_search(self, correct_value, noise_margin, measure_name, mode): def bidir_search(self, correct_value, noise_margin, measure_name, mode):
""" This will perform a bidirectional search for either setup or hold times. """ This will perform a bidirectional search for either setup or hold times.
@ -186,9 +178,11 @@ class setup_hold():
depending on whether we are doing setup or hold. depending on whether we are doing setup or hold.
""" """
period = tech.spice["feasible_period"] period = tech.spice["feasible_period"]
debug.info(2,"Feasible period from technology file: {0} ".format(period))
# The clock will start being offset by a period, so we want to look before and after # The clock will start being offset by a period, so we want to look before and after
# theis time. # this time by half a period.
if mode == "HOLD": if mode == "HOLD":
target_time = 1.5 * period target_time = 1.5 * period
lower_bound = 0.5*period lower_bound = 0.5*period
@ -212,6 +206,8 @@ class setup_hold():
setuphold_time = target_time - period setuphold_time = target_time - period
else: else:
setuphold_time = period - target_time setuphold_time = period - target_time
debug.info(2,"Checked initial {0} time {1}, data at {2}, clock at {3} ".format(mode,setuphold_time,
target_time,period))
debug.info(3,"Target time: {0} Low: {1} Up: {2} Measured: {3}".format(target_time, debug.info(3,"Target time: {0} Low: {1} Up: {2} Measured: {3}".format(target_time,
lower_bound, lower_bound,
upper_bound, upper_bound,
@ -220,6 +216,10 @@ class setup_hold():
debug.error("Initial period/target hold time fails for data value",2) debug.error("Initial period/target hold time fails for data value",2)
# We already found it feasible, so advance one step first thing. # We already found it feasible, so advance one step first thing.
debug.info(2,"Performing bidir search on {3} time: {2} LB: {0} UB: {1} ".format(lower_bound,
upper_bound,
setuphold_time,
mode))
if mode == "HOLD": if mode == "HOLD":
target_time -= 0.5 * (upper_bound - lower_bound) target_time -= 0.5 * (upper_bound - lower_bound)
else: else:
@ -269,6 +269,8 @@ class setup_hold():
setuphold_time = target_time - period setuphold_time = target_time - period
else: else:
setuphold_time = period - target_time setuphold_time = period - target_time
debug.info(2,"Converged on {0} time {1}, data at {2}, clock at {3}.".format(mode,setuphold_time,target_time,period))
return setuphold_time return setuphold_time

View File

@ -445,23 +445,31 @@ def write_supply(stim_file, vdd_name, gnd_name, vdd_voltage, gnd_voltage):
def run_sim(): def run_sim():
"""Run hspice in batch mode and output rawfile to parse.""" """Run hspice in batch mode and output rawfile to parse."""
temp_stim = "{0}stim.sp".format(OPTS.openram_temp) temp_stim = "{0}stim.sp".format(OPTS.openram_temp)
if OPTS.spice_version == "hspice": if OPTS.spice_version == "hspice":
# TODO: Should make multithreading parameter a configuration option # TODO: Should make multithreading parameter a configuration option
cmd_args = "-mt 8 -i {1} -o {2}timing 2>&1 /dev/null".format(OPTS.spice_exe, cmd = "{0} -mt 8 -i {1} -o {2}timing".format(OPTS.spice_exe,
temp_stim, temp_stim,
OPTS.openram_temp) OPTS.openram_temp)
valid_retcode=0
else: else:
cmd_args = "-b -i {1} -o {2}timing.lis 2>&1 /dev/null".format(OPTS.spice_exe, cmd = "{0} -b -o {2}timing.lis {1}".format(OPTS.spice_exe,
temp_stim, temp_stim,
OPTS.openram_temp) OPTS.openram_temp)
# for some reason, ngspice-25 returns 1 when it only has acceptable warnings
FNULL = open(os.devnull, 'w') valid_retcode=1
debug.info(2, OPTS.spice_exe + " " + cmd_args)
retcode = subprocess.call([OPTS.spice_exe, cmd_args], stdout=FNULL, stderr=FNULL)
FNULL.close() spice_stdout = open("{0}spice_stdout.log".format(OPTS.openram_temp), 'w')
spice_stderr = open("{0}spice_stderr.log".format(OPTS.openram_temp), 'w')
if (retcode > 0):
debug.error("Spice simulation error: " + OPTS.spice_exe + " " + cmd_args) debug.info(3, cmd)
sys.exit(-1) retcode = subprocess.call(cmd, stdout=spice_stdout, stderr=spice_stderr, shell=True)
spice_stdout.close()
spice_stderr.close()
if (retcode > valid_retcode):
debug.error("Spice simulation error: " + cmd, -1)

View File

@ -18,7 +18,7 @@ class contact(design.design):
dimensions[1], dimensions[1],
contact.unique_contact_id) contact.unique_contact_id)
design.design.__init__(self, name) design.design.__init__(self, name)
debug.info(2, "create contact object {0}".format(name)) debug.info(3, "create contact object {0}".format(name))
contact.unique_contact_id += 1 contact.unique_contact_id += 1
self.layer_stack = layer_stack self.layer_stack = layer_stack
@ -40,8 +40,8 @@ class contact(design.design):
self.offset_attributes(coordinate) self.offset_attributes(coordinate)
self.translate(coordinate) self.translate(coordinate)
self.height = max(obj.offset[1] + obj.height for obj in self.objs) self.height = max(obj.offset.y + obj.height for obj in self.objs)
self.width = max(obj.offset[0] + obj.width for obj in self.objs) self.width = max(obj.offset.x + obj.width for obj in self.objs)
def setup_layers(self): def setup_layers(self):
(first_layer, via_layer, second_layer) = self.layer_stack (first_layer, via_layer, second_layer) = self.layer_stack

View File

@ -146,7 +146,7 @@ class control_logic(design.design):
# Height and width # Height and width
self.height = self.logic_height + self.output_port_gap self.height = self.logic_height + self.output_port_gap
self.width = self.offset_replica_bitline[0] + self.replica_bitline.height self.width = self.offset_replica_bitline.x + self.replica_bitline.height
def add_routing(self): def add_routing(self):
""" Routing between modules """ """ Routing between modules """
@ -175,11 +175,11 @@ class control_logic(design.design):
# msf_control inputs # msf_control inputs
correct = vector(0, 0.5 * drc["minwidth_metal2"]) correct = vector(0, 0.5 * drc["minwidth_metal2"])
def translate_inputs(pt1,pt2): def translate_inputs(pt1,pt2):
return pt1 + pt2.rotate().scale(1,-1) - correct return pt1 + pt2.rotate_scale(1,-1) - correct
# msf_control outputs # msf_control outputs
def translate_outputs(pt1,pt2): def translate_outputs(pt1,pt2):
return pt1 - correct + vector(self.msf_control.height,- pt2[0]) return pt1 - correct + vector(self.msf_control.height,- pt2.x)
# set CSS WE OE signal groups(in, out, bar) # set CSS WE OE signal groups(in, out, bar)
pt1 = self.offset_msf_control pt1 = self.offset_msf_control
@ -197,21 +197,21 @@ class control_logic(design.design):
# clk , vdd # clk , vdd
base = self.offset_msf_control - vector(0.5 * drc["minwidth_metal2"], 0) base = self.offset_msf_control - vector(0.5 * drc["minwidth_metal2"], 0)
msf_clk = self.msf_control.clk_positions[0].rotate().scale(1,-1) msf_clk = self.msf_control.clk_positions[0].rotate_scale(1,-1)
self.msf_control_clk_position = base + msf_clk self.msf_control_clk_position = base + msf_clk
msf_vdd = self.msf_control.vdd_positions[0].rotate().scale(1,-1) msf_vdd = self.msf_control.vdd_positions[0].rotate_scale(1,-1)
self.msf_control_vdd_position = base + msf_vdd self.msf_control_vdd_position = base + msf_vdd
# gnd # gnd
self.msf_control_gnd_positions = [] self.msf_control_gnd_positions = []
for gnd_offset in self.msf_control.gnd_positions: for gnd_offset in self.msf_control.gnd_positions:
offset = self.offset_msf_control + vector(self.msf_control.height, offset = self.offset_msf_control + vector(self.msf_control.height,
- gnd_offset[0]) - gnd_offset.x)
self.msf_control_gnd_positions.append(offset - correct) self.msf_control_gnd_positions.append(offset - correct)
def add_1st_row(self,y_off): def add_1st_row(self,y_off):
# inv1 with clk as gate input. # inv1 with clk as gate input.
msf_control_rotate_x = self.offset_msf_control[0] + self.msf_control.height msf_control_rotate_x = self.offset_msf_control.x + self.msf_control.height
self.offset_inv1 = vector(msf_control_rotate_x - self.inv4.width, y_off) self.offset_inv1 = vector(msf_control_rotate_x - self.inv4.width, y_off)
self.add_inst(name="clk_inverter", self.add_inst(name="clk_inverter",
mod=self.inv4, mod=self.inv4,
@ -246,7 +246,7 @@ class control_logic(design.design):
self.set_nand2_nor2_pin("nand2",[1,1]) self.set_nand2_nor2_pin("nand2",[1,1])
# REPLICA BITLINE # REPLICA BITLINE
base_x = self.nand_array_position[0] + self.NAND3.width + 3 * self.inv.width base_x = self.nand_array_position.x + self.NAND3.width + 3 * self.inv.width
total_rail_gap = self.rail_offset_gap + self.overall_rail_2_gap total_rail_gap = self.rail_offset_gap + self.overall_rail_2_gap
x_off = base_x + total_rail_gap + self.replica_bitline_gap x_off = base_x + total_rail_gap + self.replica_bitline_gap
self.offset_replica_bitline = vector(x_off, y_off) self.offset_replica_bitline = vector(x_off, y_off)
@ -284,7 +284,7 @@ class control_logic(design.design):
def add_2nd_row(self, y_off): def add_2nd_row(self, y_off):
# Nand3_1 input: OE, clk_bar,CS output: rblk_bar # Nand3_1 input: OE, clk_bar,CS output: rblk_bar
self.offset_nand3_1 = vector(self.nand_array_position[0], y_off) self.offset_nand3_1 = vector(self.nand_array_position.x, y_off)
self.add_inst(name="NAND3_rblk_bar", self.add_inst(name="NAND3_rblk_bar",
mod=self.NAND3, mod=self.NAND3,
offset=self.offset_nand3_1, offset=self.offset_nand3_1,
@ -294,7 +294,7 @@ class control_logic(design.design):
self.set_Nand3_pins(nand_name = "nand3_1",nand_scale = [0,-1]) self.set_Nand3_pins(nand_name = "nand3_1",nand_scale = [0,-1])
# Nand3_2 input: WE, clk_bar,CS output: w_en_bar # Nand3_2 input: WE, clk_bar,CS output: w_en_bar
self.offset_nand3_2 = vector(self.nand_array_position[0], y_off) self.offset_nand3_2 = vector(self.nand_array_position.x, y_off)
self.add_inst(name="NAND3_w_en_bar", self.add_inst(name="NAND3_w_en_bar",
mod=self.NAND3, mod=self.NAND3,
offset=self.offset_nand3_2, offset=self.offset_nand3_2,
@ -304,7 +304,7 @@ class control_logic(design.design):
self.set_Nand3_pins(nand_name = "nand3_2",nand_scale = [0,1]) self.set_Nand3_pins(nand_name = "nand3_2",nand_scale = [0,1])
# connect nand2 and nand3 to inv # connect nand2 and nand3 to inv
nand3_to_inv_connection_height = self.NAND3.Z_position[1] - self.inv.A_position[1] + drc["minwidth_metal1"] nand3_to_inv_connection_height = self.NAND3.Z_position.y- self.inv.A_position.y+ drc["minwidth_metal1"]
self.add_rect(layer="metal1", self.add_rect(layer="metal1",
offset=self.nand3_1_Z_position, offset=self.nand3_1_Z_position,
width=drc["minwidth_metal1"], width=drc["minwidth_metal1"],
@ -315,7 +315,7 @@ class control_logic(design.design):
height=-nand3_to_inv_connection_height) height=-nand3_to_inv_connection_height)
# inv_2 input: rblk_bar, output: rblk # inv_2 input: rblk_bar, output: rblk
x_off = self.nand_array_position[0] + self.NAND3.width x_off = self.nand_array_position.x + self.NAND3.width
self.offset_inv2 = vector(x_off, y_off) self.offset_inv2 = vector(x_off, y_off)
self.add_inst(name="inv_rblk", self.add_inst(name="inv_rblk",
mod=self.inv, mod=self.inv,
@ -336,7 +336,7 @@ class control_logic(design.design):
self.set_inv2345_pins(inv_name="inv3", inv_scale=[1, 1]) self.set_inv2345_pins(inv_name="inv3", inv_scale=[1, 1])
# BUFFER INVERTERS FOR W_EN # BUFFER INVERTERS FOR W_EN
x_off = self.nand_array_position[0] + self.NAND3.width + self.inv.width x_off = self.nand_array_position.x + self.NAND3.width + self.inv.width
self.offset_inv6 = vector(x_off, y_off) self.offset_inv6 = vector(x_off, y_off)
self.add_inst(name="inv_w_en1", self.add_inst(name="inv_w_en1",
mod=self.inv, mod=self.inv,
@ -344,7 +344,7 @@ class control_logic(design.design):
mirror="RO") mirror="RO")
self.connect_inst(["pre_w_en", "pre_w_en1", "vdd", "gnd"]) self.connect_inst(["pre_w_en", "pre_w_en1", "vdd", "gnd"])
x_off = self.nand_array_position[0] + self.NAND3.width + 2 * self.inv.width x_off = self.nand_array_position.x + self.NAND3.width + 2 * self.inv.width
self.offset_inv7 = [x_off, y_off] self.offset_inv7 = [x_off, y_off]
self.add_inst(name="inv_w_en2", self.add_inst(name="inv_w_en2",
mod=self.inv, mod=self.inv,
@ -392,7 +392,7 @@ class control_logic(design.design):
def add_msf_control_routing(self): def add_msf_control_routing(self):
# FIRST RAIL : MSF_CONTROL OUTPUT RAIL # FIRST RAIL : MSF_CONTROL OUTPUT RAIL
rail1_start = vector(self.msf_control_WE_position[0], rail1_start = vector(self.msf_control_WE_position.x,
self.output_port_gap) self.output_port_gap)
for i in range(self.num_rails_1): for i in range(self.num_rails_1):
correct = vector((i+1) * self.rail_offset_gap, 0) correct = vector((i+1) * self.rail_offset_gap, 0)
@ -401,18 +401,18 @@ class control_logic(design.design):
offset=offset, offset=offset,
width=drc["minwidth_metal2"], width=drc["minwidth_metal2"],
height=self.logic_height) height=self.logic_height)
self.rail_1_x_offsets.append(offset[0]) self.rail_1_x_offsets.append(offset.x)
rail2_start_x = (self.nand_array_position[0] + self.NAND3.width rail2_start_x = (self.nand_array_position.x + self.NAND3.width
+ 3 * self.inv.width + self.rail_offset_gap) + 3 * self.inv.width + self.rail_offset_gap)
for i in range(self.num_rails_2): for i in range(self.num_rails_2):
offset = [rail2_start_x + i * self.rail_offset_gap, offset = vector(rail2_start_x + i * self.rail_offset_gap,
self.output_port_gap] self.output_port_gap)
self.add_rect(layer="metal2", self.add_rect(layer="metal2",
offset=offset, offset=offset,
width=drc["minwidth_metal2"], width=drc["minwidth_metal2"],
height=self.logic_height) height=self.logic_height)
self.rail_2_x_offsets.append(offset[0]) self.rail_2_x_offsets.append(offset.x)
def add_1st_row_routing(self): def add_1st_row_routing(self):
# First rail routing left # First rail routing left
@ -425,7 +425,7 @@ class control_logic(design.design):
line_x_offset = self.rail_1_x_offsets[line_indices[i]] line_x_offset = self.rail_1_x_offsets[line_indices[i]]
self.add_rect(layer="metal1", self.add_rect(layer="metal1",
offset=offset, offset=offset,
width=line_x_offset - offset[0] + drc["minwidth_metal2"], width=line_x_offset - offset.x + drc["minwidth_metal2"],
height=drc["minwidth_metal1"]) height=drc["minwidth_metal1"])
correct1 = vector(self.gap_between_rails, - self.via_shift) correct1 = vector(self.gap_between_rails, - self.via_shift)
correct2 = vector(self.contact_shift + drc["minwidth_metal2"],0) correct2 = vector(self.contact_shift + drc["minwidth_metal2"],0)
@ -450,27 +450,30 @@ class control_logic(design.design):
base = vector(line_x_offset, offset[1]) base = vector(line_x_offset, offset[1])
self.add_rect(layer="metal1", self.add_rect(layer="metal1",
offset=base, offset=base,
width=offset[0] - line_x_offset, width=offset.x - line_x_offset,
height=drc["minwidth_metal1"]) height=drc["minwidth_metal1"])
self.add_via(layers=("metal1", "via1", "metal2"), self.add_via(layers=("metal1", "via1", "metal2"),
offset=base + correct1, offset=base + correct1,
rotate=90) rotate=90)
# OE_bar [Bus # 1] to nor2 B input # OE_bar [Bus # 1] to nor2 B input
layer_stack = ("metal2", "via1", "metal1") layer_stack = ("metal1", "via1", "metal2")
start = self.nor2_1_B_position start = self.nor2_1_B_position
mid1 = [self.nor2_1_B_position[0] + 2 * drc["minwidth_metal2"], start[1]] mid1 = vector(self.nor2_1_B_position.x+ 2 * drc["minwidth_metal2"],
mid2 = [mid1[0], self.nor2_1_gnd_position[1] - 2 * drc["minwidth_metal1"]] start.y)
mid3 = [self.rail_1_x_offsets[1] + 0.5 * drc["minwidth_metal2"], mid2[1]] mid2 = vector(mid1.x,
end = [mid3[0], self.output_port_gap] self.nor2_1_gnd_position.y- 2 * drc["minwidth_metal1"])
mid3 = vector(self.rail_1_x_offsets[1] + 0.5 * drc["minwidth_metal2"],
mid2.y)
end = [mid3.x, self.output_port_gap]
self.add_wire(layer_stack, [start, mid1, mid2, mid3, end]) self.add_wire(layer_stack, [start, mid1, mid2, mid3, end])
layer_stack = ("metal1") layer_stack = ("metal1")
start = [self.inv1_Z_position[0], self.inv1_Z_position[1] + 0.5 * drc["minwidth_metal1"]] start = self.inv1_Z_position+ vector(0, + 0.5 * drc["minwidth_metal1"])
mid1 = [start[0] + drc["minwidth_metal2"], start[1]] mid1 = start + vector(drc["minwidth_metal2"], 0)
mid2 = [mid1[0], self.nand2_1_B_position mid2 = vector(mid1.x,
[1] + 0.5 * drc["minwidth_metal1"]] self.nand2_1_B_position.y + 0.5 * drc["minwidth_metal1"])
end = [self.nand2_1_B_position[0], mid2[1]] end = [self.nand2_1_B_position.x, mid2.y]
self.add_path(layer_stack, [start, mid1, mid2, end]) self.add_path(layer_stack, [start, mid1, mid2, end])
def add_2nd_row_routing(self): def add_2nd_row_routing(self):
@ -486,23 +489,23 @@ class control_logic(design.design):
line_x_offset = self.rail_2_x_offsets[line_indices[i]] line_x_offset = self.rail_2_x_offsets[line_indices[i]]
self.add_rect(layer="metal1", self.add_rect(layer="metal1",
offset=offset, offset=offset,
width=line_x_offset - offset[0] + drc["minwidth_metal2"], width=line_x_offset - offset.x+ drc["minwidth_metal2"],
height=drc["minwidth_metal1"]) height=drc["minwidth_metal1"])
self.add_via(layers=("metal1", "via1", "metal2"), self.add_via(layers=("metal1", "via1", "metal2"),
offset=[line_x_offset + self.gap_between_rails, offset=[line_x_offset + self.gap_between_rails,
offset[1] - self.via_shift], offset.y- self.via_shift],
rotate=90) rotate=90)
# Replica bitline (rblk to replica bitline input) # Replica bitline (rblk to replica bitline input)
layer_stack = ("metal2", "via1", "metal1") layer_stack = ("metal1", "via1", "metal2")
start = [self.rail_2_x_offsets[1] + 0.5 * drc["minwidth_metal2"], start = vector(self.rail_2_x_offsets[1] + 0.5 * drc["minwidth_metal2"],
self.output_port_gap] self.output_port_gap)
mid1 = [start[0], 0.5 * drc["minwidth_metal1"]] mid1 = vector(start.x, 0.5 * drc["minwidth_metal1"])
end = [self.replica_en_offset[0], mid1[1]] end = vector(self.replica_en_offset.x, mid1.y)
self.add_wire(layer_stack, [start, mid1, end]) self.add_wire(layer_stack, [start, mid1, end])
height = self.replica_en_offset[1] - end[1] + 0.5 * drc["minwidth_metal1"] height = self.replica_en_offset.y- end.y+ 0.5 * drc["minwidth_metal1"]
self.add_rect(layer="metal1", self.add_rect(layer="metal1",
offset=end - vector([0.5 * drc["minwidth_metal1"]] * 2), offset=end - vector([0.5 * drc["minwidth_metal1"]] * 2),
@ -514,7 +517,7 @@ class control_logic(design.design):
end = self.replica_out_offset - vector(0.5 * drc["minwidth_metal1"],0) end = self.replica_out_offset - vector(0.5 * drc["minwidth_metal1"],0)
self.add_rect(layer="metal3", self.add_rect(layer="metal3",
offset=start, offset=start,
width=self.replica_out_offset[0] - self.rail_2_x_offsets[2], width=self.replica_out_offset.x- self.rail_2_x_offsets[2],
height=drc["minwidth_metal3"]) height=drc["minwidth_metal3"])
self.add_via(layers=("metal2", "via2", "metal3"), self.add_via(layers=("metal2", "via2", "metal3"),
offset=start) offset=start)
@ -536,7 +539,7 @@ class control_logic(design.design):
self.add_rect(layer="metal1", self.add_rect(layer="metal1",
offset=self.nand3_2_vdd_position, offset=self.nand3_2_vdd_position,
width=(rail_2_x + drc["minwidth_metal2"] width=(rail_2_x + drc["minwidth_metal2"]
- self.nand3_2_vdd_position[0]), - self.nand3_2_vdd_position.x),
height=drc["minwidth_metal1"]) height=drc["minwidth_metal1"])
# Connection in horizontal metal2 vdd rail # Connection in horizontal metal2 vdd rail
@ -551,10 +554,10 @@ class control_logic(design.design):
# Connection of msf_vdd to inv1 vdd # Connection of msf_vdd to inv1 vdd
self.add_rect(layer="metal1", self.add_rect(layer="metal1",
offset=[self.msf_control_vdd_position[0], offset=[self.msf_control_vdd_position.x,
self.inv1_vdd_position[1]], self.inv1_vdd_position[1]],
width=drc["minwidth_metal1"], width=drc["minwidth_metal1"],
height=self.msf_control_vdd_position[1] - self.inv1_vdd_position[1]) height=self.msf_control_vdd_position.y- self.inv1_vdd_position[1])
vdd_offset = vector(self.replica_bitline.height,3 * drc["minwidth_metal1"]) vdd_offset = vector(self.replica_bitline.height,3 * drc["minwidth_metal1"])
@ -569,25 +572,25 @@ class control_logic(design.design):
for gnd_offset in self.msf_control_gnd_positions: for gnd_offset in self.msf_control_gnd_positions:
self.add_rect(layer="metal2", self.add_rect(layer="metal2",
offset=gnd_offset, offset=gnd_offset,
width=(self.rail_1_x_offsets[0] - gnd_offset[0] width=(self.rail_1_x_offsets[0] - gnd_offset.x
+ drc["minwidth_metal2"]), + drc["minwidth_metal2"]),
height=drc["minwidth_metal2"]) height=drc["minwidth_metal2"])
# Connect msf_control gnd to nand3 gnd # Connect msf_control gnd to nand3 gnd
self.add_rect(layer="metal1", self.add_rect(layer="metal1",
offset=self.nor2_1_gnd_position, offset=self.nor2_1_gnd_position,
width=self.offset_replica_bitline[0], width=self.offset_replica_bitline.x,
height=drc["minwidth_metal1"]) height=drc["minwidth_metal1"])
self.add_via(layers=("metal1", "via1", "metal2"), self.add_via(layers=("metal1", "via1", "metal2"),
offset=[self.rail_1_x_offsets[0] + self.gap_between_rails, offset=[self.rail_1_x_offsets[0] + self.gap_between_rails,
self.nor2_1_gnd_position[1] - self.via_shift], self.nor2_1_gnd_position.y- self.via_shift],
rotate=90) rotate=90)
# nand3 gnd to replica bitline gnd # nand3 gnd to replica bitline gnd
self.add_rect(layer="metal1", self.add_rect(layer="metal1",
offset=self.nand3_2_gnd_position, offset=self.nand3_2_gnd_position,
width=(self.offset_replica_bitline[0] width=(self.offset_replica_bitline.x
- self.nand3_2_gnd_position[0]), - self.nand3_2_gnd_position.x),
height=drc["minwidth_metal1"]) height=drc["minwidth_metal1"])
def add_input_routing(self): def add_input_routing(self):
@ -598,13 +601,13 @@ class control_logic(design.design):
self.OEb_position = self.msf_control_OEb_position self.OEb_position = self.msf_control_OEb_position
# Clk # Clk
clk_y = self.inv1_vdd_position[1] + 6 * drc["minwidth_metal1"] clk_y = self.inv1_vdd_position.y+ 6 * drc["minwidth_metal1"]
self.clk_position = vector(0, clk_y) self.clk_position = vector(0, clk_y)
# clk port to inv1 A # clk port to inv1 A
layer_stack = ("metal2", "via1", "metal1") layer_stack = ("metal1", "via1", "metal2")
start = self.inv1_A_position + vector(0, 0.5 * drc["minwidth_metal1"]) start = self.inv1_A_position + vector(0, 0.5 * drc["minwidth_metal1"])
mid1 = vector(self.inv1_A_position[0] - 2 * drc["minwidth_metal2"], mid1 = vector(self.inv1_A_position.x- 2 * drc["minwidth_metal2"],
start.y) start.y)
mid2 = vector(mid1.x, clk_y) mid2 = vector(mid1.x, clk_y)
self.clk_position = vector(0, mid2[1]) self.clk_position = vector(0, mid2[1])
@ -614,17 +617,17 @@ class control_logic(design.design):
# clk line to msf_control_clk # clk line to msf_control_clk
self.add_rect(layer="metal1", self.add_rect(layer="metal1",
offset=[self.msf_control_clk_position[0], offset=[self.msf_control_clk_position.x,
self.clk_position[1]], self.clk_position[1]],
width=drc["minwidth_metal1"], width=drc["minwidth_metal1"],
height=(self.msf_control_clk_position[1] height=(self.msf_control_clk_position.y
- self.clk_position[1])) - self.clk_position[1]))
# clk connection to nor2 A input # clk connection to nor2 A input
start = [self.inv1_A_position[0] - 2 * drc["minwidth_metal2"], start = self.inv1_A_position + vector(- 2 * drc["minwidth_metal2"],
self.inv1_A_position[1] + 0.5 * drc["minwidth_metal1"]] 0.5 * drc["minwidth_metal1"])
mid1 = [start[0] - 3 * drc["minwidth_metal2"], start[1]] mid1 = start - vector(3 * drc["minwidth_metal2"], 0)
mid2 = [mid1[0], self.nor2_1_A_position[1]] mid2 = [mid1.x, self.nor2_1_A_position.y]
self.add_path("metal1", [start, mid1, mid2, self.nor2_1_A_position]) self.add_path("metal1", [start, mid1, mid2, self.nor2_1_A_position])
@ -661,7 +664,7 @@ class control_logic(design.design):
height=self.nor2_1_Z_position.y + correct.y) height=self.nor2_1_Z_position.y + correct.y)
self.add_via(layers=("metal2", "via2", "metal3"), self.add_via(layers=("metal2", "via2", "metal3"),
offset=self.nor2_1_Z_position.scale(1, 0)) offset=self.nor2_1_Z_position.scale(1, 0))
self.tri_en_position = vector(self.nor2_1_Z_position[0], 0) self.tri_en_position = vector(self.nor2_1_Z_position.x, 0)
# tri_en_bar # tri_en_bar
correct = vector(drc["minwidth_metal2"], 0) correct = vector(drc["minwidth_metal2"], 0)
@ -671,7 +674,7 @@ class control_logic(design.design):
self.add_rect(layer="metal2", self.add_rect(layer="metal2",
offset=self.tri_en_bar_position, offset=self.tri_en_bar_position,
width=drc["minwidth_metal2"], width=drc["minwidth_metal2"],
height=self.nand2_1_Z_position[1] + drc["minwidth_metal1"]) height=self.nand2_1_Z_position.y+ drc["minwidth_metal1"])
self.add_via(layers=("metal2", "via2", "metal3"), self.add_via(layers=("metal2", "via2", "metal3"),
offset=self.tri_en_bar_position) offset=self.tri_en_bar_position)
@ -691,6 +694,6 @@ class control_logic(design.design):
self.add_rect(layer="metal2", self.add_rect(layer="metal2",
offset=self.s_en_position, offset=self.s_en_position,
width=drc["minwidth_metal2"], width=drc["minwidth_metal2"],
height=self.inv4_Z_position[1] + drc["minwidth_metal1"]) height=self.inv4_Z_position.y+ drc["minwidth_metal1"])
self.add_via(layers=("metal2", "via2", "metal3"), self.add_via(layers=("metal2", "via2", "metal3"),
offset=self.s_en_position) offset=self.s_en_position)

View File

@ -14,19 +14,6 @@ import importlib
# Current version of OpenRAM. # Current version of OpenRAM.
VERSION = "1.0" VERSION = "1.0"
# Output banner for file output and program execution.
BANNER = """\
##############################################################
# #
# OpenRAM Compiler v""" + VERSION + """ #
# #
# VLSI Design Automation Lab #
# UCSC CE Department #
# #
# VLSI Computer Architecture Research Group #
# Oklahoma State University ECE Department #
# #
##############################################################\n"""
USAGE = "usage: openram.py [options] <config file>\n" USAGE = "usage: openram.py [options] <config file>\n"
@ -81,6 +68,25 @@ def parse_args():
def get_opts(): def get_opts():
return(OPTS) return(OPTS)
def print_banner():
""" Conditionally print the banner to stdout """
global OPTS
if not OPTS.print_banner:
return
print "|==============================================================================|"
name = "OpenRAM Compiler v"+VERSION
print "|=========" + name.center(60) + "=========|"
print "|=========" + " ".center(60) + "=========|"
print "|=========" + "VLSI Design and Automation Lab".center(60) + "=========|"
print "|=========" + "University of California Santa Cruz CE Department".center(60) + "=========|"
print "|=========" + " ".center(60) + "=========|"
print "|=========" + "VLSI Computer Architecture Research Group".center(60) + "=========|"
print "|=========" + "Oklahoma State University ECE Department".center(60) + "=========|"
print "|=========" + " ".center(60) + "=========|"
print "|=========" + OPTS.openram_temp.center(60) + "=========|"
print "|==============================================================================|"
def init_openram(config_file): def init_openram(config_file):
"""Initialize the technology, paths, simulators, etc.""" """Initialize the technology, paths, simulators, etc."""
@ -134,6 +140,14 @@ def set_calibre():
debug.warning("Calibre not found. Not performing inline LVS/DRC.") debug.warning("Calibre not found. Not performing inline LVS/DRC.")
OPTS.check_lvsdrc = False OPTS.check_lvsdrc = False
def end_openram():
""" Clean up openram for a proper exit """
cleanup_paths()
def cleanup_paths():
# we should clean up this temp directory after execution...
if os.path.exists(OPTS.openram_temp):
shutil.rmtree(OPTS.openram_temp, ignore_errors=True)
def setup_paths(): def setup_paths():
""" Set up the non-tech related paths. """ """ Set up the non-tech related paths. """
@ -150,14 +164,11 @@ def setup_paths():
sys.path.append("{0}/tests".format(OPENRAM_HOME)) sys.path.append("{0}/tests".format(OPENRAM_HOME))
sys.path.append("{0}/characterizer".format(OPENRAM_HOME)) sys.path.append("{0}/characterizer".format(OPENRAM_HOME))
if not OPTS.openram_temp.endswith('/'): if not OPTS.openram_temp.endswith('/'):
OPTS.openram_temp += "/" OPTS.openram_temp += "/"
debug.info(1, "Temporary files saved in " + OPTS.openram_temp) debug.info(1, "Temporary files saved in " + OPTS.openram_temp)
# we should clean up this temp directory after execution... cleanup_paths()
if os.path.exists(OPTS.openram_temp):
shutil.rmtree(OPTS.openram_temp, ignore_errors=True)
# make the directory if it doesn't exist # make the directory if it doesn't exist
try: try:
@ -185,21 +196,46 @@ def set_spice():
debug.info(2,"Finding spice...") debug.info(2,"Finding spice...")
global OPTS global OPTS
# set the input dir for spice files if using ngspice (not needed for OPTS.spice_exe = ""
# hspice)
# Check if the preferred spice option exists in the path
for path in os.environ["PATH"].split(os.pathsep):
spice_exe = os.path.join(path, OPTS.spice_version)
# if it is found, then break and use first version
if is_exe(spice_exe):
debug.info(1, "Using spice: " + spice_exe)
OPTS.spice_exe = spice_exe
break
if not OPTS.force_spice and OPTS.spice_exe == "":
# if we didn't find the preferred version, try the other version and warn
prev_version=OPTS.spice_version
if OPTS.spice_version == "hspice":
OPTS.spice_version = "ngspice"
else:
OPTS.spice_version = "hspice"
debug.warning("Unable to find {0} so trying {1}".format(prev_version,OPTS.spice_version))
for path in os.environ["PATH"].split(os.pathsep):
spice_exe = os.path.join(path, OPTS.spice_version)
# if it is found, then break and use first version
if is_exe(spice_exe):
found_spice = True
debug.info(1, "Using spice: " + spice_exe)
OPTS.spice_exe = spice_exe
break
# set the input dir for spice files if using ngspice
if OPTS.spice_version == "ngspice": if OPTS.spice_version == "ngspice":
os.environ["NGSPICE_INPUT_DIR"] = "{0}".format(OPTS.openram_temp) os.environ["NGSPICE_INPUT_DIR"] = "{0}".format(OPTS.openram_temp)
# search for calibre in the path if OPTS.spice_exe == "":
for path in os.environ["PATH"].split(os.pathsep):
OPTS.spice_exe = os.path.join(path, OPTS.spice_version)
# if it is found, then break and use first version
if is_exe(OPTS.spice_exe):
debug.info(1, "Using spice: " + OPTS.spice_exe)
break
else:
# otherwise, give warning and procede # otherwise, give warning and procede
debug.warning("Spice not found. Unable to perform characterization.") if OPTS.force_spice:
debug.error("{0} not found. Unable to perform characterization.".format(OPTS.spice_version),1)
else:
debug.error("Neither hspice/ngspice not found. Unable to perform characterization.",1)
# imports correct technology directories for testing # imports correct technology directories for testing

View File

@ -329,7 +329,7 @@ class hierarchical_decoder(design.design):
# ADDING LABELS FOR OUTPUT SIDE OF THE 3:8 PRE-DECODER # ADDING LABELS FOR OUTPUT SIDE OF THE 3:8 PRE-DECODER
for inv_3x8 in range(8): for inv_3x8 in range(8):
if (self.num_inputs == 3): if (self.num_inputs == 3):
xoffset = self.pre3_8.x_off_inv_2 + self.inv.Z_position[0] xoffset = self.pre3_8.x_off_inv_2 + self.inv.Z_position.x
else: else:
xoffset = 0 xoffset = 0
@ -403,7 +403,7 @@ class hierarchical_decoder(design.design):
mirror=mirror) mirror=mirror)
self.add_rect(layer="metal1", self.add_rect(layer="metal1",
offset=[nand.width - correct, offset=[nand.width - correct,
y_off + y_dir * (nand.Z_position[1]-correct)], y_off + y_dir * (nand.Z_position.y-correct)],
width=drc["minwidth_metal1"], width=drc["minwidth_metal1"],
height=y_dir * drc["minwidth_metal1"]) height=y_dir * drc["minwidth_metal1"])
@ -454,9 +454,9 @@ class hierarchical_decoder(design.design):
# add output label for Row Decoder INVERTER array. # add output label for Row Decoder INVERTER array.
if (self.num_inputs == 4 or self.num_inputs == 5): if (self.num_inputs == 4 or self.num_inputs == 5):
x_off = self.nand2.width + self.inv.Z_position[0] x_off = self.nand2.width + self.inv.Z_position.x
else: else:
x_off = self.nand3.width + self.inv.Z_position[0] x_off = self.nand3.width + self.inv.Z_position.x
for row in range(self.rows): for row in range(self.rows):
if ((row % 2) == 0): if ((row % 2) == 0):
@ -502,10 +502,10 @@ class hierarchical_decoder(design.design):
+ inv_2x4 * (self.inv.height)) + inv_2x4 * (self.inv.height))
if (inv_2x4 % 2 == 0): if (inv_2x4 % 2 == 0):
pin_y = self.inv.Z_position[1] pin_y = self.inv.Z_position.y
else: else:
pin_y = (self.inv.height - drc["minwidth_metal1"] pin_y = (self.inv.height - drc["minwidth_metal1"]
- self.inv.Z_position[1]) - self.inv.Z_position.y)
yoffset = current_inv_height + pin_y yoffset = current_inv_height + pin_y
self.add_extend_rails(yoffset = yoffset, self.add_extend_rails(yoffset = yoffset,
@ -519,10 +519,10 @@ class hierarchical_decoder(design.design):
+ self.no_of_pre2x4 * self.pre2_4.height + self.no_of_pre2x4 * self.pre2_4.height
if (inv_3x8 % 2 == 0): if (inv_3x8 % 2 == 0):
pin_y = self.inv.Z_position[1] pin_y = self.inv.Z_position.y
else: else:
pin_y = (self.inv.height - drc["minwidth_metal1"] pin_y = (self.inv.height - drc["minwidth_metal1"]
- self.inv.Z_position[1]) - self.inv.Z_position.y)
yoffset = current_inv_height + pin_y yoffset = current_inv_height + pin_y
self.add_extend_rails(yoffset = yoffset, self.add_extend_rails(yoffset = yoffset,
@ -545,13 +545,13 @@ class hierarchical_decoder(design.design):
current_inv_height = self.predecoder_height + row_index * (self.inv.height) current_inv_height = self.predecoder_height + row_index * (self.inv.height)
if (row_index % 2 == 0): if (row_index % 2 == 0):
yoffset_A = current_inv_height + self.nand2.A_position[1] yoffset_A = current_inv_height + self.nand2.A_position.y
yoffset_B = current_inv_height + self.nand2.B_position[1] yoffset_B = current_inv_height + self.nand2.B_position.y
else: else:
base = current_inv_height + self.inv.height - drc["minwidth_metal1"] base = current_inv_height + self.inv.height - drc["minwidth_metal1"]
yoffset_A = base - self.nand2.A_position[1] yoffset_A = base - self.nand2.A_position.y
yoffset_B = base - self.nand2.B_position[1] yoffset_B = base - self.nand2.B_position.y
row_index = row_index + 1 row_index = row_index + 1
self.add_extend_rails(yoffset =yoffset_A, self.add_extend_rails(yoffset =yoffset_A,
@ -567,15 +567,15 @@ class hierarchical_decoder(design.design):
current_inv_height = self.predecoder_height + row_index * (self.inv.height) current_inv_height = self.predecoder_height + row_index * (self.inv.height)
if (row_index % 2 == 0): if (row_index % 2 == 0):
yoffset_A = current_inv_height + self.nand3.A_position[1] yoffset_A = current_inv_height + self.nand3.A_position.y
yoffset_B = current_inv_height + self.nand3.B_position[1] yoffset_B = current_inv_height + self.nand3.B_position.y
yoffset_C = current_inv_height + self.nand3.C_position[1] yoffset_C = current_inv_height + self.nand3.C_position.y
contact_C_yoffset = yoffset_C - self.contact_shift contact_C_yoffset = yoffset_C - self.contact_shift
else: else:
base = current_inv_height + self.inv.height - drc["minwidth_metal1"] base = current_inv_height + self.inv.height - drc["minwidth_metal1"]
yoffset_A = base - self.nand3.A_position[1] yoffset_A = base - self.nand3.A_position.y
yoffset_B = base - self.nand3.B_position[1] yoffset_B = base - self.nand3.B_position.y
yoffset_C = base - self.nand3.C_position[1] yoffset_C = base - self.nand3.C_position.y
contact_C_yoffset = yoffset_C contact_C_yoffset = yoffset_C
row_index = row_index + 1 row_index = row_index + 1

View File

@ -150,12 +150,12 @@ class hierarchical_predecode(design.design):
y_off = nand_input * (self.nand.height) y_off = nand_input * (self.nand.height)
mirror = "R0" mirror = "R0"
offset = [self.x_off_nand + self.nand.width, offset = [self.x_off_nand + self.nand.width,
y_off + self.nand.Z_position[1]] y_off + self.nand.Z_position.y]
else: else:
y_off = (nand_input + 1) * (self.nand.height) y_off = (nand_input + 1) * (self.nand.height)
mirror = "MX" mirror = "MX"
offset =[self.x_off_nand + self.nand.width, offset =[self.x_off_nand + self.nand.width,
y_off - self.nand.Z_position[1] - drc["minwidth_metal1"]] y_off - self.nand.Z_position.y - drc["minwidth_metal1"]]
self.add_inst(name=name, self.add_inst(name=name,
mod=self.nand, mod=self.nand,
offset=[self.x_off_nand, y_off], offset=[self.x_off_nand, y_off],
@ -175,22 +175,22 @@ class hierarchical_predecode(design.design):
def route_input_inverters_input(self,inv_rout,inv_in_offset): def route_input_inverters_input(self,inv_rout,inv_in_offset):
self.add_rect(layer="metal1", self.add_rect(layer="metal1",
offset=[self.rails_x_offset[inv_rout], offset=[self.rails_x_offset[inv_rout],
inv_in_offset[1]], inv_in_offset.y],
width=inv_in_offset[0] - self.rails_x_offset[inv_rout] + drc["minwidth_metal2"], width=inv_in_offset.x - self.rails_x_offset[inv_rout] + drc["minwidth_metal2"],
height=drc["minwidth_metal1"]) height=drc["minwidth_metal1"])
self.add_via(layers=("metal1", "via1", "metal2"), self.add_via(layers=("metal1", "via1", "metal2"),
offset=[self.rails_x_offset[inv_rout] + self.gap_between_rails, offset=[self.rails_x_offset[inv_rout] + self.gap_between_rails,
inv_in_offset[1] - self.via_shift], inv_in_offset.y - self.via_shift],
rotate=90) rotate=90)
def route_input_inverters_vdd(self,inv_vdd_offset): def route_input_inverters_vdd(self,inv_vdd_offset):
self.add_rect(layer="metal1", self.add_rect(layer="metal1",
offset=inv_vdd_offset, offset=inv_vdd_offset,
width=self.rails_x_offset[self.number_of_inputs] - inv_vdd_offset[0] + drc["minwidth_metal2"], width=self.rails_x_offset[self.number_of_inputs] - inv_vdd_offset.x + drc["minwidth_metal2"],
height=drc["minwidth_metal1"]) height=drc["minwidth_metal1"])
def route_input_inverters_gnd(self,inv_gnd_offset): def route_input_inverters_gnd(self,inv_gnd_offset):
self.add_rect(layer="metal1", self.add_rect(layer="metal1",
offset=inv_gnd_offset, offset=inv_gnd_offset,
width=self.rails_x_offset[self.number_of_inputs+1] - inv_gnd_offset[0] + drc["minwidth_metal2"], width=self.rails_x_offset[self.number_of_inputs+1] - inv_gnd_offset.x + drc["minwidth_metal2"],
height=drc["minwidth_metal1"]) height=drc["minwidth_metal1"])

View File

@ -65,22 +65,22 @@ class hierarchical_predecode2x4(hierarchical_predecode):
inv_in_offset = base + self.inv.A_position.scale(1,y_dir) inv_in_offset = base + self.inv.A_position.scale(1,y_dir)
inv_vdd_offset = base + self.inv.vdd_position.scale(1,y_dir) inv_vdd_offset = base + self.inv.vdd_position.scale(1,y_dir)
inv_gnd_offset = base + self.inv.gnd_position.scale(1,y_dir) inv_gnd_offset = base + self.inv.gnd_position.scale(1,y_dir)
out_y_mirrored = inv_vdd_offset[1] + output_shift + drc["minwidth_metal1"] out_y_mirrored = inv_vdd_offset.y+ output_shift + drc["minwidth_metal1"]
out_offset = [inv_out_offset[0], out_offset = [inv_out_offset.x,
inv_out_offset[1] * (1 + y_dir) / 2 inv_out_offset.y* (1 + y_dir) / 2
+ out_y_mirrored * (1 - y_dir) / 2] + out_y_mirrored * (1 - y_dir) / 2]
# output connection # output connection
correct = y_dir * (output_shift + drc["minwidth_metal1"]) correct = y_dir * (output_shift + drc["minwidth_metal1"])
off_via = [self.rails_x_offset[inv_rout + 4] + self.gap_between_rails, off_via = [self.rails_x_offset[inv_rout + 4] + self.gap_between_rails,
inv_vdd_offset[1] - self.via_shift - correct] inv_vdd_offset.y- self.via_shift - correct]
self.add_rect(layer="metal1", self.add_rect(layer="metal1",
offset=out_offset, offset=out_offset,
width=drc["minwidth_metal1"], width=drc["minwidth_metal1"],
height=(inv_vdd_offset[1] - inv_out_offset[1]) * y_dir - output_shift) height=(inv_vdd_offset.y- inv_out_offset.y) * y_dir - output_shift)
self.add_rect(layer="metal1", self.add_rect(layer="metal1",
offset=[inv_out_offset[0], offset=[inv_out_offset.x,
inv_vdd_offset[1] - correct], inv_vdd_offset.y- correct],
width=self.rails_x_offset[inv_rout + 4] - inv_out_offset[0] + drc["minwidth_metal2"], width=self.rails_x_offset[inv_rout + 4] - inv_out_offset.x+ drc["minwidth_metal2"],
height=drc["minwidth_metal1"]) height=drc["minwidth_metal1"])
self.add_via(layers = ("metal1", "via1", "metal2"), self.add_via(layers = ("metal1", "via1", "metal2"),
offset=off_via, offset=off_via,

View File

@ -49,11 +49,11 @@ class hierarchical_predecode3x8(hierarchical_predecode):
# output connection # output connection
correct = y_dir * (output_shift + drc["minwidth_metal1"]) correct = y_dir * (output_shift + drc["minwidth_metal1"])
off_via = [self.rails_x_offset[inv_rout + 5] + self.gap_between_rails, off_via = [self.rails_x_offset[inv_rout + 5] + self.gap_between_rails,
inv_vdd_offset[1] - self.via_shift - correct] inv_vdd_offset.y - self.via_shift - correct]
path1 = vector(inv_out_offset[0] + 0.5*drc["minwidth_metal1"], path1 = inv_out_offset + vector(0.5*drc["minwidth_metal1"],
inv_out_offset[1]- 1.5*drc["minwidth_metal1"] - correct) - 1.5*drc["minwidth_metal1"] - correct)
path2 = vector(path1.x, path2 = vector(path1.x,
inv_vdd_offset[1] + 0.5 * drc["minwidth_metal1"] - correct) inv_vdd_offset.y + 0.5 * drc["minwidth_metal1"] - correct)
path3 = vector(self.rails_x_offset[inv_rout + 5] + drc["minwidth_metal2"], path3 = vector(self.rails_x_offset[inv_rout + 5] + drc["minwidth_metal2"],
path2.y) path2.y)
self.add_path("metal1", [path1,path2,path3]) self.add_path("metal1", [path1,path2,path3])

View File

@ -46,13 +46,13 @@ class layout:
#***1,000,000 number is used to avoid empty sequences errors*** #***1,000,000 number is used to avoid empty sequences errors***
# FIXME Is this hard coded value ok?? # FIXME Is this hard coded value ok??
try: try:
lowestx1 = min(rect.offset[0] for rect in self.objs) lowestx1 = min(rect.offset.x for rect in self.objs)
lowesty1 = min(rect.offset[1] for rect in self.objs) lowesty1 = min(rect.offset.y for rect in self.objs)
except: except:
[lowestx1, lowesty1] = [1000000.0, 1000000.0] [lowestx1, lowesty1] = [1000000.0, 1000000.0]
try: try:
lowestx2 = min(inst.offset[0] for inst in self.insts) lowestx2 = min(inst.offset.x for inst in self.insts)
lowesty2 = min(inst.offset[1] for inst in self.insts) lowesty2 = min(inst.offset.y for inst in self.insts)
except: except:
[lowestx2, lowesty2] = [1000000.0, 1000000.0] [lowestx2, lowesty2] = [1000000.0, 1000000.0]
return vector(min(lowestx1, lowestx2), min(lowesty1, lowesty2)) return vector(min(lowestx1, lowestx2), min(lowesty1, lowesty2))
@ -76,21 +76,18 @@ class layout:
for i in range(len(attr_val)): for i in range(len(attr_val)):
# each unit in the list is a list coordinates # each unit in the list is a list coordinates
if isinstance(attr_val[i], (list,vector)): if isinstance(attr_val[i], (list,vector)):
attr_val[i] = vector([attr_val[i][0] - coordinate.x, attr_val[i] = vector(attr_val[i] - coordinate)
attr_val[i][1] - coordinate.y])
# the list itself is a coordinate # the list itself is a coordinate
else: else:
if len(attr_val)!=2: continue if len(attr_val)!=2: continue
for val in attr_val: for val in attr_val:
if not isinstance(val, (int, long, float)): continue if not isinstance(val, (int, long, float)): continue
setattr(self,attr_key, vector([attr_val[0] - coordinate.x, setattr(self,attr_key, vector(attr_val - coordinate))
attr_val[1] - coordinate.y]))
break break
# if is a vector coordinate # if is a vector coordinate
if isinstance(attr_val, vector): if isinstance(attr_val, vector):
setattr(self, attr_key, vector(attr_val[0] - coordinate.x, setattr(self, attr_key, vector(attr_val - coordinate))
attr_val[1] - coordinate.y))
@ -98,9 +95,9 @@ class layout:
"""Translates all 2d cartesian coordinates in a layout given """Translates all 2d cartesian coordinates in a layout given
the (x,y) offset""" the (x,y) offset"""
for obj in self.objs: for obj in self.objs:
obj.offset = obj.offset - coordinate obj.offset = vector(obj.offset - coordinate)
for inst in self.insts: for inst in self.insts:
inst.offset = inst.offset - coordinate inst.offset = vector(inst.offset - coordinate)
# FIXME: Make name optional and pick a random one if not specified # FIXME: Make name optional and pick a random one if not specified
def add_inst(self, name, mod, offset=[0,0], mirror="R0",rotate=0): def add_inst(self, name, mod, offset=[0,0], mirror="R0",rotate=0):
@ -177,7 +174,7 @@ class layout:
def add_wire(self, layers, coordinates, offset=None): def add_wire(self, layers, coordinates, offset=None):
"""Connects a routing path on given layer,coordinates,width. """Connects a routing path on given layer,coordinates,width.
The layers are the (vertical, via, horizontal). """ The layers are the (horizontal, via, vertical). """
import wire import wire
debug.info(3,"add wire " + str(layers) + " " + str(coordinates)) debug.info(3,"add wire " + str(layers) + " " + str(coordinates))
# Wires/paths are created so that the first point is (0,0) # Wires/paths are created so that the first point is (0,0)
@ -242,14 +239,14 @@ class layout:
Otherwise, start a new layout for dynamic generation.""" Otherwise, start a new layout for dynamic generation."""
# open the gds file if it exists or else create a blank layout # open the gds file if it exists or else create a blank layout
if os.path.isfile(self.gds_file): if os.path.isfile(self.gds_file):
debug.info(2, "opening %s" % self.gds_file) debug.info(3, "opening %s" % self.gds_file)
self.gds = gdsMill.VlsiLayout(units=GDS["unit"]) self.gds = gdsMill.VlsiLayout(units=GDS["unit"])
reader = gdsMill.Gds2reader(self.gds) reader = gdsMill.Gds2reader(self.gds)
reader.loadFromFile(self.gds_file) reader.loadFromFile(self.gds_file)
# TODO: parse the width/height # TODO: parse the width/height
# TODO: parse the pin locations # TODO: parse the pin locations
else: else:
debug.info(2, "creating structure %s" % self.name) debug.info(3, "creating structure %s" % self.name)
self.gds = gdsMill.VlsiLayout( self.gds = gdsMill.VlsiLayout(
name=self.name, units=GDS["unit"]) name=self.name, units=GDS["unit"])

View File

@ -68,7 +68,7 @@ class spice:
"""Reads the sp file (and parse the pins) from the library """Reads the sp file (and parse the pins) from the library
Otherwise, initialize it to null for dynamic generation""" Otherwise, initialize it to null for dynamic generation"""
if os.path.isfile(self.sp_file): if os.path.isfile(self.sp_file):
debug.info(2, "opening {0}".format(self.sp_file)) debug.info(3, "opening {0}".format(self.sp_file))
f = open(self.sp_file) f = open(self.sp_file)
self.spice = f.readlines() self.spice = f.readlines()
for i in range(len(self.spice)): for i in range(len(self.spice)):

View File

@ -160,16 +160,16 @@ class logic_effort_dc(design.design):
if end_inv < half_length: if end_inv < half_length:
end_i_offset = end_inv_offset + \ end_i_offset = end_inv_offset + \
self.inv.input_position.scale(1,-1) self.inv.input_position.scale(1,-1)
M2_end = [end_i_offset[0], end_i_offset[1] - 0.5 * drc["minwidth_metal2"]] M2_end = end_i_offset - vector(0, 0.5 * drc["minwidth_metal2"])
else: else:
end_i_offset = end_inv_offset + \ end_i_offset = end_inv_offset + \
self.inv.input_position.scale(-1,1) self.inv.input_position.scale(-1,1)
M2_end = [end_i_offset[0], end_i_offset[1] + 0.5 * drc["minwidth_metal2"]] M2_end = end_i_offset + vector(0, 0.5 * drc["minwidth_metal2"])
if start_inv < half_length and end_inv >= half_length: if start_inv < half_length and end_inv >= half_length:
mid = [half_length * self.inv.width \ mid = [half_length * self.inv.width \
- 0.5 * drc["minwidth_metal2"], M2_start[1]] - 0.5 * drc["minwidth_metal2"], M2_start[1]]
self.add_wire(("metal3", "via2", "metal2"), self.add_wire(("metal2", "via2", "metal3"),
[M2_start, mid, M2_end]) [M2_start, mid, M2_end])
else: else:
self.add_path(("metal2"), [M2_start, M2_end]) self.add_path(("metal2"), [M2_start, M2_end])

View File

@ -90,7 +90,7 @@ class nand_2(design.design):
def setup_layout_constants(self): def setup_layout_constants(self):
""" Calculate the layout constraints """ """ Calculate the layout constraints """
self.well_width = self.pmos1.active_position[0] \ self.well_width = self.pmos1.active_position.x \
+ 2 * self.pmos1.active_width \ + 2 * self.pmos1.active_width \
+ drc["active_to_body_active"] + \ + drc["active_to_body_active"] + \
drc["well_enclosure_active"] drc["well_enclosure_active"]
@ -127,9 +127,9 @@ class nand_2(design.design):
# determines the spacing between the edge and nmos (rail to active # determines the spacing between the edge and nmos (rail to active
# metal or poly_to_poly spacing) # metal or poly_to_poly spacing)
edge_to_nmos = max(drc["metal1_to_metal1"] edge_to_nmos = max(drc["metal1_to_metal1"]
- self.nmos1.active_contact_positions[0][1], - self.nmos1.active_contact_positions[0].y,
0.5 * (drc["poly_to_poly"] - drc["minwidth_metal1"]) 0.5 * (drc["poly_to_poly"] - drc["minwidth_metal1"])
- self.nmos1.poly_positions[0][1]) - self.nmos1.poly_positions[0].y)
# determine the position of the first transistor from the left # determine the position of the first transistor from the left
self.nmos_position1 = vector(0, 0.5 * drc["minwidth_metal1"] + edge_to_nmos) self.nmos_position1 = vector(0, 0.5 * drc["minwidth_metal1"] + edge_to_nmos)
@ -141,7 +141,7 @@ class nand_2(design.design):
self.connect_inst(["Z", "A", "net1", "gnd"]) self.connect_inst(["Z", "A", "net1", "gnd"])
self.nmos_position2 = vector(self.nmos2.active_width - self.nmos2.active_contact.width, self.nmos_position2 = vector(self.nmos2.active_width - self.nmos2.active_contact.width,
self.nmos_position1[1]) self.nmos_position1.y)
offset = self.nmos_position2 + vector(0,self.nmos2.height) offset = self.nmos_position2 + vector(0,self.nmos2.height)
self.add_inst(name="nmos2", self.add_inst(name="nmos2",
mod=self.nmos2, mod=self.nmos2,
@ -151,9 +151,9 @@ class nand_2(design.design):
# determines the spacing between the edge and pmos # determines the spacing between the edge and pmos
edge_to_pmos = max(drc["metal1_to_metal1"] \ edge_to_pmos = max(drc["metal1_to_metal1"] \
- self.pmos1.active_contact_positions[0][1], - self.pmos1.active_contact_positions[0].y,
0.5 * drc["poly_to_poly"] - 0.5 * drc["minwidth_metal1"] \ 0.5 * drc["poly_to_poly"] - 0.5 * drc["minwidth_metal1"] \
- self.pmos1.poly_positions[0][1]) - self.pmos1.poly_positions[0].y)
self.pmos_position1 = vector(0, self.height - 0.5 * drc["minwidth_metal1"] self.pmos_position1 = vector(0, self.height - 0.5 * drc["minwidth_metal1"]
- edge_to_pmos - self.pmos1.height) - edge_to_pmos - self.pmos1.height)
@ -213,13 +213,13 @@ class nand_2(design.design):
correct = vector(self.pmos1.active_contact.width - drc["minwidth_metal1"], correct = vector(self.pmos1.active_contact.width - drc["minwidth_metal1"],
0).scale(.5,0) 0).scale(.5,0)
poffset = self.pmos_position1 + self.pmos1.active_contact_positions[0] + correct poffset = self.pmos_position1 + self.pmos1.active_contact_positions[0] + correct
temp_height = self.height - poffset[1] temp_height = self.height - poffset.y
self.add_rect(layer="metal1", self.add_rect(layer="metal1",
offset=poffset, width=drc["minwidth_metal1"], offset=poffset, width=drc["minwidth_metal1"],
height=temp_height) height=temp_height)
poffset = vector(2 * self.pmos_position2.x + correct.x poffset = vector(2 * self.pmos_position2.x + correct.x
+ self.pmos2.active_contact_positions[0].x , poffset[1]) + self.pmos2.active_contact_positions[0].x , poffset.y)
self.add_rect(layer="metal1", self.add_rect(layer="metal1",
offset=poffset, offset=poffset,
width=drc["minwidth_metal1"], width=drc["minwidth_metal1"],
@ -244,14 +244,14 @@ class nand_2(design.design):
poly_length = (self.pmos_position1.y + self.pmos1.poly_positions[0].y poly_length = (self.pmos_position1.y + self.pmos1.poly_positions[0].y
- yoffset_nmos1 + drc["minwidth_poly"]) - yoffset_nmos1 + drc["minwidth_poly"])
for position in self.pmos1.poly_positions: for position in self.pmos1.poly_positions:
offset = [position[0], offset = vector(position.x,
yoffset_nmos1 - 0.5 * drc["minwidth_poly"]] yoffset_nmos1 - 0.5 * drc["minwidth_poly"])
self.add_rect(layer="poly", self.add_rect(layer="poly",
offset=offset, width=drc["minwidth_poly"], offset=offset, width=drc["minwidth_poly"],
height=poly_length) height=poly_length)
self.add_rect(layer="poly", self.add_rect(layer="poly",
offset=[offset[0] + self.pmos1.active_contact.width + 2 * drc["minwidth_poly"], offset=[offset.x + self.pmos1.active_contact.width + 2 * drc["minwidth_poly"],
offset[1]], offset.y],
width=drc["minwidth_poly"], width=drc["minwidth_poly"],
height=poly_length) height=poly_length)
@ -262,18 +262,18 @@ class nand_2(design.design):
- yoffset - self.pmos1.height + 0.5 * drc["minwidth_metal2"]) - yoffset - self.pmos1.height + 0.5 * drc["minwidth_metal2"])
for position in self.pmos1.active_contact_positions[1:][::2]: for position in self.pmos1.active_contact_positions[1:][::2]:
start = self.drain_position = [position[0] + 0.5 * drc["minwidth_metal1"] start = self.drain_position = vector(position.x + 0.5 * drc["minwidth_metal1"]
+ self.pmos_position2[0] + self.pmos_position2.x
+ self.pmos2.active_contact.first_layer_position[0] + self.pmos2.active_contact.first_layer_position.x
+ self.pmos2.active_contact.width / 2, + self.pmos2.active_contact.width / 2,
yoffset] yoffset)
mid1 = [start[0], mid1 = vector(start.x,
self.height - drc["minwidth_metal2"] - drc["metal2_to_metal2"] - self.height - drc["minwidth_metal2"] - drc["metal2_to_metal2"] -
self.pmos_size - drc["metal1_to_metal1"] - 0.5 * drc["minwidth_metal1"]] self.pmos_size - drc["metal1_to_metal1"] - 0.5 * drc["minwidth_metal1"])
end = [position[0] + 0.5 * drc["minwidth_metal1"] end = vector(position.x + 0.5 * drc["minwidth_metal1"]
+ self.pmos2.active_contact.second_layer_position[0], + self.pmos2.active_contact.second_layer_position.x,
self.pmos_position1[1] + self.pmos1.active_contact_positions[0][1]] self.pmos_position1.y + self.pmos1.active_contact_positions[0].y)
mid2 = [end[0], mid1[1]] mid2 = vector(end.x, mid1.y)
self.add_path("metal1",[start, mid1, mid2, end]) self.add_path("metal1",[start, mid1, mid2, end])
@ -290,7 +290,7 @@ class nand_2(design.design):
def route_input_gate_A(self): def route_input_gate_A(self):
""" routing for input A """ """ routing for input A """
xoffset = self.pmos1.poly_positions[0][0] xoffset = self.pmos1.poly_positions[0].x
yoffset = (self.height yoffset = (self.height
- (drc["minwidth_metal1"] - (drc["minwidth_metal1"]
+ drc["metal1_to_metal1"] + drc["metal1_to_metal1"]
@ -298,8 +298,8 @@ class nand_2(design.design):
+ drc["metal1_to_metal1"] + drc["metal1_to_metal1"]
+ self.pmos2.active_contact.second_layer_width)) + self.pmos2.active_contact.second_layer_width))
if (self.nmos_width == drc["minwidth_tx"]): if (self.nmos_width == drc["minwidth_tx"]):
yoffset = (self.pmos_position1[1] yoffset = (self.pmos_position1.y
+ self.pmos1.poly_positions[0][1] + self.pmos1.poly_positions[0].y
+ drc["poly_extend_active"] + drc["poly_extend_active"]
- (self.pmos1.active_contact.height - (self.pmos1.active_contact.height
- self.pmos1.active_height) / 2 - self.pmos1.active_height) / 2
@ -312,15 +312,15 @@ class nand_2(design.design):
size=(1,1), size=(1,1),
rotate=90) rotate=90)
offset = offset - self.poly_contact.first_layer_position.rotate().scale(1,0) offset = offset - self.poly_contact.first_layer_position.rotate_scale(1,0)
self.add_rect(layer="poly", self.add_rect(layer="poly",
offset=offset, offset=offset,
width=self.poly_contact.first_layer_position[1] + drc["minwidth_poly"], width=self.poly_contact.first_layer_position.y + drc["minwidth_poly"],
height=self.poly_contact.first_layer_width) height=self.poly_contact.first_layer_width)
input_length = (self.pmos1.poly_positions[0][0] input_length = (self.pmos1.poly_positions[0].x
- self.poly_contact.height) - self.poly_contact.height)
yoffset += self.poly_contact.via_layer_position[0] yoffset += self.poly_contact.via_layer_position.x
offset = self.input_position1 = vector(0, yoffset) offset = self.input_position1 = vector(0, yoffset)
self.add_rect(layer="metal1", self.add_rect(layer="metal1",
offset=offset, offset=offset,
@ -332,15 +332,15 @@ class nand_2(design.design):
def route_input_gate_B(self): def route_input_gate_B(self):
""" routing for input B """ """ routing for input B """
xoffset = (self.pmos2.poly_positions[0][0] xoffset = (self.pmos2.poly_positions[0].x
+ self.pmos_position2[0] + drc["minwidth_poly"]) + self.pmos_position2.x + drc["minwidth_poly"])
yoffset = (drc["minwidth_metal1"] yoffset = (drc["minwidth_metal1"]
+ drc["metal1_to_metal1"] + drc["metal1_to_metal1"]
+ self.nmos2.active_height + self.nmos2.active_height
+ drc["minwidth_metal1"]) + drc["minwidth_metal1"])
if (self.nmos_width == drc["minwidth_tx"]): if (self.nmos_width == drc["minwidth_tx"]):
yoffset = (self.nmos_position1[1] yoffset = (self.nmos_position1.y
+ self.nmos1.poly_positions[0][1] + self.nmos1.poly_positions[0].y
+ self.nmos1.poly_height + self.nmos1.poly_height
+ drc["metal1_to_metal1"]) + drc["metal1_to_metal1"])
offset = [xoffset, yoffset] offset = [xoffset, yoffset]
@ -351,18 +351,18 @@ class nand_2(design.design):
input_length = self.pmos2.poly_positions[0].x - self.poly_contact.height input_length = self.pmos2.poly_positions[0].x - self.poly_contact.height
self.input_position2 = vector(xoffset - self.poly_contact.width, self.input_position2 = vector(xoffset - self.poly_contact.width,
yoffset + self.poly_contact.via_layer_position[0]) yoffset + self.poly_contact.via_layer_position.x)
self.add_layout_pin(text="B", self.add_layout_pin(text="B",
layer="metal1", layer="metal1",
offset=self.input_position2.scale(0,1), offset=self.input_position2.scale(0,1),
width=(input_length + self.pmos_position2[0] + drc["minwidth_poly"]), width=(input_length + self.pmos_position2.x + drc["minwidth_poly"]),
height=drc["minwidth_metal1"]) height=drc["minwidth_metal1"])
def route_output(self): def route_output(self):
""" routing for output Z """ """ routing for output Z """
yoffset = (self.nmos1.height - 2 * drc["minwidth_metal1"] / 3 + yoffset = (self.nmos1.height - 2 * drc["minwidth_metal1"] / 3 +
(self.height - self.pmos1.height - self.nmos1.height - drc["minwidth_metal1"]) / 2 ) (self.height - self.pmos1.height - self.nmos1.height - drc["minwidth_metal1"]) / 2 )
xoffset = self.drain_position[0] xoffset = self.drain_position.x
offset = self.output_position = vector(xoffset, yoffset) offset = self.output_position = vector(xoffset, yoffset)
output_length = self.width - xoffset output_length = self.width - xoffset
self.add_layout_pin(text="Z", self.add_layout_pin(text="Z",
@ -420,9 +420,9 @@ class nand_2(design.design):
width=width, width=width,
height=self.pmos1.active_height) height=self.pmos1.active_height)
offset = vector(self.nmos_position2[0] + self.nmos1.active_position[0], offset = vector(self.nmos_position2.x + self.nmos1.active_position.x,
self.nmos_position1[1] - self.nmos1.active_height self.nmos_position1.y - self.nmos1.active_height
- self.nmos1.active_position[1] + self.nmos1.height) - self.nmos1.active_position.y + self.nmos1.height)
self.add_rect(layer="active", self.add_rect(layer="active",
offset=offset, offset=offset,
width=self.active_width, width=self.active_width,

View File

@ -99,7 +99,7 @@ class nand_3(design.design):
def setup_layout_constants(self): def setup_layout_constants(self):
""" setup layout constraints """ """ setup layout constraints """
self.well_width = self.nmos1.active_position[0] \ self.well_width = self.nmos1.active_position.x \
+ 3 * self.pmos1.active_width + drc["active_to_body_active"] \ + 3 * self.pmos1.active_width + drc["active_to_body_active"] \
+ drc["well_enclosure_active"] - self.nmos3.active_contact.width \ + drc["well_enclosure_active"] - self.nmos3.active_contact.width \
+ self.pmos1.active_contact.height + drc["minwidth_metal1"] \ + self.pmos1.active_contact.height + drc["minwidth_metal1"] \
@ -171,11 +171,11 @@ class nand_3(design.design):
# determines the spacing between the edge and pmos # determines the spacing between the edge and pmos
self.edge_to_pmos = max(drc["metal1_to_metal1"] self.edge_to_pmos = max(drc["metal1_to_metal1"]
- self.pmos1.active_contact_positions[0][1], - self.pmos1.active_contact_positions[0].y,
0.5 * drc["poly_to_poly"] - 0.5 * drc["minwidth_metal1"] 0.5 * drc["poly_to_poly"] - 0.5 * drc["minwidth_metal1"]
- self.pmos1.poly_positions[0][1]) - self.pmos1.poly_positions[0].y)
self.pmos_position1 = vector(self.nmos_position1[0], self.pmos_position1 = vector(self.nmos_position1.x,
self.height - 0.5 * drc["minwidth_metal1"] self.height - 0.5 * drc["minwidth_metal1"]
- self.pmos1.height - self.edge_to_pmos) - self.pmos1.height - self.edge_to_pmos)
self.add_inst(name="pmos1", self.add_inst(name="pmos1",
@ -216,10 +216,10 @@ class nand_3(design.design):
def connect_well_contacts(self): def connect_well_contacts(self):
""" Connect well contacts to vdd and gnd rail """ """ Connect well contacts to vdd and gnd rail """
well_tap_length = self.height - self.nwell_contact_position[1] well_tap_length = self.height - self.nwell_contact_position.y
xoffset = (self.nwell_contact_position[0] xoffset = (self.nwell_contact_position.x
+ self.nwell_contact.second_layer_position[0] + self.nwell_contact.second_layer_position.x
- self.nwell_contact.first_layer_position[0]) - self.nwell_contact.first_layer_position.x)
offset = [xoffset, self.nwell_contact_position.y] offset = [xoffset, self.nwell_contact_position.y]
self.add_rect(layer="metal1", self.add_rect(layer="metal1",
offset=offset, offset=offset,
@ -240,14 +240,14 @@ class nand_3(design.design):
correct = vector(self.pmos1.active_contact.width - drc["minwidth_metal1"], correct = vector(self.pmos1.active_contact.width - drc["minwidth_metal1"],
0).scale(0.5,0) 0).scale(0.5,0)
poffset = self.pmos_position1 + self.pmos1.active_contact_positions[0] + correct poffset = self.pmos_position1 + self.pmos1.active_contact_positions[0] + correct
temp_height = self.height - poffset[1] temp_height = self.height - poffset.y
self.add_rect(layer="metal1", self.add_rect(layer="metal1",
offset=poffset, offset=poffset,
width=drc["minwidth_metal1"], width=drc["minwidth_metal1"],
height=temp_height) height=temp_height)
poffset = [self.pmos_position3.x + self.pmos3.active_contact_positions[0].x + correct.x, poffset = [self.pmos_position3.x + self.pmos3.active_contact_positions[0].x + correct.x,
poffset[1]] poffset.y]
self.add_rect(layer="metal1", self.add_rect(layer="metal1",
offset=poffset, offset=poffset,
width=drc["minwidth_metal1"], width=drc["minwidth_metal1"],
@ -271,20 +271,20 @@ class nand_3(design.design):
poly_length = (self.pmos_position1.y + self.pmos1.poly_positions[0].y poly_length = (self.pmos_position1.y + self.pmos1.poly_positions[0].y
- yoffset_nmos1 + drc["minwidth_poly"]) - yoffset_nmos1 + drc["minwidth_poly"])
offset = [self.nmos_position1[0] + self.nmos1.poly_positions[0][0], offset = vector(self.nmos_position1.x + self.nmos1.poly_positions[0].x,
yoffset_nmos1 - drc["minwidth_poly"]] yoffset_nmos1 - drc["minwidth_poly"])
self.add_rect(layer="poly", self.add_rect(layer="poly",
offset=offset, offset=offset,
width=drc["minwidth_poly"], width=drc["minwidth_poly"],
height=poly_length) height=poly_length)
self.add_rect(layer="poly", self.add_rect(layer="poly",
offset=[offset[0] + self.pmos1.active_contact.width + 2 * drc["minwidth_poly"], offset=[offset.x + self.pmos1.active_contact.width + 2 * drc["minwidth_poly"],
offset[1]], offset.y],
width=drc["minwidth_poly"], width=drc["minwidth_poly"],
height=poly_length) height=poly_length)
self.add_rect(layer="poly", self.add_rect(layer="poly",
offset=[offset[0] + 2 * self.pmos1.active_contact.width + 4 * drc["minwidth_poly"], offset=[offset.x + 2 * self.pmos1.active_contact.width + 4 * drc["minwidth_poly"],
offset[1]], offset.y],
width=drc["minwidth_poly"], width=drc["minwidth_poly"],
height=poly_length) height=poly_length)
@ -294,7 +294,7 @@ class nand_3(design.design):
- drc["well_enclosure_active"] - drc["well_enclosure_active"]
+ drc["metal1_to_metal1"]) + drc["metal1_to_metal1"])
drain_length = (self.height - yoffset + 0.5 * drc["minwidth_metal1"] drain_length = (self.height - yoffset + 0.5 * drc["minwidth_metal1"]
- (self.pmos1.height - self.pmos1.active_contact_positions[0][1])) - (self.pmos1.height - self.pmos1.active_contact_positions[0].y))
layer_stack = ("metal1", "via1", "metal2") layer_stack = ("metal1", "via1", "metal2")
for position in self.pmos1.active_contact_positions[1:][::2]: for position in self.pmos1.active_contact_positions[1:][::2]:
diff_active_via = self.pmos2.active_contact.width - self.m1m2_via.second_layer_width diff_active_via = self.pmos2.active_contact.width - self.m1m2_via.second_layer_width
@ -315,7 +315,7 @@ class nand_3(design.design):
+ diff_active_via / 2) + diff_active_via / 2)
self.add_via(layer_stack,[xoffset,offset.y]) self.add_via(layer_stack,[xoffset,offset.y])
xoffset = (self.nmos_position3[0] + self.nmos3.active_position[0] xoffset = (self.nmos_position3.x + self.nmos3.active_position.x
+ self.nmos3.active_width - self.nmos3.active_contact.width / 2) + self.nmos3.active_width - self.nmos3.active_contact.width / 2)
self.drain_position = vector(xoffset, self.drain_position = vector(xoffset,
drc["minwidth_metal1"] + drc["metal1_to_metal1"]) drc["minwidth_metal1"] + drc["metal1_to_metal1"])
@ -343,11 +343,11 @@ class nand_3(design.design):
rotate=90) rotate=90)
self.add_rect(layer="poly", self.add_rect(layer="poly",
offset=offset + vector(drc["minwidth_poly"] / 2,0), offset=offset + vector(drc["minwidth_poly"] / 2,0),
width=-(self.poly_contact.first_layer_position[1] + drc["minwidth_poly"]), width=-(self.poly_contact.first_layer_position.y + drc["minwidth_poly"]),
height=self.poly_contact.first_layer_width) height=self.poly_contact.first_layer_width)
offset = vector(offset.x, offset = vector(offset.x,
self.pmos_position1[1] + self.pmos1.poly_positions[0][1]) self.pmos_position1.y + self.pmos1.poly_positions[0].y)
self.add_layout_pin(text="A", self.add_layout_pin(text="A",
layer="metal1", layer="metal1",
offset=offset, offset=offset,
@ -358,9 +358,9 @@ class nand_3(design.design):
def route_input_gate_B(self): def route_input_gate_B(self):
""" routing for input B """ """ routing for input B """
xoffset = self.pmos2.poly_positions[0][0] \ xoffset = self.pmos2.poly_positions[0].x \
+ self.pmos_position2[0] - drc["minwidth_poly"] + self.pmos_position2.x - drc["minwidth_poly"]
yoffset = self.nmos_position1[1] + self.nmos1.height \ yoffset = self.nmos_position1.y + self.nmos1.height \
- drc["well_enclosure_active"] + (self.nmos1.active_contact.height \ - drc["well_enclosure_active"] + (self.nmos1.active_contact.height \
- self.nmos1.active_height) / 2 \ - self.nmos1.active_height) / 2 \
+ drc["metal1_to_metal1"] + drc["metal1_to_metal1"]
@ -369,7 +369,7 @@ class nand_3(design.design):
self.add_via(layers=("metal1", "via1", "metal2"), self.add_via(layers=("metal1", "via1", "metal2"),
offset=[xoffset,yoffset]) offset=[xoffset,yoffset])
xoffset = self.pmos2.poly_positions[0][0] + self.pmos_position2[0] \ xoffset = self.pmos2.poly_positions[0].x + self.pmos_position2.x \
- drc["minwidth_poly"] + self.m1m2_via.width - drc["minwidth_poly"] + self.m1m2_via.width
length = -xoffset + self.m1m2_via.width length = -xoffset + self.m1m2_via.width
self.add_rect(layer="metal2", self.add_rect(layer="metal2",
@ -382,7 +382,7 @@ class nand_3(design.design):
layer="metal1", layer="metal1",
offset=self.B_position) offset=self.B_position)
xoffset = self.pmos_position1[0] + self.pmos1.active_position[0] \ xoffset = self.pmos_position1.x + self.pmos1.active_position.x \
- drc["metal1_to_metal1"] + (self.pmos1.active_contact.width \ - drc["metal1_to_metal1"] + (self.pmos1.active_contact.width \
- self.m1m2_via.second_layer_width) / 2 - self.m1m2_via.second_layer_width) / 2
self.add_via(layers=("metal1", "via1", "metal2"), self.add_via(layers=("metal1", "via1", "metal2"),
@ -395,9 +395,9 @@ class nand_3(design.design):
def route_input_gate_C(self): def route_input_gate_C(self):
""" routing for input A """ """ routing for input A """
xoffset = self.pmos3.poly_positions[0][0] \ xoffset = self.pmos3.poly_positions[0].x \
+ self.pmos_position3[0] - drc["minwidth_poly"] + self.pmos_position3.x - drc["minwidth_poly"]
yoffset = self.nmos_position1[1] + self.nmos1.height \ yoffset = self.nmos_position1.y + self.nmos1.height \
- drc["well_enclosure_active"] + (self.nmos1.active_contact.height \ - drc["well_enclosure_active"] + (self.nmos1.active_contact.height \
- self.nmos1.active_height) / 2 + drc["metal1_to_metal1"] - self.nmos1.active_height) / 2 + drc["metal1_to_metal1"]
@ -406,8 +406,8 @@ class nand_3(design.design):
self.add_via(layers=("metal1", "via1", "metal2"), self.add_via(layers=("metal1", "via1", "metal2"),
offset=[xoffset,yoffset]) offset=[xoffset,yoffset])
xoffset = self.pmos3.poly_positions[0][0] \ xoffset = self.pmos3.poly_positions[0].x \
+ self.pmos_position3[0] - drc["minwidth_poly"] \ + self.pmos_position3.x - drc["minwidth_poly"] \
+ self.m1m2_via.width + self.m1m2_via.width
length = -xoffset + self.m1m2_via.width length = -xoffset + self.m1m2_via.width
self.add_rect(layer="metal2", self.add_rect(layer="metal2",
@ -423,14 +423,14 @@ class nand_3(design.design):
width=self.m1m2_via.width, width=self.m1m2_via.width,
height=-drc["minwidth_metal2"] - drc["metal2_to_metal2"]) height=-drc["minwidth_metal2"] - drc["metal2_to_metal2"])
self.C_position = vector(0, self.C_position = vector(0,
self.B_position[1] - drc["metal2_to_metal2"] - drc["minwidth_metal1"] \ self.B_position.y - drc["metal2_to_metal2"] - drc["minwidth_metal1"] \
- (self.m1m2_via.second_layer_width - (self.m1m2_via.second_layer_width
- self.m1m2_via.first_layer_width)) - self.m1m2_via.first_layer_width))
self.add_label(text="C", self.add_label(text="C",
layer="metal1", layer="metal1",
offset=self.C_position) offset=self.C_position)
xoffset = self.pmos_position1[0] + self.pmos1.active_position[0] \ xoffset = self.pmos_position1.x + self.pmos1.active_position.x \
- drc["metal1_to_metal1"] + (self.pmos1.active_contact.width \ - drc["metal1_to_metal1"] + (self.pmos1.active_contact.width \
- self.m1m2_via.second_layer_width) / 2 - self.m1m2_via.second_layer_width) / 2
self.add_via(layers=("metal1", "via1", "metal2"), self.add_via(layers=("metal1", "via1", "metal2"),
@ -445,7 +445,7 @@ class nand_3(design.design):
def route_output(self): def route_output(self):
""" routing for output Z """ """ routing for output Z """
xoffset = self.nmos_position3[0] + self.nmos3.active_position[0] \ xoffset = self.nmos_position3.x + self.nmos3.active_position.x \
+ self.nmos3.active_width - self.nmos3.active_contact.width / 2 + self.nmos3.active_width - self.nmos3.active_contact.width / 2
yoffset = (self.nmos1.height + (self.height - drc["minwidth_metal1"] yoffset = (self.nmos1.height + (self.height - drc["minwidth_metal1"]
- self.pmos1.height - self.nmos1.height) / 2 - self.pmos1.height - self.nmos1.height) / 2
@ -463,11 +463,11 @@ class nand_3(design.design):
def extend_wells(self): def extend_wells(self):
""" extension of well """ """ extension of well """
middle_point = self.nmos_position1[1] + self.nmos1.pwell_position[1] \ middle_point = self.nmos_position1.y + self.nmos1.pwell_position.y \
+ self.nmos1.well_height + (self.pmos_position1[1] + self.nmos1.well_height + (self.pmos_position1.y
+ self.pmos1.nwell_position[1] + self.pmos1.nwell_position.y
- self.nmos_position1[1] - self.nmos_position1.y
- self.nmos1.pwell_position[1] - self.nmos1.pwell_position.y
- self.nmos1.well_height) / 2 - self.nmos1.well_height) / 2
offset = self.nwell_position = vector(0, middle_point) offset = self.nwell_position = vector(0, middle_point)
self.nwell_height = self.height - middle_point self.nwell_height = self.height - middle_point
@ -508,9 +508,9 @@ class nand_3(design.design):
width=width, width=width,
height=self.pmos1.active_height) height=self.pmos1.active_height)
offset = [self.nmos_position3[0] + self.nmos1.active_position[0], offset = [self.nmos_position3.x + self.nmos1.active_position.x,
self.nmos_position1[1] + self.nmos1.height self.nmos_position1.y + self.nmos1.height
- self.nmos1.active_position[1] - self.nmos1.active_height] - self.nmos1.active_position.y - self.nmos1.active_height]
self.add_rect(layer="active", self.add_rect(layer="active",
offset=offset, offset=offset,
width=self.active_width, width=self.active_width,

View File

@ -81,10 +81,10 @@ class nor_2(design.design):
0.5 * gate_to_gate - test_pmos.poly_positions[0].y) 0.5 * gate_to_gate - test_pmos.poly_positions[0].y)
route_margin = .5 * (self.poly_contact.second_layer_width route_margin = .5 * (self.poly_contact.second_layer_width
+ drc["minwidth_metal1"]) + drc["metal1_to_metal1"] + drc["minwidth_metal1"]) + drc["metal1_to_metal1"]
pmos_position = [0, self.height - 0.5 * drc["minwidth_metal1"] pmos_position = vector(0, self.height - 0.5 * drc["minwidth_metal1"]
- edge_to_pmos - test_pmos.height] - edge_to_pmos - test_pmos.height)
nmos_position = [0, 0.5 * drc["minwidth_metal1"] + edge_to_nmos] nmos_position = vector(0, 0.5 * drc["minwidth_metal1"] + edge_to_nmos)
leftspace = (0.7 * (pmos_position[1] - nmos_position[1]) leftspace = (0.7 * (pmos_position.y - nmos_position.y)
- 3 * route_margin - 2 * drc["metal1_to_metal1"]) - 3 * route_margin - 2 * drc["metal1_to_metal1"])
if leftspace >= 0: if leftspace >= 0:
break break
@ -209,10 +209,10 @@ class nor_2(design.design):
self.nwell_contact_position = vector(xoffset, yoffset) self.nwell_contact_position = vector(xoffset, yoffset)
self.nwell_contact=self.add_contact(layer_stack,self.nwell_contact_position,(1,self.pmos1.num_of_tacts)) self.nwell_contact=self.add_contact(layer_stack,self.nwell_contact_position,(1,self.pmos1.num_of_tacts))
xoffset = self.nmos_position2[0] + (self.nmos1.active_position[0] xoffset = self.nmos_position2.x + (self.nmos1.active_position.x
+ self.nmos1.active_width + self.nmos1.active_width
+ drc["active_to_body_active"]) + drc["active_to_body_active"])
yoffset = (self.nmos_position1[1] + self.nmos1.height yoffset = (self.nmos_position1.y + self.nmos1.height
- self.nmos1.active_contact_positions[0].y - self.nmos1.active_contact_positions[0].y
- self.nmos1.active_contact.height) - self.nmos1.active_contact.height)
self.pwell_contact_position = vector(xoffset, yoffset) self.pwell_contact_position = vector(xoffset, yoffset)
@ -222,7 +222,7 @@ class nor_2(design.design):
def route(self): def route(self):
self.route_pins() self.route_pins()
self.connect_well_contacts() self.connect_well_contacts()
M1_track = (self.B_position[1] + drc["metal1_to_metal1"] M1_track = (self.B_position.y + drc["metal1_to_metal1"]
+ .5 * (self.poly_contact.second_layer_width + .5 * (self.poly_contact.second_layer_width
+ drc["minwidth_metal1"])) + drc["minwidth_metal1"]))
self.connect_tx(M1_track) self.connect_tx(M1_track)
@ -230,11 +230,11 @@ class nor_2(design.design):
def connect_well_contacts(self): def connect_well_contacts(self):
""" Connect well contacts to vdd and gnd rail """ """ Connect well contacts to vdd and gnd rail """
well_tap_length = self.height - self.nwell_contact_position[1] well_tap_length = self.height - self.nwell_contact_position.y
xoffset = (self.nwell_contact_position.x xoffset = (self.nwell_contact_position.x
+ self.nwell_contact.second_layer_position.x + self.nwell_contact.second_layer_position.x
- self.nwell_contact.first_layer_position.x) - self.nwell_contact.first_layer_position.x)
offset = [xoffset, self.nwell_contact_position[1]] offset = [xoffset, self.nwell_contact_position.y]
self.add_rect(layer="metal1", self.add_rect(layer="metal1",
offset=offset, offset=offset,
width=drc["minwidth_metal1"], width=drc["minwidth_metal1"],
@ -243,7 +243,7 @@ class nor_2(design.design):
offset = (self.pwell_contact_position.scale(1,0) offset = (self.pwell_contact_position.scale(1,0)
+ self.pwell_contact.second_layer_position.scale(1,0) + self.pwell_contact.second_layer_position.scale(1,0)
- self.pwell_contact.first_layer_position.scale(1,0)) - self.pwell_contact.first_layer_position.scale(1,0))
well_tap_length = self.pwell_contact_position[1] well_tap_length = self.pwell_contact_position.y
self.add_rect(layer="metal1", self.add_rect(layer="metal1",
offset=offset, offset=offset,
width=drc["minwidth_metal1"], width=drc["minwidth_metal1"],
@ -257,7 +257,7 @@ class nor_2(design.design):
if i % 2 == 0: if i % 2 == 0:
correct = self.pmos1.active_contact.second_layer_position.scale(1,0) correct = self.pmos1.active_contact.second_layer_position.scale(1,0)
drain_posistion = contact_pos + correct drain_posistion = contact_pos + correct
height = self.vdd_position[1] - drain_posistion[1] height = self.vdd_position.y - drain_posistion.y
self.add_rect(layer="metal1", self.add_rect(layer="metal1",
offset=drain_posistion, offset=drain_posistion,
width=drc["minwidth_metal1"], width=drc["minwidth_metal1"],
@ -268,7 +268,7 @@ class nor_2(design.design):
+ vector(self.pmos1.active_contact.second_layer_width, + vector(self.pmos1.active_contact.second_layer_width,
0).scale(.5,0)) 0).scale(.5,0))
source_position = contact_pos + correct source_position = contact_pos + correct
mid = [self.pmos_position2[0], M1_track] mid = [self.pmos_position2.x, M1_track]
self.add_path("metal1", [source_position, mid]) self.add_path("metal1", [source_position, mid])
# the second pmos # the second pmos
@ -279,13 +279,13 @@ class nor_2(design.design):
correct= (self.pmos2.active_contact.second_layer_position.scale(1,0) correct= (self.pmos2.active_contact.second_layer_position.scale(1,0)
+ vector(0.5 * self.pmos2.active_contact.second_layer_width,0)) + vector(0.5 * self.pmos2.active_contact.second_layer_width,0))
source_position = pmos_active + correct source_position = pmos_active + correct
mid = [self.pmos_position2[0], M1_track] mid = [self.pmos_position2.x, M1_track]
self.add_path("metal1", [source_position, mid]) self.add_path("metal1", [source_position, mid])
# two nmos source to gnd # two nmos source to gnd
source_posistion1 = (self.nmos_position1 source_posistion1 = (self.nmos_position1
+ self.nmos1.active_contact_positions[0] + self.nmos1.active_contact_positions[0]
+ self.nmos1.active_contact.second_layer_position.scale(1,0)) + self.nmos1.active_contact.second_layer_position.scale(1,0))
height = self.gnd_position[1] - source_posistion1[1] height = self.gnd_position.y - source_posistion1.y
self.add_rect(layer="metal1", self.add_rect(layer="metal1",
offset=source_posistion1, offset=source_posistion1,
width=drc["minwidth_metal1"], width=drc["minwidth_metal1"],
@ -294,7 +294,7 @@ class nor_2(design.design):
source_posistion2 = (self.nmos_position2 source_posistion2 = (self.nmos_position2
+ self.nmos2.active_contact_positions[1] + self.nmos2.active_contact_positions[1]
+ self.nmos2.active_contact.second_layer_position.scale(1,0)) + self.nmos2.active_contact.second_layer_position.scale(1,0))
height = self.gnd_position[1] - source_posistion2[1] height = self.gnd_position.y - source_posistion2.y
self.add_rect(layer="metal1", self.add_rect(layer="metal1",
offset=source_posistion2, offset=source_posistion2,
width=drc["minwidth_metal1"], width=drc["minwidth_metal1"],
@ -310,22 +310,22 @@ class nor_2(design.design):
pmos_gate = (self.pmos_position1 pmos_gate = (self.pmos_position1
+ self.pmos1.poly_positions[i] + self.pmos1.poly_positions[i]
+ vector(0.5 * drc["minwidth_poly"], 0)) + vector(0.5 * drc["minwidth_poly"], 0))
mid1 = [pmos_gate[0], pmos_gate[1] - drc["poly_to_active"]] mid1 = [pmos_gate.x, pmos_gate.y - drc["poly_to_active"]]
self.add_path("poly", [nmos_gate, mid1, pmos_gate]) self.add_path("poly", [nmos_gate, mid1, pmos_gate])
# connect pmos2 poly # connect pmos2 poly
nmos_gate = [self.nmos_position2[0] \ nmos_gate = vector(self.nmos_position2[0]
+ self.nmos2.poly_positions[0][0] + self.nmos2.poly_positions[0].x
+ 0.5 * drc["minwidth_poly"], \ + 0.5 * drc["minwidth_poly"],
self.nmos_position1[1] \ self.nmos_position1.y
+ self.nmos1.poly_positions[0][1]] + self.nmos1.poly_positions[0].y)
for i in range(len(self.pmos2.poly_positions)): for i in range(len(self.pmos2.poly_positions)):
pmos_gate = (self.pmos_position2 pmos_gate = (self.pmos_position2
+ self.pmos2.poly_positions[i] + self.pmos2.poly_positions[i]
+ vector(0.5 * drc["minwidth_poly"], 0)) + vector(0.5 * drc["minwidth_poly"], 0))
mid1 = [pmos_gate[0], mid1 = vector(pmos_gate.x,
nmos_gate[1] + self.nmos2.height \ nmos_gate.y + self.nmos2.height
+ drc["poly_to_active"]] + drc["poly_to_active"])
self.add_path("poly", [nmos_gate, mid1, pmos_gate]) self.add_path("poly", [nmos_gate, mid1, pmos_gate])
def route_pins(self): def route_pins(self):
@ -350,15 +350,15 @@ class nor_2(design.design):
rotate=90) rotate=90)
# connect gate input to tx gate # connect gate input to tx gate
offset = self.A_position - vector(self.poly_contact.first_layer_position[1], offset = self.A_position - vector(self.poly_contact.first_layer_position.y,
0.5 * self.poly_contact.width) 0.5 * self.poly_contact.width)
self.add_rect(layer="poly", self.add_rect(layer="poly",
offset=offset, offset=offset,
width=self.poly_contact.first_layer_position[1] + drc["minwidth_poly"], width=self.poly_contact.first_layer_position.y + drc["minwidth_poly"],
height=self.poly_contact.first_layer_width) height=self.poly_contact.first_layer_width)
# extend the metal to the boundary of the cell # extend the metal to the boundary of the cell
input_length = self.A_position[0] input_length = self.A_position.x
offset = [0, self.A_position[1] - 0.5 * drc["minwidth_metal1"]] offset = [0, self.A_position.y - 0.5 * drc["minwidth_metal1"]]
self.add_layout_pin(text="A", self.add_layout_pin(text="A",
layer="metal1", layer="metal1",
offset=offset, offset=offset,
@ -367,9 +367,9 @@ class nor_2(design.design):
def route_input_B(self): def route_input_B(self):
"""create input B layout """ """create input B layout """
xoffset = self.pmos2.poly_positions[0][0] \ xoffset = self.pmos2.poly_positions[0].x \
+ self.pmos_position2[0] + self.pmos_position2.x
yoffset = self.A_position[1] \ yoffset = self.A_position.y \
+ 0.5 * (self.poly_contact.second_layer_width \ + 0.5 * (self.poly_contact.second_layer_width \
+ drc["minwidth_metal1"]) + drc["metal1_to_metal1"] + drc["minwidth_metal1"]) + drc["metal1_to_metal1"]
self.B_position = vector(xoffset, yoffset) self.B_position = vector(xoffset, yoffset)
@ -380,13 +380,13 @@ class nor_2(design.design):
self.add_rect(layer="poly", self.add_rect(layer="poly",
offset=offset, offset=offset,
width=-(self.poly_contact.first_layer_position[1] + drc["minwidth_poly"]), width=-(self.poly_contact.first_layer_position.y + drc["minwidth_poly"]),
height=self.poly_contact.first_layer_width) height=self.poly_contact.first_layer_width)
self.add_layout_pin(text="B", self.add_layout_pin(text="B",
layer="metal1", layer="metal1",
offset=[0, offset=[0,
self.B_position[1] - 0.5 * drc["minwidth_metal1"]], self.B_position.y - 0.5 * drc["minwidth_metal1"]],
width=self.B_position[0], width=self.B_position.x,
height=drc["minwidth_metal1"]) height=drc["minwidth_metal1"])
def route_output(self): def route_output(self):
@ -398,7 +398,7 @@ class nor_2(design.design):
+ self.nmos1.active_contact.second_layer_position + self.nmos1.active_contact.second_layer_position
+ vector(self.nmos1.active_contact.second_layer_width, + vector(self.nmos1.active_contact.second_layer_width,
0).scale(0.5, 0)) 0).scale(0.5, 0))
mid = [nmos_contact[0], self.A_position[1]] mid = [nmos_contact.x, self.A_position.y]
self.add_path("metal1", [self.Z_position, mid, nmos_contact]) self.add_path("metal1", [self.Z_position, mid, nmos_contact])
for i in range(len(self.pmos2.poly_positions) + 1): for i in range(len(self.pmos2.poly_positions) + 1):
@ -412,19 +412,19 @@ class nor_2(design.design):
offset = pmos_contact - vector(0.5 * self.m1m2_via.width, 0) offset = pmos_contact - vector(0.5 * self.m1m2_via.width, 0)
self.add_via(layers=("metal1", "via1", "metal2"), self.add_via(layers=("metal1", "via1", "metal2"),
offset=offset) offset=offset)
mid = [pmos_contact[0], self.Z_position[1]] mid = [pmos_contact.x, self.Z_position.y]
self.add_wire(("metal2", "via1", "metal1"), self.add_wire(("metal1", "via1", "metal2"),
[self.Z_position, mid, pmos_contact]) [self.Z_position, mid, pmos_contact])
def extend_wells(self): def extend_wells(self):
""" extend well for well contact""" """ extend well for well contact"""
middle_point = (self.nmos_position1[1] middle_point = (self.nmos_position1.y
+ self.nmos1.pwell_position[1] + self.nmos1.pwell_position.y
+ self.nmos1.well_height + self.nmos1.well_height
+ (self.pmos_position1[1] + (self.pmos_position1.y
+ self.pmos1.nwell_position[1] + self.pmos1.nwell_position.y
- self.nmos_position1[1] - self.nmos_position1.y
- self.nmos1.pwell_position[1] - self.nmos1.pwell_position.y
- self.nmos1.well_height) / 2 ) - self.nmos1.well_height) / 2 )
self.nwell_position = vector(0, middle_point) self.nwell_position = vector(0, middle_point)
self.nwell_height = self.height - middle_point self.nwell_height = self.height - middle_point

View File

@ -34,8 +34,7 @@ if len(args) < 1:
print globals.USAGE print globals.USAGE
sys.exit(2) sys.exit(2)
if OPTS.print_banner: globals.print_banner()
print globals.BANNER
globals.init_openram(args[0]) globals.init_openram(args[0])
@ -94,7 +93,7 @@ s.gds_write(gdsname)
# Run Characterizer on the design # Run Characterizer on the design
sram_file = spname sram_file = spname
if OPTS.run_pex: if OPTS.use_pex:
sram_file = OPTS.out_path + "temp_pex.sp" sram_file = OPTS.out_path + "temp_pex.sp"
calibre.run_pex(s.name, gdsname, spname, output=sram_file) calibre.run_pex(s.name, gdsname, spname, output=sram_file)
@ -117,5 +116,6 @@ libname = OPTS.out_path + s.name + ".lib"
print "LIB: Writing to {0}".format(libname) print "LIB: Writing to {0}".format(libname)
lib.lib(libname,s,sram_file) lib.lib(libname,s,sram_file)
globals.end_openram()
print "End: ", datetime.datetime.now() print "End: ", datetime.datetime.now()

View File

@ -1,16 +1,18 @@
import optparse import optparse
import getpass import getpass
import os
class options(optparse.Values): class options(optparse.Values):
""" """
Class for holding all of the OpenRAM options. Class for holding all of the OpenRAM options.
""" """
# This is the technology directory. # This is the technology directory.
openram_tech = "" openram_tech = ""
# This is the name of the technology. # This is the name of the technology.
tech_name = "" tech_name = ""
# This is the temp directory where all intermediate results are stored. # This is the temp directory where all intermediate results are stored.
openram_temp = "/tmp/openram_{0}_temp/".format(getpass.getuser()) openram_temp = "/tmp/openram_{0}_{1}_temp/".format(getpass.getuser(),os.getpid())
# This is the verbosity level to control debug information. 0 is none, 1 # This is the verbosity level to control debug information. 0 is none, 1
# is minimal, etc. # is minimal, etc.
debug_level = 0 debug_level = 0
@ -18,6 +20,8 @@ class options(optparse.Values):
check_lvsdrc = True check_lvsdrc = True
# Variable to select the variant of spice (hspice or ngspice right now) # Variable to select the variant of spice (hspice or ngspice right now)
spice_version = "hspice" spice_version = "hspice"
# Should we fall back if we can't find our preferred spice?
force_spice = False
# Should we print out the banner at startup # Should we print out the banner at startup
print_banner = True print_banner = True
# The Calibre executable being used which is derived from the user PATH. # The Calibre executable being used which is derived from the user PATH.
@ -25,7 +29,7 @@ class options(optparse.Values):
# The spice executable being used which is derived from the user PATH. # The spice executable being used which is derived from the user PATH.
spice_exe = "" spice_exe = ""
# Run with extracted parasitics # Run with extracted parasitics
run_pex = False use_pex = False
# Trim noncritical memory cells for simulation speed-up # Trim noncritical memory cells for simulation speed-up
trim_noncritical = False trim_noncritical = False
# Define the output file paths # Define the output file paths

View File

@ -19,7 +19,7 @@ class path(design.design):
name = "path_{0}".format(path.unique_path_id) name = "path_{0}".format(path.unique_path_id)
path.unique_path_id += 1 path.unique_path_id += 1
design.design.__init__(self, name) design.design.__init__(self, name)
debug.info(2, "create path obj {0}".format(name)) debug.info(3, "create path obj {0}".format(name))
self.name = name self.name = name
self.layer_name = layer self.layer_name = layer

View File

@ -109,7 +109,7 @@ class pinv(design.design):
"""Sets up constant variables""" """Sets up constant variables"""
# the well width is determined the multi-finger PMOS device width plus # the well width is determined the multi-finger PMOS device width plus
# the well contact width and enclosure # the well contact width and enclosure
self.well_width = self.pmos.active_position[0] \ self.well_width = self.pmos.active_position.x \
+ self.pmos.active_width \ + self.pmos.active_width \
+ drc["active_to_body_active"] \ + drc["active_to_body_active"] \
+ self.pmos.active_contact.width \ + self.pmos.active_contact.width \
@ -140,10 +140,10 @@ class pinv(design.design):
# determines the spacing between the edge and nmos (rail to active # determines the spacing between the edge and nmos (rail to active
# metal or poly_to_poly spacing) # metal or poly_to_poly spacing)
edge_to_nmos = max(drc["metal1_to_metal1"] \ edge_to_nmos = max(drc["metal1_to_metal1"] \
- self.nmos.active_contact_positions[0][1], - self.nmos.active_contact_positions[0].y,
0.5 * drc["poly_to_poly"] \ 0.5 * drc["poly_to_poly"] \
- 0.5 * drc["minwidth_metal1"] \ - 0.5 * drc["minwidth_metal1"] \
- self.nmos.poly_positions[0][1]) - self.nmos.poly_positions[0].y)
self.nmos_position = vector(0, 0.5 * drc["minwidth_metal1"] + edge_to_nmos) self.nmos_position = vector(0, 0.5 * drc["minwidth_metal1"] + edge_to_nmos)
offset = self.nmos_position + vector(0,self.nmos.height) offset = self.nmos_position + vector(0,self.nmos.height)
self.add_inst(name="pinv_nmos", self.add_inst(name="pinv_nmos",
@ -154,10 +154,10 @@ class pinv(design.design):
# determines the spacing between the edge and pmos # determines the spacing between the edge and pmos
edge_to_pmos = max(drc["metal1_to_metal1"] \ edge_to_pmos = max(drc["metal1_to_metal1"] \
- self.pmos.active_contact_positions[0][1], - self.pmos.active_contact_positions[0].y,
0.5 * drc["poly_to_poly"] \ 0.5 * drc["poly_to_poly"] \
- 0.5 * drc["minwidth_metal1"] \ - 0.5 * drc["minwidth_metal1"] \
- self.pmos.poly_positions[0][1]) - self.pmos.poly_positions[0].y)
self.pmos_position = vector(0, self.pmos_position = vector(0,
self.height - 0.5 * drc["minwidth_metal1"] self.height - 0.5 * drc["minwidth_metal1"]
- edge_to_pmos - self.pmos.height) - edge_to_pmos - self.pmos.height)
@ -168,9 +168,9 @@ class pinv(design.design):
def extend_wells(self): def extend_wells(self):
"""Extends the n/p wells to cover whole layout""" """Extends the n/p wells to cover whole layout"""
nmos_top_yposition = self.nmos_position[1] + self.nmos.height nmos_top_yposition = self.nmos_position.y + self.nmos.height
# calculates the length between the pmos and nmos # calculates the length between the pmos and nmos
middle_length = self.pmos_position[1] - nmos_top_yposition middle_length = self.pmos_position.y - nmos_top_yposition
# calculate the middle point between the pmos and nmos # calculate the middle point between the pmos and nmos
middle_yposition = nmos_top_yposition + 0.5 * middle_length middle_yposition = nmos_top_yposition + 0.5 * middle_length
@ -185,7 +185,7 @@ class pinv(design.design):
width=self.well_width, width=self.well_width,
height=self.nwell_height) height=self.nwell_height)
self.pwell_position = [0, 0] self.pwell_position = vector(0, 0)
self.pwell_height = middle_yposition self.pwell_height = middle_yposition
self.add_rect(layer="pwell", self.add_rect(layer="pwell",
offset=self.pwell_position, width=self.well_width, offset=self.pwell_position, width=self.well_width,
@ -239,14 +239,14 @@ class pinv(design.design):
def connect_poly(self): def connect_poly(self):
"""Connects the poly from nmos to pmos (as well if it is multi-fingered)""" """Connects the poly from nmos to pmos (as well if it is multi-fingered)"""
# Calculates the y-coordinate of the top of the poly of the nmos # Calculates the y-coordinate of the top of the poly of the nmos
nmos_top_poly_yposition = self.nmos_position[1] \ nmos_top_poly_yposition = self.nmos_position.y \
+ self.nmos.height \ + self.nmos.height \
- self.nmos.poly_positions[0][1] - self.nmos.poly_positions[0].y
poly_length = self.pmos_position[1] + self.pmos.poly_positions[0][1] \ poly_length = self.pmos_position.y + self.pmos.poly_positions[0].y \
- nmos_top_poly_yposition - nmos_top_poly_yposition
for position in self.pmos.poly_positions: for position in self.pmos.poly_positions:
offset = [position[0], nmos_top_poly_yposition] offset = [position.x, nmos_top_poly_yposition]
self.add_rect(layer="poly", self.add_rect(layer="poly",
offset=offset, offset=offset,
width=drc["minwidth_poly"], width=drc["minwidth_poly"],
@ -257,14 +257,14 @@ class pinv(design.design):
# Determines the top y-coordinate of the nmos drain metal layer # Determines the top y-coordinate of the nmos drain metal layer
yoffset = self.nmos.height \ yoffset = self.nmos.height \
- 0.5 * drc["minwidth_metal1"] \ - 0.5 * drc["minwidth_metal1"] \
- self.nmos.active_contact_positions[0][1] - self.nmos.active_contact_positions[0].y
drain_length = self.height - yoffset + drc["minwidth_metal1"] \ drain_length = self.height - yoffset + drc["minwidth_metal1"] \
- (self.pmos.height - (self.pmos.height
- self.pmos.active_contact_positions[0][1]) - self.pmos.active_contact_positions[0].y)
for position in self.pmos.active_contact_positions[1:][::2]: for position in self.pmos.active_contact_positions[1:][::2]:
offset = [position[0] + self.pmos.active_contact.second_layer_position[0], offset = [position.x + self.pmos.active_contact.second_layer_position.x,
yoffset] yoffset]
self.drain_position = offset self.drain_position = vector(offset)
self.add_rect(layer="metal1", self.add_rect(layer="metal1",
offset=offset, offset=offset,
width=self.nmos.active_contact.second_layer_width, width=self.nmos.active_contact.second_layer_width,
@ -273,7 +273,7 @@ class pinv(design.design):
def route_input_gate(self): def route_input_gate(self):
"""Routes the input gate to the left side of the cell for access""" """Routes the input gate to the left side of the cell for access"""
xoffset = self.pmos.poly_positions[0][0] xoffset = self.pmos.poly_positions[0].x
# Determines the y-coordinate of where to place the gate input poly pin # Determines the y-coordinate of where to place the gate input poly pin
# (middle in between the pmos and nmos) # (middle in between the pmos and nmos)
yoffset = self.nmos.height + (self.height yoffset = self.nmos.height + (self.height
@ -285,13 +285,13 @@ class pinv(design.design):
rotate=90) rotate=90)
# Determines the poly coordinate to connect to the poly contact # Determines the poly coordinate to connect to the poly contact
offset = offset - self.poly_contact.first_layer_position.rotate().scale(1,0) offset = offset - self.poly_contact.first_layer_position.rotate_scale(1,0)
self.add_rect(layer="poly", self.add_rect(layer="poly",
offset=offset, offset=offset,
width=self.poly_contact.first_layer_position[1] + drc["minwidth_poly"], width=self.poly_contact.first_layer_position.y + drc["minwidth_poly"],
height=self.poly_contact.first_layer_width) height=self.poly_contact.first_layer_width)
input_length = self.pmos.poly_positions[0][0] \ input_length = self.pmos.poly_positions[0].x \
- self.poly_contact.height - self.poly_contact.height
# Determine the y-coordinate for the placement of the metal1 via # Determine the y-coordinate for the placement of the metal1 via
self.input_position = vector(0, .5*(self.height - drc["minwidth_metal1"] self.input_position = vector(0, .5*(self.height - drc["minwidth_metal1"]
@ -305,9 +305,9 @@ class pinv(design.design):
def route_output_drain(self): def route_output_drain(self):
"""Routes the output (drain) to the right side of the cell for access""" """Routes the output (drain) to the right side of the cell for access"""
# Determines the y-coordinate of the output metal1 via pin # Determines the y-coordinate of the output metal1 via pin
offset = vector(self.drain_position[0] offset = vector(self.drain_position.x
+ self.nmos.active_contact.second_layer_width, + self.nmos.active_contact.second_layer_width,
self.input_position[1]) self.input_position.y)
output_length = self.width - offset.x output_length = self.width - offset.x
if self.route_output == True: if self.route_output == True:
self.output_position = offset + vector(output_length,0) self.output_position = offset + vector(output_length,0)
@ -325,22 +325,18 @@ class pinv(design.design):
"""Adds n/p well taps to the layout""" """Adds n/p well taps to the layout"""
layer_stack = ("active", "contact", "metal1") layer_stack = ("active", "contact", "metal1")
# Same y-positions of the drain/source metals as the n/p mos # Same y-positions of the drain/source metals as the n/p mos
nwell_tap_xposition = self.pmos_position[0] \ well_contact_offset = vector(self.pmos.active_position.x
+ self.pmos.active_position[0] \ + self.active_width
+ self.active_width \ - self.nwell_contact.width,
- self.nwell_contact.width self.pmos.active_contact_positions[0].y)
nwell_tap_yposition = self.pmos_position[1] \ self.nwell_contact_position = self.pmos_position + well_contact_offset
+ self.pmos.active_contact_positions[0][1]
self.nwell_contact_position = [nwell_tap_xposition, nwell_tap_yposition]
self.nwell_contact=self.add_contact(layer_stack,self.nwell_contact_position,(1,self.pmos.num_of_tacts)) self.nwell_contact=self.add_contact(layer_stack,self.nwell_contact_position,(1,self.pmos.num_of_tacts))
pwell_tap_xposition = self.nmos_position[0] \ well_contact_offset = vector(self.nmos.active_position.x
+ self.nmos.active_position[0] \ + self.active_width
+ self.active_width \ - self.pwell_contact.width,
- self.pwell_contact.width self.nmos.active_contact_positions[0].y)
pwell_tap_yposition = self.nmos_position[1] \ self.pwell_contact_position = self.nmos_position + well_contact_offset
+ self.nmos.active_contact_positions[0][1]
self.pwell_contact_position = [pwell_tap_xposition, pwell_tap_yposition]
self.pwell_contact=self.add_contact(layer_stack,self.pwell_contact_position,(1,self.nmos.num_of_tacts)) self.pwell_contact=self.add_contact(layer_stack,self.pwell_contact_position,(1,self.nmos.num_of_tacts))
def connect_well_contacts(self): def connect_well_contacts(self):
@ -348,7 +344,7 @@ class pinv(design.design):
# calculates the length needed to connect the nwell_tap to vdd # calculates the length needed to connect the nwell_tap to vdd
nwell_tap_length = self.height \ nwell_tap_length = self.height \
- 0.5 * drc["minwidth_metal1"] \ - 0.5 * drc["minwidth_metal1"] \
- self.nwell_contact_position[1] - self.nwell_contact_position.y
# obtains the position for the metal 1 layer in the nwell_tap # obtains the position for the metal 1 layer in the nwell_tap
offset = self.nwell_contact_position + \ offset = self.nwell_contact_position + \
self.nwell_contact.second_layer_position.scale(1,0) self.nwell_contact.second_layer_position.scale(1,0)
@ -356,10 +352,10 @@ class pinv(design.design):
offset=offset, width=self.nwell_contact.second_layer_width, offset=offset, width=self.nwell_contact.second_layer_width,
height=nwell_tap_length) height=nwell_tap_length)
pwell_tap_length = self.pwell_contact_position[1] \ pwell_tap_length = self.pwell_contact_position.y \
+ 0.5 * drc["minwidth_metal1"] + 0.5 * drc["minwidth_metal1"]
offset = [self.pwell_contact_position[0] offset = [self.pwell_contact_position.x
+ self.pwell_contact.second_layer_position[0], + self.pwell_contact.second_layer_position.x,
0.5 * drc["minwidth_metal1"]] 0.5 * drc["minwidth_metal1"]]
self.add_rect(layer="metal1", self.add_rect(layer="metal1",
offset=offset, offset=offset,
@ -377,7 +373,7 @@ class pinv(design.design):
- drc["minwidth_metal1"]).scale(.5,.5) - drc["minwidth_metal1"]).scale(.5,.5)
# nmos position of the source metals # nmos position of the source metals
noffset = self.nmos_position + self.nmos.active_contact_positions[0] + correct noffset = self.nmos_position + self.nmos.active_contact_positions[0] + correct
offset = [self.nmos.active_contact.second_layer_position[0] + noffset[0], offset = [self.nmos.active_contact.second_layer_position.x + noffset.x,
0.5 * drc["minwidth_metal1"]] 0.5 * drc["minwidth_metal1"]]
self.add_rect(layer="metal1", offset=offset, self.add_rect(layer="metal1", offset=offset,
width=self.nmos.active_contact.second_layer_width, width=self.nmos.active_contact.second_layer_width,
@ -390,7 +386,7 @@ class pinv(design.design):
# pmos position of the source metals # pmos position of the source metals
offset = self.pmos_position + self.pmos.active_contact_positions[0]\ offset = self.pmos_position + self.pmos.active_contact_positions[0]\
+ correct + self.pmos.active_contact.second_layer_position + correct + self.pmos.active_contact.second_layer_position
temp_height = self.height - offset[1] - 0.5 * drc["minwidth_metal1"] temp_height = self.height - offset.y - 0.5 * drc["minwidth_metal1"]
self.add_rect(layer="metal1", self.add_rect(layer="metal1",
offset=offset, offset=offset,
width=self.pmos.active_contact.second_layer_width, width=self.pmos.active_contact.second_layer_width,

View File

@ -185,7 +185,7 @@ class precharge(design.design):
def add_vdd_rail(self): def add_vdd_rail(self):
"""Adds a vdd rail at the top of the cell""" """Adds a vdd rail at the top of the cell"""
# adds the rail across the width of the cell # adds the rail across the width of the cell
self.vdd_position = vector(self.pclk_position[0], self.vdd_position = vector(self.pclk_position.x,
self.height - drc["minwidth_metal1"]) self.height - drc["minwidth_metal1"])
self.add_layout_pin(text="vdd", self.add_layout_pin(text="vdd",
layer="metal1", layer="metal1",

View File

@ -16,7 +16,7 @@ class ptx(design.design):
name = "{0}{1}".format(name, ptx.unique_mos_id) name = "{0}{1}".format(name, ptx.unique_mos_id)
ptx.unique_mos_id += 1 ptx.unique_mos_id += 1
design.design.__init__(self, name) design.design.__init__(self, name)
debug.info(2, "create ptx structure {0}".format(name)) debug.info(3, "create ptx structure {0}".format(name))
self.tx_type = tx_type self.tx_type = tx_type
self.mults = mults self.mults = mults
@ -56,10 +56,10 @@ class ptx(design.design):
# We can do this in ptx because we have offset all modules it uses. # We can do this in ptx because we have offset all modules it uses.
# Is this really true considering the paths that connect the src/drain? # Is this really true considering the paths that connect the src/drain?
self.height = max(max(obj.offset[1] + obj.height for obj in self.objs), self.height = max(max(obj.offset.y + obj.height for obj in self.objs),
max(inst.offset[1] + inst.mod.height for inst in self.insts)) max(inst.offset.y + inst.mod.height for inst in self.insts))
self.width = max(max(obj.offset[0] + obj.width for obj in self.objs), self.width = max(max(obj.offset.x + obj.width for obj in self.objs),
max(inst.offset[0] + inst.mod.width for inst in self.insts)) max(inst.offset.x + inst.mod.width for inst in self.insts))
def create_spice(self): def create_spice(self):
self.spice.append("\n.SUBCKT {0} {1}".format(self.name, self.spice.append("\n.SUBCKT {0} {1}".format(self.name,
@ -78,29 +78,27 @@ class ptx(design.design):
self.mults_poly_to_poly = max(2 * drc["contact_to_poly"] + drc["minwidth_contact"], self.mults_poly_to_poly = max(2 * drc["contact_to_poly"] + drc["minwidth_contact"],
drc["poly_to_poly"]) drc["poly_to_poly"])
outeractive_to_contact = max(drc["active_enclosure_contact"], outeractive_to_contact = max(drc["active_enclosure_contact"],
(drc["minwidth_active"] - drc["minwidth_contact"]) / 2) (drc["minwidth_active"] - drc["minwidth_contact"]) / 2)
self.active_width = 2 * (outeractive_to_contact \ self.active_width = (2 * (outeractive_to_contact + drc["minwidth_contact"]
+ drc["minwidth_contact"] \ + drc["contact_to_poly"])
+ drc["contact_to_poly"]) \ + drc["minwidth_poly"]
+ drc["minwidth_poly"] \ + (self.mults - 1) * (self.mults_poly_to_poly
+ (self.mults - 1) * ( + drc["minwidth_poly"]))
self.mults_poly_to_poly + drc["minwidth_poly"])
self.active_height = max(drc["minarea_active"] / self.active_width, self.active_height = max(drc["minarea_active"] / self.active_width,
self.gate_width) self.gate_width)
self.poly_width = drc["minwidth_poly"] # horizontal self.poly_width = drc["minwidth_poly"] # horizontal
self.poly_height = max(drc["minarea_poly"] / self.poly_width, self.poly_height = max(drc["minarea_poly"] / self.poly_width,
self.gate_width \ self.gate_width
+ 2 * drc["poly_extend_active"]) # vertical + 2 * drc["poly_extend_active"]) # vertical
self.well_width = self.active_width \ self.well_width = (self.active_width
+ 2 * (drc["well_enclosure_active"]) + 2 * (drc["well_enclosure_active"]))
self.well_height = max(self.gate_width + 2 * (drc["well_enclosure_active"]), self.well_height = max(self.gate_width + 2 * (drc["well_enclosure_active"]),
drc["minwidth_well"]) drc["minwidth_well"])
def connect_fingered_poly(self): def connect_fingered_poly(self):
poly_connect_length = self.poly_positions[-1][0] + self.poly_width \ poly_connect_length = self.poly_positions[-1].x + self.poly_width \
- self.poly_positions[0][0] - self.poly_positions[0].x
poly_connect_position = [self.poly_positions[0][0], poly_connect_position = self.poly_positions[0] - vector(0, self.poly_width)
self.poly_positions[0][1] - self.poly_width]
if len(self.poly_positions) > 1: if len(self.poly_positions) > 1:
self.add_rect(layer="poly", self.add_rect(layer="poly",
offset=poly_connect_position, offset=poly_connect_position,
@ -127,8 +125,8 @@ class ptx(design.design):
drc["minwidth_metal1"] + drc["minwidth_contact"]), drc["minwidth_metal1"] + drc["minwidth_contact"]),
0.5 * (self.active_contact.height - drc["minwidth_contact"]) 0.5 * (self.active_contact.height - drc["minwidth_contact"])
- drc["metal1_extend_contact"]) - drc["metal1_extend_contact"])
connected=vector(b[0] + drc["minwidth_metal1"], connected=vector(b.x + drc["minwidth_metal1"],
a[1] + self.active_contact.height + drc["metal1_to_metal1"]) a.y + self.active_contact.height + drc["metal1_to_metal1"])
self.source_positions.append(a + correct) self.source_positions.append(a + correct)
self.source_positions.append(vector(a.x + correct.x, connected.y)) self.source_positions.append(vector(a.x + correct.x, connected.y))
self.source_positions.append(vector(b.x + correct.x, self.source_positions.append(vector(b.x + correct.x,
@ -144,10 +142,10 @@ class ptx(design.design):
+ drc["minwidth_contact"]), + drc["minwidth_contact"]),
0.5*(self.active_contact.height - drc["minwidth_contact"]) 0.5*(self.active_contact.height - drc["minwidth_contact"])
- drc["metal1_extend_contact"]) - drc["metal1_extend_contact"])
connected = vector(d[0] + drc["minwidth_metal1"], c[1] - drc["metal1_to_metal1"]) connected = vector(d.x + drc["minwidth_metal1"], c.y - drc["metal1_to_metal1"])
self.drain_positions.append(vector(c + correct)) self.drain_positions.append(vector(c + correct))
self.drain_positions.append(vector(c[0] + correct.x, connected.y)) self.drain_positions.append(vector(c.x + correct.x, connected.y))
self.drain_positions.append(vector(d[0] + correct.x, self.drain_positions.append(vector(d.x + correct.x,
connected.y - 0.5 * drc["minwidth_metal1"])) connected.y - 0.5 * drc["minwidth_metal1"]))
self.drain_positions.append(vector(d + correct)) self.drain_positions.append(vector(d + correct))
@ -165,7 +163,7 @@ class ptx(design.design):
def add_poly(self): def add_poly(self):
# left_most poly # left_most poly
poly_xoffset = self.active_contact.via_layer_position[0] \ poly_xoffset = self.active_contact.via_layer_position.x \
+ drc["minwidth_contact"] + drc["contact_to_poly"] + drc["minwidth_contact"] + drc["contact_to_poly"]
poly_yoffset = -drc["poly_extend_active"] poly_yoffset = -drc["poly_extend_active"]
self.poly_positions = [] self.poly_positions = []
@ -255,10 +253,10 @@ class ptx(design.design):
# middle contact columns # middle contact columns
for i in range(self.mults - 1): for i in range(self.mults - 1):
contact_xoffset = self.poly_positions[i][0] + self.poly_width \ contact_xoffset = self.poly_positions[i].x + self.poly_width \
+ (self.mults_poly_to_poly / 2) \ + (self.mults_poly_to_poly / 2) \
- (drc["minwidth_contact"] / 2) - \ - (drc["minwidth_contact"] / 2) - \
self.active_contact.via_layer_position[0] self.active_contact.via_layer_position.x
offset = vector(contact_xoffset, contact_yoffset) offset = vector(contact_xoffset, contact_yoffset)
self.add_contact(layers=("active", "contact", "metal1"), self.add_contact(layers=("active", "contact", "metal1"),
offset=offset, offset=offset,
@ -267,9 +265,9 @@ class ptx(design.design):
self.active_contact_positions.append(offset) self.active_contact_positions.append(offset)
# right_most contact column # right_most contact column
contact_xoffset = self.poly_positions[-1][0] \ contact_xoffset = self.poly_positions[-1].x \
+ self.poly_width + drc["contact_to_poly"] - \ + self.poly_width + drc["contact_to_poly"] - \
self.active_contact.via_layer_position[0] self.active_contact.via_layer_position.x
offset = vector(contact_xoffset, contact_yoffset) offset = vector(contact_xoffset, contact_yoffset)
self.add_contact(layers=("active", "contact", "metal1"), self.add_contact(layers=("active", "contact", "metal1"),
offset=offset, offset=offset,

View File

@ -68,7 +68,8 @@ class replica_bitline(design.design):
self.inv.height * 0.5) self.inv.height * 0.5)
self.replica_bitline_offset = vector(self.delay_chain_offset.x self.replica_bitline_offset = vector(self.delay_chain_offset.x
+ bitcell_array_spacing, + bitcell_array_spacing,
self.bitcell_chars["height"] + gnd_route_margin) self.bitcell_chars["height"]
+ gnd_route_margin)
self.delay_inv_offset = vector(self.delay_chain_offset.x - self.inv.width, self.delay_inv_offset = vector(self.delay_chain_offset.x - self.inv.width,
self.inv.height * 2) self.inv.height * 2)
@ -184,59 +185,44 @@ class replica_bitline(design.design):
BL_inv_in = self.BL_inv_offset + self.inv.A_position + correct BL_inv_in = self.BL_inv_offset + self.inv.A_position + correct
BL_offset = self.replica_bitline_offset + vector(1,0).scale(self.bitcell_chars["BL"]) BL_offset = self.replica_bitline_offset + vector(1,0).scale(self.bitcell_chars["BL"])
pin_offset = self.delay_chain.clk_out_offset.rotate().scale(-1,1) pin_offset = self.delay_chain.clk_out_offset.rotate_scale(-1,1)
delay_chain_output = self.delay_chain_offset + pin_offset delay_chain_output = self.delay_chain_offset + pin_offset
vdd_offset = vector(self.delay_chain_offset.x + 9 * drc["minwidth_metal2"],
self.height)
self.create_input() self.create_input()
self.route_BL_t_BL_inv(BL_offset, BL_inv_in) self.route_BL_t_BL_inv(BL_offset, BL_inv_in)
self.route_access_tx(delay_chain_output, BL_inv_in) self.route_access_tx(delay_chain_output, BL_inv_in, vdd_offset)
self.route_vdd() self.route_vdd()
self.route_gnd() self.route_gnd()
# route loads after gnd and vdd created # route loads after gnd and vdd created
self.route_loads() self.route_loads(vdd_offset)
self.route_RC() self.route_RC(vdd_offset)
def create_input(self): def create_input(self):
# create routing module based on module offset # create routing module based on module offset
correct = vector(0.5 * drc["minwidth_metal1"], 0) correct = vector(0.5 * drc["minwidth_metal1"], 0)
pin_offset = self.delay_chain.clk_in_offset.rotate().scale(-1,1) pin_offset = self.delay_chain.clk_in_offset.rotate_scale(-1,1)
input_offset = self.delay_chain_offset + pin_offset + correct input_offset = self.delay_chain_offset + pin_offset + correct
mid1 = [input_offset[0], self.en_input_offset[1]] mid1 = [input_offset.x, self.en_input_offset.y]
self.add_path("metal1", [self.en_input_offset, mid1, input_offset]) self.add_path("metal1", [self.en_input_offset, mid1, input_offset])
self.add_label(text="en", self.add_label(text="en",
layer="metal1", layer="metal1",
offset=self.en_input_offset) offset=self.en_input_offset)
def route_nor2A_t_dc(self, nor_A, delayed_en_offset):
# delay chain output to m2
dc_offset = [delayed_en_offset[0], delayed_en_offset[1]]
mid1 = [dc_offset[0], self.en_nor_offset
[1] + 3 * drc["minwidth_metal2"]]
mid2 = [self.delay_chain_offset[0] + 3*drc["minwidth_metal2"],
dc_offset[1]]
mid3 = [mid2[0], nor_A[1]]
self.add_wire(("metal2", "via1", "metal1"),
[dc_offset, mid2, mid3, nor_A])
def route_nor2B_t_BL_inv(self, nor_B, BL_inv_out):
mid1 = [nor_B[0] + 0.5 * drc["metal2_to_metal2"], nor_B[1]]
self.add_wire(("metal2", "via1", "metal1"),
[nor_B, mid1, BL_inv_out])
def route_BL_t_BL_inv(self, BL_offset, BL_inv_in): def route_BL_t_BL_inv(self, BL_offset, BL_inv_in):
# BL_inv input to M3 # BL_inv input to M3
mid1 = [BL_inv_in[0], mid1 = BL_inv_in - vector(0,
BL_inv_in[1] - drc["metal2_to_metal2"] - self.m1m2_via.width] drc["metal2_to_metal2"] + self.m1m2_via.width)
mid2 = [self.en_nor_offset[0] + 3*drc["metal1_to_metal1"], mid2 = vector(self.en_nor_offset.x + 3 * drc["metal1_to_metal1"],
mid1[1]] mid1.y)
mid3 = [mid2[0], mid3 = vector(mid2.x,
self.replica_bitline_offset[1] - self.replica_bitcell.height self.replica_bitline_offset.y - self.replica_bitcell.height
- 0.5 * (self.m1m2_via.height + drc["metal1_to_metal1"]) - 0.5 * (self.m1m2_via.height + drc["metal1_to_metal1"])
- 2 * drc["metal1_to_metal1"]] - 2 * drc["metal1_to_metal1"])
self.add_wire(("metal1", "via1", "metal2"), self.add_wire(layers=("metal2", "via1", "metal1"),
[BL_inv_in, mid1, mid2, mid3]) coordinates=[BL_inv_in, mid1, mid2, mid3])
# need to fix the mid point as this is done with two wire # need to fix the mid point as this is done with two wire
# this seems to cover the metal1 error of the wire # this seems to cover the metal1 error of the wire
@ -246,18 +232,18 @@ class replica_bitline(design.design):
width=drc["minwidth_metal1"], width=drc["minwidth_metal1"],
height=drc["minwidth_metal1"]) height=drc["minwidth_metal1"])
mid4 = [BL_offset[0], mid3[1]] mid4 = [BL_offset.x, mid3.y]
self.add_wire(("metal2", "via1", "metal1"), self.add_wire(layers=("metal1", "via1", "metal2"),
[BL_offset, mid4, mid3]) coordinates=[BL_offset, mid4, mid3])
def route_access_tx(self, delay_chain_output, BL_inv_in): def route_access_tx(self, delay_chain_output, BL_inv_in, vdd_offset):
self.route_tx_gate(delay_chain_output) self.route_tx_gate(delay_chain_output)
self.route_tx_drain() self.route_tx_drain(vdd_offset)
self.route_tx_source(BL_inv_in) self.route_tx_source(BL_inv_in)
def route_tx_gate(self, delay_chain_output): def route_tx_gate(self, delay_chain_output):
# gate input for access tx # gate input for access tx
offset = (self.access_tx.poly_positions[0].rotate().scale(0,1) offset = (self.access_tx.poly_positions[0].rotate_scale(0,1)
+ self.access_tx_offset) + self.access_tx_offset)
width = -6 * drc["minwidth_metal1"] width = -6 * drc["minwidth_metal1"]
self.add_rect(layer="poly", self.add_rect(layer="poly",
@ -276,35 +262,36 @@ class replica_bitline(design.design):
def route_access_tx_t_delay_chain(self, offset, delay_chain_output): def route_access_tx_t_delay_chain(self, offset, delay_chain_output):
m2rail_space = (drc["minwidth_metal2"] + drc["metal2_to_metal2"]) m2rail_space = (drc["minwidth_metal2"] + drc["metal2_to_metal2"])
mid1 = [offset[0], self.delay_chain_offset[1] - 3 * m2rail_space] mid1 = vector(offset.x, self.delay_chain_offset.y - 3 * m2rail_space)
mid2 = [delay_chain_output[0], mid1[1]] mid2 = [delay_chain_output.x, mid1.y]
# Note the inverted wire stack # Note the inverted wire stack
self.add_wire(("metal2", "via1", "metal1"), self.add_wire(layers=("metal1", "via1", "metal2"),
[offset, mid1, mid2, delay_chain_output]) coordinates=[offset, mid1, mid2, delay_chain_output])
self.add_via(layers=("metal1", "via1", "metal2"), self.add_via(layers=("metal1", "via1", "metal2"),
offset=delay_chain_output, offset=delay_chain_output,
mirror="MX") mirror="MX")
def route_access_tx_t_WL(self, offset): def route_access_tx_t_WL(self, offset):
m1m2_via_offset = offset - vector(0.5 * self.m1m2_via.width, m1m2_via_offset = offset - vector(0.5 * self.m1m2_via.width,
0.5 * self.m1m2_via.height) 0.5 * self.m1m2_via.height)
self.add_via(layers=("metal1", "via1", "metal2"), self.add_via(layers=("metal1", "via1", "metal2"),
offset=m1m2_via_offset) offset=m1m2_via_offset)
# route gate to RC WL # route gate to RC WL
RC_WL = self.replica_bitline_offset - vector(0,1).scale(self.bitcell_chars["WL"]) RC_WL = self.replica_bitline_offset - vector(0,1).scale(self.bitcell_chars["WL"])
mid1 = [offset[0], 0] mid1 = vector(offset.x, 0)
mid2 = [self.en_nor_offset[0] + 3 * drc["metal1_to_metal1"], mid2 = vector(self.en_nor_offset.x + 3 * drc["metal1_to_metal1"],
mid1[1]] mid1.y)
mid3 = [RC_WL[0] - drc["minwidth_metal1"] - self.m1m2_via.height, mid3 = vector(RC_WL.x - drc["minwidth_metal1"] - self.m1m2_via.height,
mid1[1]] mid1.y)
mid4 = [mid3[0], RC_WL[1]] mid4 = vector(mid3.x, RC_WL.y)
self.add_path("metal2", [offset, mid1, mid2, mid3, mid4]) self.add_path("metal2", [offset, mid1, mid2, mid3, mid4])
offset = mid4 - vector([0.5 * drc["minwidth_metal1"]]*2) offset = mid4 - vector([0.5 * drc["minwidth_metal1"]] * 2)
width = RC_WL[0] - offset[0] width = RC_WL.x - offset.x
# enter the bit line array with metal1 # enter the bit line array with metal1
via_offset = [mid4[0] - 0.5 * self.m1m2_via.width, via_offset = [mid4.x - 0.5 * self.m1m2_via.width,
offset[1] - 0.5 * (self.m1m2_via.height offset.y
- 0.5 * (self.m1m2_via.height
- drc["minwidth_metal1"])] - drc["minwidth_metal1"])]
self.add_via(layers=("metal1", "via1", "metal2"), self.add_via(layers=("metal1", "via1", "metal2"),
offset=via_offset) offset=via_offset)
@ -313,26 +300,24 @@ class replica_bitline(design.design):
width=width, width=width,
height=drc["minwidth_metal1"]) height=drc["minwidth_metal1"])
def route_tx_drain(self): def route_tx_drain(self,vdd_offset):
# route drain to Vdd # route drain to Vdd
active_offset = self.access_tx.active_contact_positions[1].rotate().scale(-1,1) active_offset = self.access_tx.active_contact_positions[1].rotate_scale(-1,1)
correct = vector(drc["minwidth_metal1"], correct = vector(-0.5 * drc["minwidth_metal1"],
self.access_tx.active_contact.width).scale(-0.5, 0.5) 0.5 * self.access_tx.active_contact.width)
drain_offset = self.access_tx_offset + active_offset + correct drain_offset = self.access_tx_offset + active_offset + correct
vdd_rail = [self.delay_chain_offset[0] + 9 * drc["minwidth_metal2"],
self.height]
close_Vdd_offset = self.BL_inv_offset + vector(0, self.inv.height) close_Vdd_offset = self.BL_inv_offset + vector(0, self.inv.height)
self.add_path("metal1", [drain_offset, close_Vdd_offset]) self.add_path("metal1", [drain_offset, close_Vdd_offset])
mid = [vdd_rail[0], close_Vdd_offset[1]] mid = [vdd_offset.x, close_Vdd_offset.y]
self.add_wire(("metal2", "via1", "metal1"), self.add_wire(layers=("metal1", "via1", "metal2"),
[close_Vdd_offset, mid, vdd_rail]) coordinates=[close_Vdd_offset, mid, vdd_offset])
def route_tx_source(self, BL_inv_in): def route_tx_source(self, BL_inv_in):
# route source to BL inv input which is connected to BL # route source to BL inv input which is connected to BL
active_offset = self.access_tx.active_contact_positions[0].rotate().scale(-1,1) active_offset = self.access_tx.active_contact_positions[0].rotate_scale(-1,1)
correct = vector(drc["minwidth_metal1"], correct = vector(-0.5 * drc["minwidth_metal1"],
self.access_tx.active_contact.width).scale(-0.5, 0.5) 0.5 * self.access_tx.active_contact.width)
source_offset = self.access_tx_offset + active_offset + correct source_offset = self.access_tx_offset + active_offset + correct
self.add_path("metal1", [source_offset, BL_inv_in]) self.add_path("metal1", [source_offset, BL_inv_in])
@ -347,11 +332,13 @@ class replica_bitline(design.design):
start = self.delay_chain_offset - vector(0.5 * self.delay_chain.height, 0) start = self.delay_chain_offset - vector(0.5 * self.delay_chain.height, 0)
m1rail_space = (drc["minwidth_metal1"] + drc["metal1_to_metal1"]) m1rail_space = (drc["minwidth_metal1"] + drc["metal1_to_metal1"])
mid1 = start - vector(0, m1rail_space) mid1 = start - vector(0, m1rail_space)
mid2 = [self.delay_chain_offset[0] + 9 * drc["minwidth_metal2"], mid2 = vector(self.delay_chain_offset.x + 9 * drc["minwidth_metal2"],
mid1[1]] mid1.y)
end = [mid2[0], vdd_offset[1]] end = [mid2.x, vdd_offset.y]
self.add_path(("metal1"), [start, mid1, mid2]) self.add_path(layer=("metal1"),
self.add_wire(("metal2", "via1", "metal1"), [mid1, mid2, end]) coordinates=[start, mid1, mid2])
self.add_wire(layers=("metal1", "via1", "metal2"),
coordinates=[mid1, mid2, end])
def route_gnd(self): def route_gnd(self):
"""route gnd of delay chain, en_nor, en_inv and BL_inv""" """route gnd of delay chain, en_nor, en_inv and BL_inv"""
@ -366,8 +353,9 @@ class replica_bitline(design.design):
mid2 = vector(mid1.x, y_off) mid2 = vector(mid1.x, y_off)
share_gnd = vector(self.gnd_position.x, mid2.y) share_gnd = vector(self.gnd_position.x, mid2.y)
# Note the inverted stacks # Note the inverted stacks
self.add_wire(("metal2", "via1", "metal1"), lst = [BL_gnd_offset, mid1, mid2, share_gnd, self.gnd_position]
[BL_gnd_offset, mid1, mid2, share_gnd, self.gnd_position]) self.add_wire(layers=("metal1", "via1", "metal2"),
coordinates=lst)
self.add_label(text="gnd", self.add_label(text="gnd",
layer="metal1", layer="metal1",
offset=self.gnd_position) offset=self.gnd_position)
@ -377,51 +365,51 @@ class replica_bitline(design.design):
offset=offset, offset=offset,
width=drc["minwidth_metal1"], width=drc["minwidth_metal1"],
height=-self.delay_chain.width) height=-self.delay_chain.width)
offset = [offset[0] + self.delay_chain.height, offset = [offset.x + self.delay_chain.height,
mid2[1]] mid2.y]
self.add_rect(layer="metal1", self.add_rect(layer="metal1",
offset=offset, offset=offset,
width=drc["minwidth_metal1"], width=drc["minwidth_metal1"],
height=-self.delay_chain.width) height=-self.delay_chain.width)
def route_loads(self): def route_loads(self,vdd_offset):
"""connect all the loads word line to gnd""" """connect all the loads word line to gnd"""
vdd_offset = [self.delay_chain_offset[0] + 9*drc["minwidth_metal2"],
self.height]
self.add_via(layers=("metal1", "via1", "metal2"), self.add_via(layers=("metal1", "via1", "metal2"),
offset=vdd_offset, offset=vdd_offset,
mirror="MX") mirror="MX")
gnd_offset = (self.delay_chain_offset gnd_offset = (self.delay_chain_offset
+ vector([drc["minwidth_metal1"]]*2).scale(-.5,.5)) + vector([drc["minwidth_metal1"]] * 2).scale(-.5,.5))
for i in range(self.rows): for i in range(self.rows):
WL_offset = (self.replica_bitline_offset WL_offset = (self.replica_bitline_offset
+ self.bitline_load.WL_positions[i].scale(0,1)) + self.bitline_load.WL_positions[i].scale(0,1))
mid = [self.delay_chain_offset[0] + 6 * drc["minwidth_metal2"], mid = [self.delay_chain_offset.x + 6 * drc["minwidth_metal2"],
gnd_offset[1]] gnd_offset.y]
self.add_wire(("metal2", "via1", "metal1"), [gnd_offset, mid, WL_offset]) self.add_wire(layers=("metal1", "via1", "metal2"),
coordinates=[gnd_offset, mid, WL_offset])
if i % 2 == 0: if i % 2 == 0:
load_vdd_offset = (self.replica_bitline_offset load_vdd_offset = (self.replica_bitline_offset
+ self.bitline_load.vdd_positions[i]) + self.bitline_load.vdd_positions[i])
mid = [vdd_offset[0], load_vdd_offset[1]] mid = [vdd_offset.x, load_vdd_offset.y]
self.add_wire(("metal2", "via1", "metal1"), [vdd_offset, mid, load_vdd_offset]) self.add_wire(layers=("metal1", "via1", "metal2"),
coordinates=[vdd_offset, mid, load_vdd_offset])
def route_RC(self): def route_RC(self,vdd_offset):
"""route vdd gnd to the replica cell """ """route vdd gnd to the replica cell """
# connect vdd # connect vdd
RC_vdd = self.replica_bitline_offset + vector(1,-1).scale(self.bitcell_chars["vdd"]) RC_vdd = self.replica_bitline_offset + vector(1,-1).scale(self.bitcell_chars["vdd"])
vdd_offset = [self.delay_chain_offset[0] + 9 * drc["minwidth_metal2"], mid = [vdd_offset.x, RC_vdd.y]
self.height]
mid = [vdd_offset[0], RC_vdd[1]]
# Note the inverted stacks # Note the inverted stacks
self.add_wire(("metal2", "via1", "metal1"), [vdd_offset, mid, RC_vdd]) self.add_wire(layers=("metal1", "via1", "metal2"),
coordinates=[vdd_offset, mid, RC_vdd])
gnd_offset = self.BL_inv_offset - vector(self.inv.width, 0) gnd_offset = self.BL_inv_offset - vector(self.inv.width, 0)
load_gnd = (self.replica_bitline_offset load_gnd = self.replica_bitline_offset + vector(self.bitcell_chars["gnd"][0],
+ vector(self.bitcell_chars["gnd"][0], self.bitline_load.height)) self.bitline_load.height)
mid = [load_gnd[0], gnd_offset[1]] mid = [load_gnd.x, gnd_offset.y]
self.add_wire(("metal2", "via1", "metal1"), [gnd_offset, mid, load_gnd]) self.add_wire(layers=("metal1", "via1", "metal2"),
coordinates=[gnd_offset, mid, load_gnd])
load_gnd = (self.replica_bitline_offset load_gnd = self.replica_bitline_offset + vector(0,
+ vector(0, self.bitline_load.height)) self.bitline_load.height)
mid = [load_gnd[0], gnd_offset[1]] mid = [load_gnd.x, gnd_offset.y]
self.add_wire(("metal2", "via1", "metal1"), [gnd_offset, mid, load_gnd]) self.add_wire(("metal1", "via1", "metal2"), [gnd_offset, mid, load_gnd])

View File

@ -79,7 +79,7 @@ class single_level_column_mux(design.design):
self.poly_offset = (self.nmos1_position self.poly_offset = (self.nmos1_position
+ self.nmos1.poly_positions[0] + self.nmos1.poly_positions[0]
+ vector(0,self.nmos1.poly_height)) + vector(0,self.nmos1.poly_height))
width=self.nmos2_position[0] - self.nmos1_position[0] + drc["minwidth_poly"] width=self.nmos2_position.x- self.nmos1_position.x+ drc["minwidth_poly"]
self.poly = self.add_rect(layer="poly", self.poly = self.add_rect(layer="poly",
offset=self.poly_offset, offset=self.poly_offset,
width=width, width=width,
@ -91,7 +91,7 @@ class single_level_column_mux(design.design):
def connect_to_bitlines(self): def connect_to_bitlines(self):
offset = [self.nmos1.active_contact_positions[0].x + self.m1m2_via.contact_width / 2 offset = [self.nmos1.active_contact_positions[0].x + self.m1m2_via.contact_width / 2
+ 3 * (self.m1m2_via.second_layer_width - self.m1m2_via.first_layer_width) / 2, + 3 * (self.m1m2_via.second_layer_width - self.m1m2_via.first_layer_width) / 2,
self.nmos1.active_position[1] + self.nmos1.active_height] self.nmos1.active_position.y+ self.nmos1.active_height]
offset = self.nmos1_position + offset offset = self.nmos1_position + offset
connection = vector(0, connection = vector(0,
self.nmos2.active_height+ 2 * drc["poly_extend_active"] \ self.nmos2.active_height+ 2 * drc["poly_extend_active"] \
@ -101,7 +101,7 @@ class single_level_column_mux(design.design):
width=drc["minwidth_metal2"], width=drc["minwidth_metal2"],
height=connection.y - drc["minwidth_metal2"]) height=connection.y - drc["minwidth_metal2"])
self.BL_position = (vector(self.bitcell_chars["BL"][0] - 0.5 * self.m1m2_via.width, self.BL_position = (vector(self.bitcell_chars["BL"][0]- 0.5 * self.m1m2_via.width,
offset.y) offset.y)
+ connection) + connection)
self.add_via(layers=("metal1", "via1", "metal2"), self.add_via(layers=("metal1", "via1", "metal2"),
@ -116,10 +116,10 @@ class single_level_column_mux(design.design):
width=drc["minwidth_metal2"], width=drc["minwidth_metal2"],
height=2 * drc["minwidth_metal2"]) height=2 * drc["minwidth_metal2"])
width = self.bitcell_chars["BL"][0] - 0.5 * self.m1m2_via.width - offset[0] + drc["minwidth_metal2"] width = self.bitcell_chars["BL"][0]- 0.5 * self.m1m2_via.width - offset.x+ drc["minwidth_metal2"]
self.add_rect(layer="metal2", self.add_rect(layer="metal2",
offset=[offset[0], offset=[offset[0],
self.BL_position[1] - 2*drc["minwidth_metal2"]], self.BL_position.y- 2*drc["minwidth_metal2"]],
width=width, width=width,
height=drc["minwidth_metal2"]) height=drc["minwidth_metal2"])
@ -127,24 +127,24 @@ class single_level_column_mux(design.design):
self.add_via(layers=("metal1", "via1", "metal2"), self.add_via(layers=("metal1", "via1", "metal2"),
offset=offset) offset=offset)
self.add_rect(layer="metal2", self.add_rect(layer="metal2",
offset=[self.bitcell_chars["BL"][0] - 0.5 * self.m1m2_via.width, offset=[self.bitcell_chars["BL"][0]- 0.5 * self.m1m2_via.width,
0], 0],
width=drc["minwidth_metal2"], width=drc["minwidth_metal2"],
height=(drc["minwidth_metal2"] + offset[1])) height=(drc["minwidth_metal2"] + offset[1]))
self.add_rect(layer="metal2", self.add_rect(layer="metal2",
offset=[self.bitcell_chars["BL"][0] - 0.5 * self.m1m2_via.width, offset=[self.bitcell_chars["BL"][0]- 0.5 * self.m1m2_via.width,
offset[1]], offset[1]],
width=(offset[0] - self.bitcell_chars["BL"][0] - 0.5 * self.m1m2_via.width width=(offset.x- self.bitcell_chars["BL"][0]- 0.5 * self.m1m2_via.width
+ 2 * drc["minwidth_metal2"]), + 2 * drc["minwidth_metal2"]),
height=drc["minwidth_metal2"]) height=drc["minwidth_metal2"])
self.BL_out_position = vector(self.bitcell_chars["BL"][0] - 0.5* self.m1m2_via.width, self.BL_out_position = vector(self.bitcell_chars["BL"][0]- 0.5* self.m1m2_via.width,
0) 0)
self.add_label(text="bl_out", self.add_label(text="bl_out",
layer="metal2", layer="metal2",
offset=self.BL_out_position) offset=self.BL_out_position)
offset = [self.nmos2.active_contact_positions[1].x - self.m1m2_via.contact_width / 2, offset = [self.nmos2.active_contact_positions[1].x - self.m1m2_via.contact_width / 2,
self.nmos2.active_position[1] + self.nmos2.active_height] self.nmos2.active_position.y+ self.nmos2.active_height]
offset = self.nmos2_position + offset offset = self.nmos2_position + offset
self.add_via(layers=("metal1", "via1", "metal2"), self.add_via(layers=("metal1", "via1", "metal2"),
offset=offset, offset=offset,
@ -152,21 +152,21 @@ class single_level_column_mux(design.design):
mid = offset + vector(drc["minwidth_metal2"],0) mid = offset + vector(drc["minwidth_metal2"],0)
self.add_rect(layer="metal2", self.add_rect(layer="metal2",
offset= mid, offset= mid,
width= (self.bitcell_chars["BR"][0] - mid[0] + 0.5*self.m1m2_via.width), width= (self.bitcell_chars["BR"][0]- mid.x+ 0.5*self.m1m2_via.width),
height=-drc["minwidth_metal2"]) height=-drc["minwidth_metal2"])
self.add_rect(layer="metal2", self.add_rect(layer="metal2",
offset=[self.bitcell_chars["BR"][0] - 0.5*self.m1m2_via.width, offset=[self.bitcell_chars["BR"][0]- 0.5*self.m1m2_via.width,
offset[1] - drc["metal1_to_metal1"]], offset.y- drc["metal1_to_metal1"]],
width=drc["minwidth_metal2"], width=drc["minwidth_metal2"],
height=2*drc["minwidth_metal2"]) height=2*drc["minwidth_metal2"])
self.BR_position = vector(self.bitcell_chars["BR"][0] - 0.5 * self.m1m2_via.width, self.BR_position = vector(self.bitcell_chars["BR"][0]- 0.5 * self.m1m2_via.width,
self.BL_position.y) self.BL_position.y)
self.add_label(text="br", self.add_label(text="br",
layer="metal2", layer="metal2",
offset=self.BR_position) offset=self.BR_position)
offset = self.nmos2_position + self.nmos2.active_contact_positions[0] offset = self.nmos2_position + self.nmos2.active_contact_positions[0]
self.BR_out_position = vector(self.bitcell_chars["BR"][0] - 0.5 * self.m1m2_via.width, self.BR_out_position = vector(self.bitcell_chars["BR"][0]- 0.5 * self.m1m2_via.width,
0) 0)
self.add_label(text="br_out", self.add_label(text="br_out",
layer="metal2", layer="metal2",
@ -179,12 +179,12 @@ class single_level_column_mux(design.design):
height=drc["minwidth_metal2"]) height=drc["minwidth_metal2"])
self.add_rect(layer="metal2", self.add_rect(layer="metal2",
offset=[self.BR_out_position.x, offset=[self.BR_out_position.x,
offset[1] + drc["minwidth_metal2"]], offset.y+ drc["minwidth_metal2"]],
width=drc["minwidth_metal2"], width=drc["minwidth_metal2"],
height=-(offset[1] + drc["minwidth_metal2"])) height=-(offset.y+ drc["minwidth_metal2"]))
def add_gnd_rail(self): def add_gnd_rail(self):
self.gnd_position = vector(self.bitcell_chars["gnd"][0] - 0.5 * self.m1m2_via.width, self.gnd_position = vector(self.bitcell_chars["gnd"][0]- 0.5 * self.m1m2_via.width,
0) 0)
self.add_layout_pin(text="gnd", self.add_layout_pin(text="gnd",
layer="metal2", layer="metal2",
@ -193,7 +193,7 @@ class single_level_column_mux(design.design):
height=self.BL_position[1]) height=self.BL_position[1])
def add_well_contacts(self): def add_well_contacts(self):
offset = vector(self.gnd_position[0] + drc["minwidth_metal2"], offset = vector(self.gnd_position.x+ drc["minwidth_metal2"],
self.nmos1.poly_height / 2) self.nmos1.poly_height / 2)
self.add_via(layers=("metal1", "via1", "metal2"), self.add_via(layers=("metal1", "via1", "metal2"),
offset=offset - vector(self.m1m2_via.width / 2, 0), offset=offset - vector(self.m1m2_via.width / 2, 0),
@ -212,11 +212,11 @@ class single_level_column_mux(design.design):
offset_well = self.nmos1_position + vector(self.nmos1.width, 0) offset_well = self.nmos1_position + vector(self.nmos1.width, 0)
self.add_rect(layer="pwell", self.add_rect(layer="pwell",
offset=offset_well, offset=offset_well,
width=self.gnd_position[0] + drc["minwidth_metal2"] - offset_well[0], width=self.gnd_position.x+ drc["minwidth_metal2"] - offset_well[0],
height=self.nmos1.height + drc["minwidth_poly"]) height=self.nmos1.height + drc["minwidth_poly"])
self.add_rect(layer="vtg", self.add_rect(layer="vtg",
offset=offset_well, offset=offset_well,
width=self.gnd_position[0] + drc["minwidth_metal2"] - offset_well[0], width=self.gnd_position.x+ drc["minwidth_metal2"] - offset_well[0],
height=self.nmos1.height + drc["minwidth_poly"]) height=self.nmos1.height + drc["minwidth_poly"])
def setup_layout_constants(self): def setup_layout_constants(self):

View File

@ -380,14 +380,14 @@ class sram(design.design):
self.width = self.bank.width + self.control.height + 2*drc["minwidth_metal3"] self.width = self.bank.width + self.control.height + 2*drc["minwidth_metal3"]
self.height = self.bank.height self.height = self.bank.height
self.control.CSb_position.rotate().scale(-1,1) self.control.CSb_position.rotate_scale(-1,1)
self.CSb_position = (self.control.CSb_position.rotate().scale(-1,1) self.CSb_position = (self.control.CSb_position.rotate_scale(-1,1)
+self.control_position) +self.control_position)
self.OEb_position = (self.control.OEb_position.rotate().scale(-1,1) self.OEb_position = (self.control.OEb_position.rotate_scale(-1,1)
+self.control_position) +self.control_position)
self.WEb_position = (self.control.WEb_position.rotate().scale(-1,1) self.WEb_position = (self.control.WEb_position.rotate_scale(-1,1)
+self.control_position) +self.control_position)
self.clk_position = (self.control.clk_position.rotate().scale(-1,1) self.clk_position = (self.control.clk_position.rotate_scale(-1,1)
+self.control_position) +self.control_position)
for i in range(0, self.word_size): for i in range(0, self.word_size):
self.add_label(text="DATA[{0}]".format(i), self.add_label(text="DATA[{0}]".format(i),
@ -612,7 +612,7 @@ class sram(design.design):
bank_attr = self.sram_property[attr_index] bank_attr = self.sram_property[attr_index]
self.add_rect(layer="metal3", self.add_rect(layer="metal3",
offset=getattr(self,bank_attr)[left_bank_index], offset=getattr(self,bank_attr)[left_bank_index],
width=getattr(self,bank_attr)[right_bank_index].x - getattr(self,bank_attr)[left_bank_index][0], width=getattr(self,bank_attr)[right_bank_index].x - getattr(self,bank_attr)[left_bank_index].x,
height=drc["minwidth_metal3"]) height=drc["minwidth_metal3"])
self.add_via(layers=("metal2", "via2", "metal3"), self.add_via(layers=("metal2", "via2", "metal3"),
offset=[self.vertical_line_positions[attr_index].x, offset=[self.vertical_line_positions[attr_index].x,
@ -710,17 +710,17 @@ class sram(design.design):
# 0 = s_en # 0 = s_en
control_side = [] control_side = []
control_side.append(self.control.clk_position.rotate().scale(-1, 1) control_side.append(self.control.clk_position.rotate_scale(-1, 1)
+ self.control_position) + self.control_position)
control_side.append(self.control.clk_bar_position.rotate().scale(-1, 1) control_side.append(self.control.clk_bar_position.rotate_scale(-1, 1)
+ self.control_position) + self.control_position)
control_side.append(self.control.tri_en_position.rotate().scale(-1, 1) control_side.append(self.control.tri_en_position.rotate_scale(-1, 1)
+ self.control_position) + self.control_position)
control_side.append(self.control.tri_en_bar_position.rotate().scale(-1, 1) control_side.append(self.control.tri_en_bar_position.rotate_scale(-1, 1)
+ self.control_position) + self.control_position)
control_side.append(self.control.w_en_position.rotate().scale(-1, 1) control_side.append(self.control.w_en_position.rotate_scale(-1, 1)
+ self.control_position) + self.control_position)
control_side.append(self.control.s_en_position.rotate().scale(-1, 1) control_side.append(self.control.s_en_position.rotate_scale(-1, 1)
+ self.control_position) + self.control_position)
bank_side = [] bank_side = []
@ -763,14 +763,14 @@ class sram(design.design):
msb_line = self.control_size + self.num_banks/2 - 1 - i msb_line = self.control_size + self.num_banks/2 - 1 - i
bank_select_start_line = msb_line + 2 + self.bank_addr_size bank_select_start_line = msb_line + 2 + self.bank_addr_size
msf_msb_din = (self.msf_msb_address.din_positions[i].rotate().scale(1, -1) msf_msb_din = (self.msf_msb_address.din_positions[i].rotate_scale(1, -1)
+ self.msf_msb_address_position) + self.msf_msb_address_position)
contact_pos = [self.vertical_line_positions[msb_line].x, contact_pos = vector(self.vertical_line_positions[msb_line].x,
msf_msb_din.y - 0.5*self.m2m3_via.width] msf_msb_din.y - 0.5*self.m2m3_via.width)
self.add_rect(layer="metal3", self.add_rect(layer="metal3",
offset=contact_pos, offset=contact_pos,
width=msf_msb_din[0] - contact_pos[0], width=msf_msb_din.x - contact_pos.x,
height=drc["minwidth_metal3"]) height=drc["minwidth_metal3"])
self.add_via(layers=("metal2", "via2", "metal3"), self.add_via(layers=("metal2", "via2", "metal3"),
offset=contact_pos) offset=contact_pos)
@ -785,9 +785,9 @@ class sram(design.design):
height=drc["minwidth_metal1"]) height=drc["minwidth_metal1"])
if(self.num_banks == 2): if(self.num_banks == 2):
msb_msf_dout_position = (self.msf_msb_address.dout_positions[i].rotate().scale(1, -1) msb_msf_dout_position = (self.msf_msb_address.dout_positions[i].rotate_scale(1, -1)
+ self.msf_msb_address_position) + self.msf_msb_address_position)
msb_msf_dout_bar_position = (self.msf_msb_address.dout_bar_positions[i].rotate().scale(1, -1) msb_msf_dout_bar_position = (self.msf_msb_address.dout_bar_positions[i].rotate_scale(1, -1)
+ self.msf_msb_address_position) + self.msf_msb_address_position)
starts = [msb_msf_dout_bar_position, starts = [msb_msf_dout_bar_position,
msb_msf_dout_position] msb_msf_dout_position]
@ -801,9 +801,9 @@ class sram(design.design):
+ self.msf_msb_address.height + self.msf_msb_address.height
+ 4 * (i + 1) * drc["minwidth_metal2"], + 4 * (i + 1) * drc["minwidth_metal2"],
start.y) start.y)
end = vector(mid1.x, self.msf_msb_address_position[1] end = vector(mid1.x, self.msf_msb_address_position.y
+ 4 * (i + 1) * drc["minwidth_metal2"]) + 4 * (i + 1) * drc["minwidth_metal2"])
self.add_wire(("metal1", "via1", "metal2"), [start, mid1, end]) self.add_wire(("metal2", "via1", "metal1"), [start, mid1, end])
x_off = self.vertical_line_positions[bank_select_line].x x_off = self.vertical_line_positions[bank_select_line].x
contact_pos = vector(x_off, contact_pos = vector(x_off,
@ -818,7 +818,7 @@ class sram(design.design):
if(self.num_banks == 4): if(self.num_banks == 4):
for i in range(2): for i in range(2):
msb_msf_out_position = (self.msf_msb_address.dout_positions[i].rotate().scale(1, -1) msb_msf_out_position = (self.msf_msb_address.dout_positions[i].rotate_scale(1, -1)
+ self.msf_msb_address_position) + self.msf_msb_address_position)
msb_decoder_in_position =(self.msb_decoder.A_positions[i].scale(-1, 1) msb_decoder_in_position =(self.msb_decoder.A_positions[i].scale(-1, 1)
+ self.msb_decoder_position + self.msb_decoder_position
@ -827,11 +827,11 @@ class sram(design.design):
start = msb_msf_out_position start = msb_msf_out_position
mid1 = start + vector(4 * (i + 1) * drc["minwidth_metal1"], 0) mid1 = start + vector(4 * (i + 1) * drc["minwidth_metal1"], 0)
mid2 = vector(mid1.x, msb_decoder_in_position.y) mid2 = vector(mid1.x, msb_decoder_in_position.y)
end = vector(self.msb_decoder_position[0] end = vector(self.msb_decoder_position.x
+ 3*drc["minwidth_metal3"], + 3*drc["minwidth_metal3"],
mid2.y) mid2.y)
layer_stack = ("metal1", "via1", "metal2") layer_stack = ("metal2", "via1", "metal1")
self.add_wire(layer_stack, [start, mid1, mid2, end]) self.add_wire(layer_stack, [start, mid1, mid2, end])
self.add_rect(layer="metal1", self.add_rect(layer="metal1",
@ -874,9 +874,9 @@ class sram(design.design):
# control logic # control logic
self.control_vdd1_position = (self.control_position self.control_vdd1_position = (self.control_position
+ self.control.vdd1_position.rotate().scale(-1, 1)) + self.control.vdd1_position.rotate_scale(-1, 1))
self.control_vdd2_position = (self.control_position self.control_vdd2_position = (self.control_position
+ self.control.vdd2_position.rotate().scale(-1, 1)) + self.control.vdd2_position.rotate_scale(-1, 1))
self.add_rect(layer="metal1", self.add_rect(layer="metal1",
offset=self.control_vdd1_position, offset=self.control_vdd1_position,
@ -974,7 +974,7 @@ class sram(design.design):
# msf_msb_address # msf_msb_address
start = msf_address_vdd_position = (self.msf_msb_address_position start = msf_address_vdd_position = (self.msf_msb_address_position
+ self.msf_msb_address.vdd_positions[0].rotate().scale(1,-1)) + self.msf_msb_address.vdd_positions[0].rotate_scale(1,-1))
mid1 = vector(start.x, mid1 = vector(start.x,
self.msf_msb_address_position.y self.msf_msb_address_position.y
- self.msf_msb_address.width - self.msf_msb_address.width
@ -1029,7 +1029,7 @@ class sram(design.design):
offset=self.gnd_offset) offset=self.gnd_offset)
self.control_gnd_position = (self.control_position self.control_gnd_position = (self.control_position
+ self.control.gnd_position.rotate().scale(-1,1) + self.control.gnd_position.rotate_scale(-1,1)
+ vector(drc["minwidth_metal2"],0)) + vector(drc["minwidth_metal2"],0))
self.add_rect(layer="metal3", self.add_rect(layer="metal3",
@ -1070,12 +1070,12 @@ class sram(design.design):
self.add_rect(layer="metal2", self.add_rect(layer="metal2",
offset=self.sram_bank_left_gnd_positions[0], offset=self.sram_bank_left_gnd_positions[0],
width=drc["minwidth_metal2"], width=drc["minwidth_metal2"],
height=control_gnd_supply[1] + drc["minwidth_metal1"] height=control_gnd_supply.y + drc["minwidth_metal1"]
- self.sram_bank_left_gnd_positions[0].y) - self.sram_bank_left_gnd_positions[0].y)
self.add_via(layers=("metal1", "via1", "metal2"), self.add_via(layers=("metal1", "via1", "metal2"),
offset=[self.sram_bank_left_gnd_positions[0].x offset=[self.sram_bank_left_gnd_positions[0].x
+ drc["minwidth_metal2"], + drc["minwidth_metal2"],
control_gnd_supply[1]], control_gnd_supply.y],
mirror="R90") mirror="R90")
# Control gnd # Control gnd
self.add_via(layers=("metal1", "via1", "metal2"), self.add_via(layers=("metal1", "via1", "metal2"),

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python2.7 #!/usr/bin/env python2.7
import unittest import unittest
from header import header from testutils import header
import sys,os import sys,os
sys.path.append(os.path.join(sys.path[0],"..")) sys.path.append(os.path.join(sys.path[0],".."))
import globals import globals

View File

@ -2,7 +2,7 @@
"Run a regresion test the library cells for DRC" "Run a regresion test the library cells for DRC"
import unittest import unittest
from header import header from testutils import header
import sys,os import sys,os
sys.path.append(os.path.join(sys.path[0],"..")) sys.path.append(os.path.join(sys.path[0],".."))
import globals import globals
@ -33,7 +33,7 @@ class library_drc_test(unittest.TestCase):
# fails if there are any DRC errors on any cells # fails if there are any DRC errors on any cells
self.assertEqual(drc_errors, 0) self.assertEqual(drc_errors, 0)
globals.end_openram()
def setup_files(): def setup_files():
gds_dir = OPTS.openram_tech + "/gds_lib" gds_dir = OPTS.openram_tech + "/gds_lib"

View File

@ -2,7 +2,7 @@
"Run a regresion test the library cells for LVS" "Run a regresion test the library cells for LVS"
import unittest import unittest
from header import header from testutils import header
import sys,os import sys,os
sys.path.append(os.path.join(sys.path[0],"..")) sys.path.append(os.path.join(sys.path[0],".."))
import globals import globals
@ -37,7 +37,7 @@ class library_lvs_test(unittest.TestCase):
# fail if the error count is not zero # fail if the error count is not zero
self.assertEqual(lvs_errors, 0) self.assertEqual(lvs_errors, 0)
globals.end_openram()
def setup_files(): def setup_files():
gds_dir = OPTS.openram_tech + "/gds_lib" gds_dir = OPTS.openram_tech + "/gds_lib"

View File

@ -2,7 +2,7 @@
"Run a regresion test for DRC on basic contacts of different array sizes" "Run a regresion test for DRC on basic contacts of different array sizes"
import unittest import unittest
from header import header from testutils import header
import sys,os import sys,os
sys.path.append(os.path.join(sys.path[0],"..")) sys.path.append(os.path.join(sys.path[0],".."))
import globals import globals
@ -54,6 +54,7 @@ class contact_test(unittest.TestCase):
self.local_check(c) self.local_check(c)
OPTS.check_lvsdrc = True OPTS.check_lvsdrc = True
globals.end_openram()
def local_check(self, c): def local_check(self, c):
tempgds = OPTS.openram_temp + "temp.gds" tempgds = OPTS.openram_temp + "temp.gds"

View File

@ -2,7 +2,7 @@
"Run a regresion test on a basic path" "Run a regresion test on a basic path"
import unittest import unittest
from header import header from testutils import header
import sys,os import sys,os
sys.path.append(os.path.join(sys.path[0],"..")) sys.path.append(os.path.join(sys.path[0],".."))
import globals import globals
@ -75,6 +75,7 @@ class path_test(unittest.TestCase):
# return it back to it's normal state # return it back to it's normal state
OPTS.check_lvsdrc = True OPTS.check_lvsdrc = True
globals.end_openram()
def local_check(self, w): def local_check(self, w):
tempgds = OPTS.openram_temp + "temp.gds" tempgds = OPTS.openram_temp + "temp.gds"

View File

@ -2,7 +2,7 @@
"Run a regresion test on a basic parameterized transistors" "Run a regresion test on a basic parameterized transistors"
import unittest import unittest
from header import header from testutils import header
import sys,os import sys,os
sys.path.append(os.path.join(sys.path[0],"..")) sys.path.append(os.path.join(sys.path[0],".."))
import globals import globals
@ -33,7 +33,7 @@ class ptx_test(unittest.TestCase):
OPTS.check_lvsdrc = True OPTS.check_lvsdrc = True
self.local_check(fet) self.local_check(fet)
globals.end_openram()
def add_mods(self, fet): def add_mods(self, fet):

View File

@ -2,7 +2,7 @@
"Run a regresion test on a basic parameterized transistors" "Run a regresion test on a basic parameterized transistors"
import unittest import unittest
from header import header from testutils import header
import sys,os import sys,os
sys.path.append(os.path.join(sys.path[0],"..")) sys.path.append(os.path.join(sys.path[0],".."))
import globals import globals
@ -33,7 +33,7 @@ class ptx_test(unittest.TestCase):
OPTS.check_lvsdrc = True OPTS.check_lvsdrc = True
self.local_check(fet) self.local_check(fet)
globals.end_openram()
def add_mods(self, fet): def add_mods(self, fet):

View File

@ -2,7 +2,7 @@
"Run a regresion test on a basic parameterized transistors" "Run a regresion test on a basic parameterized transistors"
import unittest import unittest
from header import header from testutils import header
import sys,os import sys,os
sys.path.append(os.path.join(sys.path[0],"..")) sys.path.append(os.path.join(sys.path[0],".."))
import globals import globals
@ -33,7 +33,7 @@ class ptx_test(unittest.TestCase):
OPTS.check_lvsdrc = True OPTS.check_lvsdrc = True
self.local_check(fet) self.local_check(fet)
globals.end_openram()
def add_mods(self, fet): def add_mods(self, fet):
self.create_contacts() self.create_contacts()

View File

@ -2,7 +2,7 @@
"Run a regresion test on a basic parameterized transistors" "Run a regresion test on a basic parameterized transistors"
import unittest import unittest
from header import header from testutils import header
import sys,os import sys,os
sys.path.append(os.path.join(sys.path[0],"..")) sys.path.append(os.path.join(sys.path[0],".."))
import globals import globals
@ -33,6 +33,7 @@ class ptx_test(unittest.TestCase):
OPTS.check_lvsdrc = True OPTS.check_lvsdrc = True
self.local_check(fet) self.local_check(fet)
globals.end_openram()
def add_mods(self, fet): def add_mods(self, fet):
self.create_contacts() self.create_contacts()

View File

@ -2,7 +2,7 @@
"Run a regresion test on a basic wire" "Run a regresion test on a basic wire"
import unittest import unittest
from header import header from testutils import header
import sys,os import sys,os
sys.path.append(os.path.join(sys.path[0],"..")) sys.path.append(os.path.join(sys.path[0],".."))
import globals import globals
@ -128,6 +128,7 @@ class wire_test(unittest.TestCase):
# return it back to it's normal state # return it back to it's normal state
OPTS.check_lvsdrc = True OPTS.check_lvsdrc = True
globals.end_openram()
def local_check(self, w): def local_check(self, w):
tempgds = OPTS.openram_temp + "temp.gds" tempgds = OPTS.openram_temp + "temp.gds"

View File

@ -6,7 +6,7 @@ size 2_input nand gate that is nmos_width=2*tech.drc[minwidth_tx].
""" """
import unittest import unittest
from header import header from testutils import header
import sys,os import sys,os
sys.path.append(os.path.join(sys.path[0],"..")) sys.path.append(os.path.join(sys.path[0],".."))
import globals import globals
@ -33,6 +33,7 @@ class nand_2_test(unittest.TestCase):
tx = nand_2.nand_2(name="a_nand_1", nmos_width=2 * tech.drc["minwidth_tx"]) tx = nand_2.nand_2(name="a_nand_1", nmos_width=2 * tech.drc["minwidth_tx"])
OPTS.check_lvsdrc = True OPTS.check_lvsdrc = True
self.local_check(tx) self.local_check(tx)
globals.end_openram()
def local_check(self, tx): def local_check(self, tx):

View File

@ -6,7 +6,7 @@ It generate only the minimum size 3_input nand gate that is nmos_width=3*tech.dr
""" """
import unittest import unittest
from header import header from testutils import header
import sys,os import sys,os
sys.path.append(os.path.join(sys.path[0],"..")) sys.path.append(os.path.join(sys.path[0],".."))
import globals import globals
@ -31,6 +31,7 @@ class nand_3_test(unittest.TestCase):
OPTS.check_lvsdrc = True OPTS.check_lvsdrc = True
self.local_check(tx) self.local_check(tx)
globals.end_openram()
def local_check(self, tx): def local_check(self, tx):
tempspice = OPTS.openram_temp + "temp.sp" tempspice = OPTS.openram_temp + "temp.sp"

View File

@ -5,7 +5,7 @@ This module doesn't generate multi_finger 2_input nor gate
It generate only the minimum size 2_input nor gate that is nmos_width=2*tech.drc[minwidth_tx] It generate only the minimum size 2_input nor gate that is nmos_width=2*tech.drc[minwidth_tx]
""" """
import unittest import unittest
from header import header from testutils import header
import sys,os import sys,os
sys.path.append(os.path.join(sys.path[0],"..")) sys.path.append(os.path.join(sys.path[0],".."))
import globals import globals
@ -32,7 +32,7 @@ class nor_2_test(unittest.TestCase):
tx = nor_2.nor_2(name="a_nor_1", nmos_width=2 * tech.drc["minwidth_tx"]) tx = nor_2.nor_2(name="a_nor_1", nmos_width=2 * tech.drc["minwidth_tx"])
OPTS.check_lvsdrc = True OPTS.check_lvsdrc = True
self.local_check(tx) self.local_check(tx)
globals.end_openram()
def local_check(self, tx): def local_check(self, tx):
tempspice = OPTS.openram_temp + "temp.sp" tempspice = OPTS.openram_temp + "temp.sp"

View File

@ -4,7 +4,7 @@ Run regresion tests on a parameterized inverter
""" """
import unittest import unittest
from header import header from testutils import header
import sys,os import sys,os
sys.path.append(os.path.join(sys.path[0],"..")) sys.path.append(os.path.join(sys.path[0],".."))
import globals import globals
@ -42,6 +42,7 @@ class pinv_test(unittest.TestCase):
OPTS.check_lvsdrc = True OPTS.check_lvsdrc = True
self.local_check(tx) self.local_check(tx)
globals.end_openram()
def local_check(self, tx): def local_check(self, tx):
tempspice = OPTS.openram_temp + "temp.sp" tempspice = OPTS.openram_temp + "temp.sp"

View File

@ -4,7 +4,7 @@ Run a regresion test on a wordline_driver array
""" """
import unittest import unittest
from header import header from testutils import header
import sys,os import sys,os
sys.path.append(os.path.join(sys.path[0],"..")) sys.path.append(os.path.join(sys.path[0],".."))
import globals import globals
@ -33,7 +33,7 @@ class wordline_driver_test(unittest.TestCase):
OPTS.check_lvsdrc = True OPTS.check_lvsdrc = True
self.local_check(tx) self.local_check(tx)
globals.end_openram()
def local_check(self, tx): def local_check(self, tx):
tempspice = OPTS.openram_temp + "temp.sp" tempspice = OPTS.openram_temp + "temp.sp"
tempgds = OPTS.openram_temp + "temp.gds" tempgds = OPTS.openram_temp + "temp.gds"

View File

@ -4,7 +4,7 @@ Run a regresion test on a basic array
""" """
import unittest import unittest
from header import header from testutils import header
import sys,os import sys,os
sys.path.append(os.path.join(sys.path[0],"..")) sys.path.append(os.path.join(sys.path[0],".."))
import globals import globals
@ -31,7 +31,7 @@ class array_test(unittest.TestCase):
OPTS.check_lvsdrc = True OPTS.check_lvsdrc = True
self.local_check(a) self.local_check(a)
globals.end_openram()
def local_check(self, a): def local_check(self, a):
tempspice = OPTS.openram_temp + "temp.sp" tempspice = OPTS.openram_temp + "temp.sp"

View File

@ -4,7 +4,7 @@ Run a regresion test on a thierarchy_decoder.
""" """
import unittest import unittest
from header import header from testutils import header
import sys,os import sys,os
sys.path.append(os.path.join(sys.path[0],"..")) sys.path.append(os.path.join(sys.path[0],".."))
import globals import globals
@ -57,6 +57,7 @@ class hierarchical_decoder_test(unittest.TestCase):
OPTS.check_lvsdrc = True OPTS.check_lvsdrc = True
self.local_check(a) self.local_check(a)
globals.end_openram()
def local_check(self, a): def local_check(self, a):
tempspice = OPTS.openram_temp + "temp.sp" tempspice = OPTS.openram_temp + "temp.sp"

View File

@ -4,7 +4,7 @@ Run a regresion test on a hierarchical_predecode2x4.
""" """
import unittest import unittest
from header import header from testutils import header
import sys,os import sys,os
sys.path.append(os.path.join(sys.path[0],"..")) sys.path.append(os.path.join(sys.path[0],".."))
import globals import globals
@ -30,6 +30,7 @@ class hierarchical_predecode2x4_test(unittest.TestCase):
OPTS.check_lvsdrc = True OPTS.check_lvsdrc = True
self.local_check(a) self.local_check(a)
globals.end_openram()
def local_check(self, a): def local_check(self, a):
tempspice = OPTS.openram_temp + "temp.sp" tempspice = OPTS.openram_temp + "temp.sp"

View File

@ -4,7 +4,7 @@ Run a regresion test on a hierarchical_predecode3x8.
""" """
import unittest import unittest
from header import header from testutils import header
import sys,os import sys,os
sys.path.append(os.path.join(sys.path[0],"..")) sys.path.append(os.path.join(sys.path[0],".."))
import globals import globals
@ -30,6 +30,7 @@ class hierarchical_predecode3x8_test(unittest.TestCase):
OPTS.check_lvsdrc = True OPTS.check_lvsdrc = True
self.local_check(a) self.local_check(a)
globals.end_openram()
def local_check(self, a): def local_check(self, a):
tempspice = OPTS.openram_temp + "temp.sp" tempspice = OPTS.openram_temp + "temp.sp"

View File

@ -4,7 +4,7 @@ Run a regresion test on a single transistor column_mux.
""" """
import unittest import unittest
from header import header from testutils import header
import sys,os import sys,os
sys.path.append(os.path.join(sys.path[0],"..")) sys.path.append(os.path.join(sys.path[0],".."))
import globals import globals
@ -28,6 +28,7 @@ class single_level_column_mux_test(unittest.TestCase):
rows=32, columns=32, word_size=16) rows=32, columns=32, word_size=16)
OPTS.check_lvsdrc = True OPTS.check_lvsdrc = True
self.local_check(a) self.local_check(a)
globals.end_openram()
def local_check(self, a): def local_check(self, a):
tempspice = OPTS.openram_temp + "temp.sp" tempspice = OPTS.openram_temp + "temp.sp"

View File

@ -4,7 +4,7 @@ Run a regresion test on a precharge array
""" """
import unittest import unittest
from header import header from testutils import header
import sys,os import sys,os
sys.path.append(os.path.join(sys.path[0],"..")) sys.path.append(os.path.join(sys.path[0],".."))
import globals import globals
@ -38,6 +38,7 @@ class precharge_test(unittest.TestCase):
OPTS.check_lvsdrc = True OPTS.check_lvsdrc = True
self.local_check(pc) self.local_check(pc)
globals.end_openram()
def local_check(self, pc): def local_check(self, pc):
tempspice = OPTS.openram_temp + "temp.sp" tempspice = OPTS.openram_temp + "temp.sp"

View File

@ -4,7 +4,7 @@ Run a regresion test on a sense amp array
""" """
import unittest import unittest
from header import header from testutils import header
import sys,os import sys,os
sys.path.append(os.path.join(sys.path[0],"..")) sys.path.append(os.path.join(sys.path[0],".."))
import globals import globals
@ -41,6 +41,7 @@ class sense_amp_test(unittest.TestCase):
OPTS.check_lvsdrc = True OPTS.check_lvsdrc = True
self.local_check(a) self.local_check(a)
globals.end_openram()
def local_check(self, a): def local_check(self, a):
tempspice = OPTS.openram_temp + "temp.sp" tempspice = OPTS.openram_temp + "temp.sp"

View File

@ -4,7 +4,7 @@ Run a regresion test on a write driver array
""" """
import unittest import unittest
from header import header from testutils import header
import sys,os import sys,os
sys.path.append(os.path.join(sys.path[0],"..")) sys.path.append(os.path.join(sys.path[0],".."))
import globals import globals
@ -35,6 +35,7 @@ class write_driver_test(unittest.TestCase):
OPTS.check_lvsdrc = True OPTS.check_lvsdrc = True
self.local_check(a) self.local_check(a)
globals.end_openram()
def local_check(self, a): def local_check(self, a):
tempspice = OPTS.openram_temp + "temp.sp" tempspice = OPTS.openram_temp + "temp.sp"

View File

@ -4,7 +4,7 @@ Run a regresion test on a dff_array.
""" """
import unittest import unittest
from header import header from testutils import header
import sys,os import sys,os
sys.path.append(os.path.join(sys.path[0],"..")) sys.path.append(os.path.join(sys.path[0],".."))
import globals import globals
@ -31,6 +31,7 @@ class dff_array_test(unittest.TestCase):
OPTS.check_lvsdrc = True OPTS.check_lvsdrc = True
self.local_check(a) self.local_check(a)
globals.end_openram()
def local_check(self, a): def local_check(self, a):
tempspice = OPTS.openram_temp + "temp.sp" tempspice = OPTS.openram_temp + "temp.sp"

View File

@ -4,7 +4,7 @@ Run a regresion test on a control_logic
""" """
import unittest import unittest
from header import header from testutils import header
import sys,os import sys,os
sys.path.append(os.path.join(sys.path[0],"..")) sys.path.append(os.path.join(sys.path[0],".."))
import globals import globals
@ -29,6 +29,7 @@ class control_logic_test(unittest.TestCase):
OPTS.check_lvsdrc = True OPTS.check_lvsdrc = True
self.local_check(a) self.local_check(a)
globals.end_openram()
def local_check(self, a): def local_check(self, a):
tempspice = OPTS.openram_temp + "temp.sp" tempspice = OPTS.openram_temp + "temp.sp"

View File

@ -4,7 +4,7 @@ Run a test on a delay chain
""" """
import unittest import unittest
from header import header from testutils import header
import sys,os import sys,os
sys.path.append(os.path.join(sys.path[0],"..")) sys.path.append(os.path.join(sys.path[0],".."))
import globals import globals
@ -31,6 +31,8 @@ class logic_effort_dc_test(unittest.TestCase):
OPTS.check_lvsdrc = True OPTS.check_lvsdrc = True
self.local_check(a) self.local_check(a)
globals.end_openram()
def local_check(self, a): def local_check(self, a):
tempspice = OPTS.openram_temp + "temp.sp" tempspice = OPTS.openram_temp + "temp.sp"
tempgds = OPTS.openram_temp + "temp.gds" tempgds = OPTS.openram_temp + "temp.gds"

View File

@ -4,7 +4,7 @@ Run a regresion test on a tri_gate_array.
""" """
import unittest import unittest
from header import header from testutils import header
import sys,os import sys,os
sys.path.append(os.path.join(sys.path[0],"..")) sys.path.append(os.path.join(sys.path[0],".."))
import globals import globals
@ -28,6 +28,8 @@ class tri_gate_array_test(unittest.TestCase):
OPTS.check_lvsdrc = True OPTS.check_lvsdrc = True
self.local_check(a) self.local_check(a)
globals.end_openram()
def local_check(self, a): def local_check(self, a):
tempspice = OPTS.openram_temp + "temp.sp" tempspice = OPTS.openram_temp + "temp.sp"
tempgds = OPTS.openram_temp + "temp.gds" tempgds = OPTS.openram_temp + "temp.gds"

View File

@ -4,7 +4,7 @@ Run a test on a delay chain
""" """
import unittest import unittest
from header import header from testutils import header
import sys,os import sys,os
sys.path.append(os.path.join(sys.path[0],"..")) sys.path.append(os.path.join(sys.path[0],".."))
import globals import globals
@ -31,6 +31,8 @@ class replica_bitline_test(unittest.TestCase):
OPTS.check_lvsdrc = True OPTS.check_lvsdrc = True
self.local_check(a) self.local_check(a)
globals.end_openram()
def local_check(self, a): def local_check(self, a):
tempspice = OPTS.openram_temp + "temp.sp" tempspice = OPTS.openram_temp + "temp.sp"
tempgds = OPTS.openram_temp + "temp.gds" tempgds = OPTS.openram_temp + "temp.gds"

View File

@ -4,7 +4,7 @@ Run a regresion test on various srams
""" """
import unittest import unittest
from header import header from testutils import header
import sys,os import sys,os
sys.path.append(os.path.join(sys.path[0],"..")) sys.path.append(os.path.join(sys.path[0],".."))
import globals import globals
@ -35,6 +35,8 @@ class bank_test(unittest.TestCase):
OPTS.check_lvsdrc = True OPTS.check_lvsdrc = True
self.local_check(a) self.local_check(a)
globals.end_openram()
def local_check(self, a): def local_check(self, a):
tempspice = OPTS.openram_temp + "temp.sp" tempspice = OPTS.openram_temp + "temp.sp"
tempgds = OPTS.openram_temp + "temp.gds" tempgds = OPTS.openram_temp + "temp.gds"

View File

@ -4,7 +4,7 @@ Run a regresion test on a 1 bank SRAM
""" """
import unittest import unittest
from header import header from testutils import header
import sys,os import sys,os
sys.path.append(os.path.join(sys.path[0],"..")) sys.path.append(os.path.join(sys.path[0],".."))
import globals import globals
@ -30,6 +30,7 @@ class sram_1bank_test(unittest.TestCase):
OPTS.check_lvsdrc = True OPTS.check_lvsdrc = True
self.local_check(a) self.local_check(a)
globals.end_openram()
def local_check(self, a): def local_check(self, a):
tempspice = OPTS.openram_temp + "temp.sp" tempspice = OPTS.openram_temp + "temp.sp"

View File

@ -4,7 +4,7 @@ Run a regresion test on a 2 bank SRAM
""" """
import unittest import unittest
from header import header from testutils import header
import sys,os import sys,os
sys.path.append(os.path.join(sys.path[0],"..")) sys.path.append(os.path.join(sys.path[0],".."))
import globals import globals
@ -30,6 +30,8 @@ class sram_2bank_test(unittest.TestCase):
OPTS.check_lvsdrc = True OPTS.check_lvsdrc = True
self.local_check(a) self.local_check(a)
globals.end_openram()
def local_check(self, a): def local_check(self, a):
tempspice = OPTS.openram_temp + "temp.sp" tempspice = OPTS.openram_temp + "temp.sp"
tempgds = OPTS.openram_temp + "temp.gds" tempgds = OPTS.openram_temp + "temp.gds"

View File

@ -4,7 +4,7 @@ Run a regresion test on a 4 bank SRAM
""" """
import unittest import unittest
from header import header from testutils import header
import sys,os import sys,os
sys.path.append(os.path.join(sys.path[0],"..")) sys.path.append(os.path.join(sys.path[0],".."))
import globals import globals
@ -30,6 +30,8 @@ class sram_4bank_test(unittest.TestCase):
OPTS.check_lvsdrc = True OPTS.check_lvsdrc = True
self.local_check(a) self.local_check(a)
globals.end_openram()
def local_check(self, a): def local_check(self, a):
tempspice = OPTS.openram_temp + "temp.sp" tempspice = OPTS.openram_temp + "temp.sp"
tempgds = OPTS.openram_temp + "temp.gds" tempgds = OPTS.openram_temp + "temp.gds"

View File

@ -4,7 +4,7 @@ Run a regresion test on various srams
""" """
import unittest import unittest
from header import header from testutils import header,isclose
import sys,os import sys,os
sys.path.append(os.path.join(sys.path[0],"..")) sys.path.append(os.path.join(sys.path[0],".."))
import globals import globals
@ -22,7 +22,9 @@ class timing_sram_test(unittest.TestCase):
globals.init_openram("config_20_{0}".format(OPTS.tech_name)) globals.init_openram("config_20_{0}".format(OPTS.tech_name))
# we will manually run lvs/drc # we will manually run lvs/drc
OPTS.check_lvsdrc = False OPTS.check_lvsdrc = False
OPTS.use_pex = False OPTS.spice_version="hspice"
OPTS.force_spice = True
globals.set_spice()
import sram import sram
@ -61,10 +63,7 @@ class timing_sram_test(unittest.TestCase):
os.remove(tempspice) os.remove(tempspice)
def isclose(value1,value2): globals.end_openram()
""" This is used to compare relative values for convergence. """
return (abs(value1 - value2) / max(value1,value2) <= 1e-2)
# instantiate a copdsay of the class to actually run the test # instantiate a copdsay of the class to actually run the test
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -4,7 +4,7 @@ Run a regresion test on various srams
""" """
import unittest import unittest
from header import header from testutils import header,isclose
import sys,os import sys,os
sys.path.append(os.path.join(sys.path[0],"..")) sys.path.append(os.path.join(sys.path[0],".."))
import globals import globals
@ -22,7 +22,9 @@ class timing_setup_test(unittest.TestCase):
globals.init_openram("config_20_{0}".format(OPTS.tech_name)) globals.init_openram("config_20_{0}".format(OPTS.tech_name))
# we will manually run lvs/drc # we will manually run lvs/drc
OPTS.check_lvsdrc = False OPTS.check_lvsdrc = False
OPTS.use_pex = False OPTS.spice_version="hspice"
OPTS.force_spice = True
globals.set_spice()
import sram import sram
import setup_hold import setup_hold
@ -41,10 +43,7 @@ class timing_setup_test(unittest.TestCase):
else: else:
self.assertTrue(False) # other techs fail self.assertTrue(False) # other techs fail
def isclose(value1,value2): globals.end_openram()
""" This is used to compare relative values for convergence. """
return (abs(value1 - value2) / max(value1,value2) <= 1e-2)
# instantiate a copdsay of the class to actually run the test # instantiate a copdsay of the class to actually run the test
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -4,7 +4,7 @@ Run a regresion test on various srams
""" """
import unittest import unittest
from header import header from testutils import header,isclose
import sys,os import sys,os
sys.path.append(os.path.join(sys.path[0],"..")) sys.path.append(os.path.join(sys.path[0],".."))
import globals import globals
@ -20,9 +20,12 @@ class timing_setup_test(unittest.TestCase):
def runTest(self): def runTest(self):
globals.init_openram("config_20_{0}".format(OPTS.tech_name)) globals.init_openram("config_20_{0}".format(OPTS.tech_name))
# we will manually run lvs/drc # we will manually run lvs/drc
OPTS.check_lvsdrc = False OPTS.check_lvsdrc = False
OPTS.use_pex = False OPTS.spice_version="hspice"
OPTS.force_spice = True
globals.set_spice()
import sram import sram
import setup_hold import setup_hold
@ -40,10 +43,7 @@ class timing_setup_test(unittest.TestCase):
else: else:
self.assertTrue(False) # other techs fail self.assertTrue(False) # other techs fail
def isclose(value1,value2): globals.end_openram()
""" This is used to compare relative values for convergence. """
return (abs(value1 - value2) / max(value1,value2) <= 1e-2)
# instantiate a copdsay of the class to actually run the test # instantiate a copdsay of the class to actually run the test
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -0,0 +1,73 @@
#!/usr/bin/env python2.7
"""
Run a regresion test on various srams
"""
import unittest
from testutils import header,isclose
import sys,os
sys.path.append(os.path.join(sys.path[0],".."))
import globals
import debug
import calibre
OPTS = globals.get_opts()
#@unittest.skip("SKIPPING 21_ngspice_delay_test")
class timing_sram_test(unittest.TestCase):
def runTest(self):
globals.init_openram("config_20_{0}".format(OPTS.tech_name))
# we will manually run lvs/drc
OPTS.check_lvsdrc = False
OPTS.spice_version="ngspice"
OPTS.force_spice = True
globals.set_spice()
import sram
debug.info(1, "Testing timing for sample 1bit, 16words SRAM with 1 bank")
s = sram.sram(word_size=OPTS.config.word_size,
num_words=OPTS.config.num_words,
num_banks=OPTS.config.num_banks,
name="test_sram1")
# reset these options
OPTS.check_lvsdrc = True
OPTS.spice_version="hspice"
OPTS.force_spice = False
globals.set_spice()
import delay
tempspice = OPTS.openram_temp + "temp.sp"
s.sp_write(tempspice)
probe_address = "1" * s.addr_size
probe_data = s.word_size - 1
debug.info(1, "Probe address {0} probe data {1}".format(probe_address, probe_data))
d = delay.delay(s,tempspice)
data = d.analyze(probe_address, probe_data)
if OPTS.tech_name == "freepdk45":
self.assertTrue(isclose(data['delay1'],0.013649)) # diff than hspice
self.assertTrue(isclose(data['delay0'],0.22893)) # diff than hspice
self.assertTrue(isclose(data['min_period1'],0.078582763671875)) # diff than hspice
self.assertTrue(isclose(data['min_period0'],0.25543212890625)) # diff than hspice
elif OPTS.tech_name == "scn3me_subm":
self.assertTrue(isclose(data['delay1'],1.5342000000000002)) # diff than hspice
self.assertTrue(isclose(data['delay0'],2.2698)) # diff than hspice
self.assertTrue(isclose(data['min_period1'],1.534423828125)) # diff than hspice
self.assertTrue(isclose(data['min_period0'],2.99560546875)) # diff than hspice
else:
self.assertTrue(False) # other techs fail
os.remove(tempspice)
# instantiate a copdsay of the class to actually run the test
if __name__ == "__main__":
(OPTS, args) = globals.parse_args()
del sys.argv[1:]
header(__file__, OPTS.tech_name)
unittest.main()

View File

@ -0,0 +1,55 @@
#!/usr/bin/env python2.7
"""
Run a regresion test on various srams
"""
import unittest
from testutils import header,isclose
import sys,os
sys.path.append(os.path.join(sys.path[0],".."))
import globals
import debug
import calibre
OPTS = globals.get_opts()
#@unittest.skip("SKIPPING 21_timing_sram_test")
class timing_setup_test(unittest.TestCase):
def runTest(self):
globals.init_openram("config_20_{0}".format(OPTS.tech_name))
# we will manually run lvs/drc
OPTS.check_lvsdrc = False
OPTS.spice_version="ngspice"
OPTS.force_spice = True
globals.set_spice()
import sram
import setup_hold
sh = setup_hold.setup_hold()
[one_setup_time, zero_setup_time] = sh.hold_time()
# reset these options
OPTS.check_lvsdrc = True
OPTS.spice_version="hspice"
OPTS.force_spice = False
globals.set_spice()
if OPTS.tech_name == "freepdk45":
self.assertTrue(isclose(one_setup_time,-0.0048828125))
self.assertTrue(isclose(zero_setup_time,-0.010986328125))
elif OPTS.tech_name == "scn3me_subm":
self.assertTrue(isclose(one_setup_time,0.45654296875)) # diff than hspice
self.assertTrue(isclose(zero_setup_time,-0.0830078125))
else:
self.assertTrue(False) # other techs fail
# instantiate a copdsay of the class to actually run the test
if __name__ == "__main__":
(OPTS, args) = globals.parse_args()
del sys.argv[1:]
header(__file__, OPTS.tech_name)
unittest.main()

View File

@ -0,0 +1,55 @@
#!/usr/bin/env python2.7
"""
Run a regresion test on various srams
"""
import unittest
from testutils import header,isclose
import sys,os
sys.path.append(os.path.join(sys.path[0],".."))
import globals
import debug
import calibre
OPTS = globals.get_opts()
#@unittest.skip("SKIPPING 21_timing_sram_test")
class timing_setup_test(unittest.TestCase):
def runTest(self):
globals.init_openram("config_20_{0}".format(OPTS.tech_name))
# we will manually run lvs/drc
OPTS.check_lvsdrc = False
OPTS.spice_version="ngspice"
OPTS.force_spice = True
globals.set_spice()
import sram
import setup_hold
sh = setup_hold.setup_hold()
[one_setup_time, zero_setup_time] = sh.setup_time()
# reset these options
OPTS.check_lvsdrc = True
OPTS.spice_version="hspice"
OPTS.force_spice = False
globals.set_spice()
if OPTS.tech_name == "freepdk45":
self.assertTrue(isclose(one_setup_time,0.0146484375))
self.assertTrue(isclose(zero_setup_time,0.008544921875))
elif OPTS.tech_name == "scn3me_subm":
self.assertTrue(isclose(one_setup_time,0.09521484375)) #diff than hspice
self.assertTrue(isclose(zero_setup_time,-0.0244140625))
else:
self.assertTrue(False) # other techs fail
# instantiate a copdsay of the class to actually run the test
if __name__ == "__main__":
(OPTS, args) = globals.parse_args()
del sys.argv[1:]
header(__file__, OPTS.tech_name)
unittest.main()

View File

@ -4,7 +4,7 @@ Run a regression test on an extracted SRAM to ensure functionality.
""" """
import unittest import unittest
from header import header from testutils import header
import sys,os import sys,os
sys.path.append(os.path.join(sys.path[0],"..")) sys.path.append(os.path.join(sys.path[0],".."))
import globals import globals
@ -24,6 +24,8 @@ class sram_func_test(unittest.TestCase):
self.func_test(bank_num=2) self.func_test(bank_num=2)
self.func_test(bank_num=4) self.func_test(bank_num=4)
globals.end_openram()
def func_test(self, bank_num): def func_test(self, bank_num):
import sram import sram

View File

@ -4,7 +4,7 @@ Run a regresion test on various srams
""" """
import unittest import unittest
from header import header from testutils import header
import sys,os import sys,os
sys.path.append(os.path.join(sys.path[0],"..")) sys.path.append(os.path.join(sys.path[0],".."))
import globals import globals
@ -22,7 +22,6 @@ class sram_func_test(unittest.TestCase):
globals.init_openram("config_20_{0}".format(OPTS.tech_name)) globals.init_openram("config_20_{0}".format(OPTS.tech_name))
# we will manually run lvs/drc # we will manually run lvs/drc
OPTS.check_lvsdrc = False OPTS.check_lvsdrc = False
OPTS.use_pex = False
import sram import sram
@ -51,6 +50,8 @@ class sram_func_test(unittest.TestCase):
os.remove(tempspice) os.remove(tempspice)
globals.end_openram()
# instantiate a copdsay of the class to actually run the test # instantiate a copdsay of the class to actually run the test
if __name__ == "__main__": if __name__ == "__main__":
(OPTS, args) = globals.parse_args() (OPTS, args) = globals.parse_args()

View File

@ -4,7 +4,7 @@ Check the .lib file for an SRAM
""" """
import unittest import unittest
from header import header from testutils import header,isdiff
import sys,os import sys,os
sys.path.append(os.path.join(sys.path[0],"..")) sys.path.append(os.path.join(sys.path[0],".."))
import globals import globals
@ -20,11 +20,9 @@ class lib_test(unittest.TestCase):
globals.init_openram("config_20_{0}".format(OPTS.tech_name)) globals.init_openram("config_20_{0}".format(OPTS.tech_name))
# we will manually run lvs/drc # we will manually run lvs/drc
OPTS.check_lvsdrc = False OPTS.check_lvsdrc = False
OPTS.use_pex = False
import sram import sram
import lib import lib
import filecmp
debug.info(1, "Testing timing for sample 2 bit, 16 words SRAM with 1 bank") debug.info(1, "Testing timing for sample 2 bit, 16 words SRAM with 1 bank")
s = sram.sram(word_size=2, s = sram.sram(word_size=2,
@ -33,22 +31,20 @@ class lib_test(unittest.TestCase):
name="sram_2_16_1_{0}".format(OPTS.tech_name)) name="sram_2_16_1_{0}".format(OPTS.tech_name))
OPTS.check_lvsdrc = True OPTS.check_lvsdrc = True
tempspice = OPTS.openram_temp + "temp.sp" tempspice = OPTS.openram_temp + "temp.sp"
s.sp_write(tempspice) s.sp_write(tempspice)
curpath=os.path.dirname(os.path.realpath(__file__)) + "/"
filename = s.name + ".lib" filename = s.name + ".lib"
libname = curpath + filename libname = OPTS.openram_temp + filename
lib.lib(libname,s,tempspice) lib.lib(libname,s,tempspice)
# let's diff the result with a golden model # let's diff the result with a golden model
golden = "{0}/golden/{1}".format(os.path.dirname(os.path.realpath(__file__)),filename) golden = "{0}/golden/{1}".format(os.path.dirname(os.path.realpath(__file__)),filename)
self.assertEqual(filecmp.cmp(libname,golden),True) self.assertEqual(isdiff(libname,golden),True)
os.system("rm {0}".format(libname)) os.system("rm {0}".format(libname))
globals.end_openram()
# instantiate a copdsay of the class to actually run the test # instantiate a copdsay of the class to actually run the test
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -4,7 +4,7 @@ Check the LEF file for an SRMA
""" """
import unittest import unittest
from header import header from testutils import header,isdiff
import sys,os import sys,os
sys.path.append(os.path.join(sys.path[0],"..")) sys.path.append(os.path.join(sys.path[0],".."))
import globals import globals
@ -23,7 +23,6 @@ class lef_test(unittest.TestCase):
import sram import sram
import lef import lef
import filecmp
debug.info(1, "Testing LEF for sample 2 bit, 16 words SRAM with 1 bank") debug.info(1, "Testing LEF for sample 2 bit, 16 words SRAM with 1 bank")
s = sram.sram(word_size=2, s = sram.sram(word_size=2,
@ -33,22 +32,21 @@ class lef_test(unittest.TestCase):
OPTS.check_lvsdrc = True OPTS.check_lvsdrc = True
curpath=os.path.dirname(os.path.realpath(__file__)) + "/"
gdsfile = s.name + ".gds" gdsfile = s.name + ".gds"
leffile = s.name + ".lef" leffile = s.name + ".lef"
gdsname = curpath + gdsfile gdsname = OPTS.openram_temp + gdsfile
lefname = curpath + leffile lefname = OPTS.openram_temp + leffile
s.gds_write(gdsname) s.gds_write(gdsname)
lef.lef(gdsname,lefname,s) lef.lef(gdsname,lefname,s)
# let's diff the result with a golden model # let's diff the result with a golden model
golden = "{0}/golden/{1}".format(os.path.dirname(os.path.realpath(__file__)),leffile) golden = "{0}/golden/{1}".format(os.path.dirname(os.path.realpath(__file__)),leffile)
self.assertEqual(filecmp.cmp(lefname,golden),True) self.assertEqual(isdiff(lefname,golden),True)
os.system("rm {0}".format(gdsname)) os.system("rm {0}".format(gdsname))
os.system("rm {0}".format(lefname)) os.system("rm {0}".format(lefname))
globals.end_openram()
# instantiate a copdsay of the class to actually run the test # instantiate a copdsay of the class to actually run the test
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -4,7 +4,7 @@ Check the .v file for an SRAM
""" """
import unittest import unittest
from header import header from testutils import header,isdiff
import sys,os import sys,os
sys.path.append(os.path.join(sys.path[0],"..")) sys.path.append(os.path.join(sys.path[0],".."))
import globals import globals
@ -23,7 +23,6 @@ class verilog_test(unittest.TestCase):
import sram import sram
import verilog import verilog
import filecmp
debug.info(1, "Testing Verilog for sample 2 bit, 16 words SRAM with 1 bank") debug.info(1, "Testing Verilog for sample 2 bit, 16 words SRAM with 1 bank")
s = sram.sram(word_size=2, s = sram.sram(word_size=2,
@ -33,18 +32,19 @@ class verilog_test(unittest.TestCase):
OPTS.check_lvsdrc = True OPTS.check_lvsdrc = True
curpath=os.path.dirname(os.path.realpath(__file__)) + "/"
vfile = s.name + ".v" vfile = s.name + ".v"
vname = curpath + vfile vname = OPTS.openram_temp + vfile
verilog.verilog(vname,s) verilog.verilog(vname,s)
# let's diff the result with a golden model # let's diff the result with a golden model
golden = "{0}/golden/{1}".format(os.path.dirname(os.path.realpath(__file__)),vfile) golden = "{0}/golden/{1}".format(os.path.dirname(os.path.realpath(__file__)),vfile)
self.assertEqual(filecmp.cmp(vname,golden),True) self.assertEqual(isdiff(vname,golden),True)
os.system("rm {0}".format(vname)) os.system("rm {0}".format(vname))
globals.end_openram()
# instantiate a copdsay of the class to actually run the test # instantiate a copdsay of the class to actually run the test
if __name__ == "__main__": if __name__ == "__main__":
(OPTS, args) = globals.parse_args() (OPTS, args) = globals.parse_args()

View File

@ -6,7 +6,7 @@ check that these files are right.
""" """
import unittest import unittest
from header import header from testutils import header
import sys,os import sys,os
sys.path.append(os.path.join(sys.path[0],"..")) sys.path.append(os.path.join(sys.path[0],".."))
import globals import globals
@ -24,10 +24,8 @@ class openram_test(unittest.TestCase):
debug.info(1, "Testing top-level openram.py with 2-bit, 16 word SRAM.") debug.info(1, "Testing top-level openram.py with 2-bit, 16 word SRAM.")
out_file = "testsram" out_file = "testsram"
# get the directory under the test modules
out_path=os.path.dirname(os.path.realpath(__file__))
# make a temp directory for output # make a temp directory for output
out_path += "/testsram" out_path = OPTS.openram_temp + out_file
# make sure we start without the files existing # make sure we start without the files existing
if os.path.exists(out_path): if os.path.exists(out_path):
@ -73,6 +71,7 @@ class openram_test(unittest.TestCase):
shutil.rmtree(out_path, ignore_errors=True) shutil.rmtree(out_path, ignore_errors=True)
self.assertEqual(os.path.exists(out_path),False) self.assertEqual(os.path.exists(out_path),False)
globals.end_openram()
# instantiate a copdsay of the class to actually run the test # instantiate a copdsay of the class to actually run the test
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -1,10 +0,0 @@
def header(str, tec):
tst = "Running Test for:"
print "\n"
print " ______________________________________________________________________________ "
print "|==============================================================================|"
print "|=========" + tst.center(60) + "=========|"
print "|=========" + tec.center(60) + "=========|"
print "|=========" + str.center(60) + "=========|"
print "|==============================================================================|"

View File

@ -9,8 +9,8 @@ import globals
(OPTS, args) = globals.parse_args() (OPTS, args) = globals.parse_args()
del sys.argv[1:] del sys.argv[1:]
import header from testutils import header
header.header(__file__, OPTS.tech_name) header(__file__, OPTS.tech_name)
# get a list of all files in the tests directory # get a list of all files in the tests directory
files = os.listdir(sys.path[0]) files = os.listdir(sys.path[0])

View File

@ -0,0 +1,43 @@
def isclose(value1,value2,error_tolerance=1e-2):
""" This is used to compare relative values. """
import debug
relative_diff = abs(value1 - value2) / max(value1,value2)
check = relative_diff <= error_tolerance
if not check:
debug.info(1,"NOT CLOSE {0} {1} relative diff={2}".format(value1,value2,relative_diff))
else:
debug.info(2,"CLOSE {0} {1} relative diff={2}".format(value1,value2,relative_diff))
return (check)
def isdiff(file1,file2):
""" This is used to compare two files and display the diff if they are different.. """
import debug
import filecmp
import difflib
check = filecmp.cmp(file1,file2)
if not check:
debug.info(2,"MISMATCH {0} {1}".format(file1,file2))
f1 = open(file1,"r")
s1 = f1.readlines()
f2 = open(file2,"r")
s2 = f2.readlines()
for line in difflib.unified_diff(s1, s2):
debug.error(line)
else:
debug.info(2,"MATCH {0} {1}".format(file1,file2))
return (check)
def header(filename, technology):
tst = "Running Test for:"
print "\n"
print " ______________________________________________________________________________ "
print "|==============================================================================|"
print "|=========" + tst.center(60) + "=========|"
print "|=========" + technology.center(60) + "=========|"
print "|=========" + filename.center(60) + "=========|"
import globals
OPTS = globals.get_opts()
print "|=========" + OPTS.openram_temp.center(60) + "=========|"
print "|==============================================================================|"

View File

@ -24,3 +24,7 @@ def auto_measure_libcell(pin_list, name, units, layer):
for pin in pin_list: for pin in pin_list:
cell[str(pin)] = gdsPinToOffset(cell_vlsi.readPin(str(pin))) cell[str(pin)] = gdsPinToOffset(cell_vlsi.readPin(str(pin)))
return cell return cell

View File

@ -83,6 +83,16 @@ class vector():
""" """
return vector(other[0]- self.x, other[1] - self.y) return vector(other[0]- self.x, other[1] - self.y)
def snap_to_grid(self, offset):
"""
Changes the coodrinate to match the grid settings
"""
grid = tech.drc["grid"]
# this gets the nearest integer value
off_in_grid = int(round(round((offset / grid), 2), 0))
offset = off_in_grid * grid
return offset
def rotate(self): def rotate(self):
""" pass a copy of rotated vector, without altering the vector! """ """ pass a copy of rotated vector, without altering the vector! """
return vector(self.y,self.x) return vector(self.y,self.x)
@ -94,12 +104,9 @@ class vector():
x_factor=x_factor[0] x_factor=x_factor[0]
return vector(self.x*x_factor,self.y*y_factor) return vector(self.x*x_factor,self.y*y_factor)
def snap_to_grid(self, offset): def rotate_scale(self, x_factor, y_factor=None):
""" """ pass a copy of scaled vector, without altering the vector! """
Changes the coodrinate to match the grid settings if y_factor==None:
""" y_factor=x_factor[1]
grid = tech.drc["grid"] x_factor=x_factor[0]
# this gets the nearest integer value return vector(self.y*x_factor,self.x*y_factor)
off_in_grid = int(round(round((offset / grid), 2), 0))
offset = off_in_grid * grid
return offset

View File

@ -20,7 +20,7 @@ class wire(path):
name = "wire_{0}".format(wire.unique_wire_id) name = "wire_{0}".format(wire.unique_wire_id)
wire.unique_wire_id += 1 wire.unique_wire_id += 1
design.design.__init__(self, name) design.design.__init__(self, name)
debug.info(2, "create wire obj {0}".format(name)) debug.info(3, "create wire obj {0}".format(name))
self.layer_stack = layer_stack self.layer_stack = layer_stack
self.position_list = position_list self.position_list = position_list
@ -37,7 +37,7 @@ class wire(path):
# wires and paths should not be offset to (0,0) # wires and paths should not be offset to (0,0)
def setup_layers(self): def setup_layers(self):
(vert_layer, via_layer, horiz_layer) = self.layer_stack (horiz_layer, via_layer, vert_layer) = self.layer_stack
if (via_layer != None): if (via_layer != None):
self.via_layer_name = via_layer self.via_layer_name = via_layer
else: else:

View File

@ -24,6 +24,7 @@ os.environ["MGC_TMPDIR"] = "/tmp"
DRCLVS_HOME= PDK_DIR+"/ncsu_basekit/techfile/calibre" DRCLVS_HOME= PDK_DIR+"/ncsu_basekit/techfile/calibre"
os.environ["DRCLVS_HOME"] = DRCLVS_HOME os.environ["DRCLVS_HOME"] = DRCLVS_HOME
os.environ["SPICE_MODEL_DIR"] = PDK_DIR+"/ncsu_basekit/models/hspice/tran_models/models_nom" os.environ["SPICE_MODEL_DIR"] = PDK_DIR+"/ncsu_basekit/models/hspice/tran_models/models_nom"
########################## ##########################

View File

@ -22,7 +22,11 @@ os.environ["MGC_TMPDIR"] = "/tmp"
OPENRAM_TECH=os.path.abspath(os.environ.get("OPENRAM_TECH")) OPENRAM_TECH=os.path.abspath(os.environ.get("OPENRAM_TECH"))
DRCLVS_HOME=OPENRAM_TECH+"/scn3me_subm/tech" DRCLVS_HOME=OPENRAM_TECH+"/scn3me_subm/tech"
os.environ["DRCLVS_HOME"] = DRCLVS_HOME os.environ["DRCLVS_HOME"] = DRCLVS_HOME
os.environ["SPICE_MODEL_DIR"] = "/mada/software/techfiles/scn3me_subm" # You can override the spice model diretory in the environment
try:
SPICE_MODEL_DIR = os.path.abspath(os.environ.get("SPICE_MODEL_DIR"))
except:
os.environ["SPICE_MODEL_DIR"] = "/mada/software/techfiles/scn3me_subm"
########################## ##########################
# Paths required for OPENRAM to function # Paths required for OPENRAM to function