Merge branch 'dev' into multiport_characterization

This commit is contained in:
Hunter Nichols 2018-08-22 14:50:29 -07:00
commit 21e85297d3
19 changed files with 8059 additions and 351 deletions

View File

@ -718,7 +718,7 @@ class layout(lef.lef):
conflicts between pins. conflicts between pins.
""" """
def remove_pin_from_graph(pin, g): def remove_net_from_graph(pin, g):
# Remove the pin from the keys # Remove the pin from the keys
g.pop(pin,None) g.pop(pin,None)
# Remove the pin from all conflicts # Remove the pin from all conflicts
@ -726,7 +726,8 @@ class layout(lef.lef):
for other_pin,conflicts in g.items(): for other_pin,conflicts in g.items():
if pin in conflicts: if pin in conflicts:
conflicts.remove(pin) conflicts.remove(pin)
vcg[other_pin]=conflicts g[other_pin]=conflicts
return g
if not pitch: if not pitch:
pitch = self.m2_pitch pitch = self.m2_pitch
@ -740,20 +741,24 @@ class layout(lef.lef):
# Initialize the vertical conflict graph (vcg) and make a list of all pins # Initialize the vertical conflict graph (vcg) and make a list of all pins
vcg = {} vcg = {}
for (top_name, bot_name) in route_map:
vcg[top_name] = []
vcg[bot_name] = []
# Find the vertical pin conflicts # Find the vertical pin conflicts
# FIXME: O(n^2) but who cares for now # FIXME: O(n^2) but who cares for now
for top_name,top_pin in top_pins.items(): for top_name,top_pin in top_pins.items():
vcg[top_name]=[]
for bot_name,bot_pin in bottom_pins.items(): for bot_name,bot_pin in bottom_pins.items():
if not vertical and abs(top_pin.center().x-bot_pin.center().x) < pitch: # Remember, vertical is the boolean of the routes in the channel
vcg[top_name].append(bot_name) # so check the intervals of the pins in the other dimension
vcg[bot_name].append(top_name) x_overlap = abs(top_pin.center().x-bot_pin.center().x)<pitch
elif vertical and abs(top_pin.center().y-bot_pin.center().y) < pitch: y_overlap = abs(top_pin.center().y-bot_pin.center().y)<pitch
vcg[top_name].append(bot_name)
vcg[bot_name].append(top_name) if (vertical and y_overlap) or (not vertical and x_overlap):
try:
vcg[bot_name].append(top_name)
except:
vcg[bot_name] = [top_name]
#FIXME: What if we have a cycle?
# This is the starting offset of the first trunk # This is the starting offset of the first trunk
if vertical: if vertical:
@ -770,7 +775,7 @@ class layout(lef.lef):
route_pin=None route_pin=None
for route_pin,conflicts in vcg.items(): for route_pin,conflicts in vcg.items():
if len(conflicts)==0: if len(conflicts)==0:
remove_pin_from_graph(route_pin,vcg) vcg=remove_net_from_graph(route_pin,vcg)
break break
# Get the connected pins from the routing map # Get the connected pins from the routing map
@ -781,7 +786,7 @@ class layout(lef.lef):
# Remove the other pins from the conflict graph too # Remove the other pins from the conflict graph too
for other_pin in pin_connections: for other_pin in pin_connections:
remove_pin_from_graph(other_pin, vcg) vcg=remove_net_from_graph(other_pin, vcg)
# Create a list of the pins rather than a list of the names # Create a list of the pins rather than a list of the names
pin_list = [all_pins[pin_name] for pin_name in pin_connections] pin_list = [all_pins[pin_name] for pin_name in pin_connections]

View File

@ -166,7 +166,6 @@ class delay():
self.sf.write("\n* Generation of control signals\n") self.sf.write("\n* Generation of control signals\n")
self.stim.gen_constant(sig_name="CSb", v_val=self.vdd_voltage) self.stim.gen_constant(sig_name="CSb", v_val=self.vdd_voltage)
self.stim.gen_constant(sig_name="WEb", v_val=self.vdd_voltage) self.stim.gen_constant(sig_name="WEb", v_val=self.vdd_voltage)
self.stim.gen_constant(sig_name="OEb", v_val=self.vdd_voltage)
self.sf.write("\n* Generation of global clock signal\n") self.sf.write("\n* Generation of global clock signal\n")
self.stim.gen_constant(sig_name="CLK", v_val=0) self.stim.gen_constant(sig_name="CLK", v_val=0)
@ -623,7 +622,6 @@ class delay():
self.cycle_times.append(self.t_current) self.cycle_times.append(self.t_current)
self.t_current += self.period self.t_current += self.period
self.web_values.append(1) self.web_values.append(1)
self.oeb_values.append(1)
self.csb_values.append(1) self.csb_values.append(1)
self.add_data(data) self.add_data(data)
@ -639,7 +637,6 @@ class delay():
self.t_current += self.period self.t_current += self.period
self.web_values.append(1) self.web_values.append(1)
self.oeb_values.append(0)
self.csb_values.append(0) self.csb_values.append(0)
self.add_data(data) self.add_data(data)
@ -656,7 +653,6 @@ class delay():
self.t_current += self.period self.t_current += self.period
self.web_values.append(0) self.web_values.append(0)
self.oeb_values.append(1)
self.csb_values.append(0) self.csb_values.append(0)
self.add_data(data) self.add_data(data)
@ -676,7 +672,6 @@ class delay():
# Control logic signals each cycle # Control logic signals each cycle
self.web_values = [] self.web_values = []
self.oeb_values = []
self.csb_values = [] self.csb_values = []
# Address and data values for each address/data bit # Address and data values for each address/data bit
@ -800,4 +795,3 @@ class delay():
""" Generates the control signals """ """ Generates the control signals """
self.stim.gen_pwl("csb", self.cycle_times, self.csb_values, self.period, self.slew, 0.05) self.stim.gen_pwl("csb", self.cycle_times, self.csb_values, self.period, self.slew, 0.05)
self.stim.gen_pwl("web", self.cycle_times, self.web_values, self.period, self.slew, 0.05) self.stim.gen_pwl("web", self.cycle_times, self.web_values, self.period, self.slew, 0.05)
self.stim.gen_pwl("oeb", self.cycle_times, self.oeb_values, self.period, self.slew, 0.05)

View File

@ -22,9 +22,9 @@ class bank(design.design):
def __init__(self, word_size, num_words, words_per_row, num_banks=1, name=""): def __init__(self, word_size, num_words, words_per_row, num_banks=1, name=""):
mod_list = ["tri_gate", "bitcell", "decoder", "ms_flop_array", "wordline_driver", mod_list = ["bitcell", "decoder", "ms_flop_array", "wordline_driver",
"bitcell_array", "sense_amp_array", "precharge_array", "bitcell_array", "sense_amp_array", "precharge_array",
"column_mux_array", "write_driver_array", "tri_gate_array", "column_mux_array", "write_driver_array",
"dff", "bank_select"] "dff", "bank_select"]
from importlib import reload from importlib import reload
for mod_name in mod_list: for mod_name in mod_list:
@ -84,8 +84,7 @@ class bank(design.design):
# the signals gated_*. # the signals gated_*.
if self.num_banks > 1: if self.num_banks > 1:
self.add_pin("bank_sel","INPUT") self.add_pin("bank_sel","INPUT")
for pin in ["s_en","w_en","tri_en_bar","tri_en", for pin in ["s_en","w_en","clk_buf_bar","clk_buf"]:
"clk_buf_bar","clk_buf"]:
self.add_pin(pin,"INPUT") self.add_pin(pin,"INPUT")
self.add_pin("vdd","POWER") self.add_pin("vdd","POWER")
self.add_pin("gnd","GROUND") self.add_pin("gnd","GROUND")
@ -96,15 +95,12 @@ class bank(design.design):
self.route_precharge_to_bitcell_array() self.route_precharge_to_bitcell_array()
self.route_col_mux_to_bitcell_array() self.route_col_mux_to_bitcell_array()
self.route_sense_amp_to_col_mux_or_bitcell_array() self.route_sense_amp_to_col_mux_or_bitcell_array()
#self.route_sense_amp_to_trigate()
#self.route_tri_gate_out()
self.route_sense_amp_out() self.route_sense_amp_out()
self.route_wordline_driver() self.route_wordline_driver()
self.route_write_driver() self.route_write_driver()
self.route_row_decoder() self.route_row_decoder()
self.route_column_address_lines() self.route_column_address_lines()
self.route_control_lines() self.route_control_lines()
self.add_control_pins()
if self.num_banks > 1: if self.num_banks > 1:
self.route_bank_select() self.route_bank_select()
@ -121,8 +117,6 @@ class bank(design.design):
self.add_column_mux_array() self.add_column_mux_array()
self.add_sense_amp_array() self.add_sense_amp_array()
self.add_write_driver_array() self.add_write_driver_array()
# Not needed for single bank
#self.add_tri_gate_array()
# To the left of the bitcell array # To the left of the bitcell array
self.add_row_decoder() self.add_row_decoder()
@ -150,9 +144,9 @@ class bank(design.design):
self.supply_rail_pitch = self.supply_rail_width + 4*self.m2_space self.supply_rail_pitch = self.supply_rail_width + 4*self.m2_space
# Number of control lines in the bus # Number of control lines in the bus
self.num_control_lines = 6 self.num_control_lines = 4
# The order of the control signals on the control bus: # The order of the control signals on the control bus:
self.input_control_signals = ["clk_buf", "tri_en_bar", "tri_en", "clk_buf_bar", "w_en", "s_en"] self.input_control_signals = ["clk_buf", "clk_buf_bar", "w_en", "s_en"]
# These will be outputs of the gaters if this is multibank, if not, normal signals. # These will be outputs of the gaters if this is multibank, if not, normal signals.
if self.num_banks > 1: if self.num_banks > 1:
self.control_signals = ["gated_"+str for str in self.input_control_signals] self.control_signals = ["gated_"+str for str in self.input_control_signals]
@ -176,7 +170,6 @@ class bank(design.design):
def create_modules(self): def create_modules(self):
""" Create all the modules using the class loader """ """ Create all the modules using the class loader """
self.tri = self.mod_tri_gate()
self.bitcell = self.mod_bitcell() self.bitcell = self.mod_bitcell()
self.bitcell_array = self.mod_bitcell_array(cols=self.num_cols, self.bitcell_array = self.mod_bitcell_array(cols=self.num_cols,
@ -203,10 +196,6 @@ class bank(design.design):
self.row_decoder = self.mod_decoder(rows=self.num_rows) self.row_decoder = self.mod_decoder(rows=self.num_rows)
self.add_mod(self.row_decoder) self.add_mod(self.row_decoder)
self.tri_gate_array = self.mod_tri_gate_array(columns=self.num_cols,
word_size=self.word_size)
self.add_mod(self.tri_gate_array)
self.wordline_driver = self.mod_wordline_driver(rows=self.num_rows) self.wordline_driver = self.mod_wordline_driver(rows=self.num_rows)
self.add_mod(self.wordline_driver) self.add_mod(self.wordline_driver)
@ -316,22 +305,6 @@ class bank(design.design):
temp.extend([self.prefix+"w_en", "vdd", "gnd"]) temp.extend([self.prefix+"w_en", "vdd", "gnd"])
self.connect_inst(temp) self.connect_inst(temp)
def add_tri_gate_array(self):
""" data tri gate to drive the data bus """
y_offset = self.sense_amp_array.height+self.column_mux_height \
+ self.m2_gap + self.tri_gate_array.height
self.tri_gate_array_inst=self.add_inst(name="tri_gate_array",
mod=self.tri_gate_array,
offset=vector(0,y_offset).scale(-1,-1))
temp = []
for i in range(self.word_size):
temp.append("sa_out[{0}]".format(i))
for i in range(self.word_size):
temp.append("dout[{0}]".format(i))
temp.extend([self.prefix+"tri_en", self.prefix+"tri_en_bar", "vdd", "gnd"])
self.connect_inst(temp)
def add_row_decoder(self): def add_row_decoder(self):
""" Add the hierarchical row decoder """ """ Add the hierarchical row decoder """
@ -447,7 +420,6 @@ class bank(design.design):
self.precharge_array_inst, self.precharge_array_inst,
self.sense_amp_array_inst, self.sense_amp_array_inst,
self.write_driver_array_inst, self.write_driver_array_inst,
# self.tri_gate_array_inst,
self.row_decoder_inst, self.row_decoder_inst,
self.wordline_driver_inst] self.wordline_driver_inst]
# Add these if we use the part... # Add these if we use the part...
@ -493,10 +465,7 @@ class bank(design.design):
control bus, power ring, etc. """ control bus, power ring, etc. """
#The minimum point is either the bottom of the address flops, #The minimum point is either the bottom of the address flops,
#the column decoder (if there is one) or the tristate output #the column decoder (if there is one).
#driver.
# Leave room for the output below the tri gate.
#tri_gate_min_y_offset = self.tri_gate_array_inst.by() - 3*self.m2_pitch
write_driver_min_y_offset = self.write_driver_array_inst.by() - 3*self.m2_pitch write_driver_min_y_offset = self.write_driver_array_inst.by() - 3*self.m2_pitch
row_decoder_min_y_offset = self.row_decoder_inst.by() row_decoder_min_y_offset = self.row_decoder_inst.by()
if self.col_addr_size > 0: if self.col_addr_size > 0:
@ -506,10 +475,10 @@ class bank(design.design):
if self.num_banks>1: if self.num_banks>1:
# The control gating logic is below the decoder # The control gating logic is below the decoder
# Min of the control gating logic and tri gate. # Min of the control gating logic and write driver.
self.min_y_offset = min(col_decoder_min_y_offset - self.bank_select.height, write_driver_min_y_offset) self.min_y_offset = min(col_decoder_min_y_offset - self.bank_select.height, write_driver_min_y_offset)
else: else:
# Just the min of the decoder logic logic and tri gate. # Just the min of the decoder logic logic and write driver.
self.min_y_offset = min(col_decoder_min_y_offset, write_driver_min_y_offset) self.min_y_offset = min(col_decoder_min_y_offset, write_driver_min_y_offset)
# The max point is always the top of the precharge bitlines # The max point is always the top of the precharge bitlines
@ -535,13 +504,15 @@ class bank(design.design):
# and control lines. # and control lines.
# The bank is at (0,0), so this is to the left of the y-axis. # The bank is at (0,0), so this is to the left of the y-axis.
# 2 pitches on the right for vias/jogs to access the inputs # 2 pitches on the right for vias/jogs to access the inputs
control_bus_offset = vector(-self.m2_pitch * self.num_control_lines - self.m2_width, 0) control_bus_offset = vector(-self.m2_pitch * self.num_control_lines - self.m2_width, self.min_y_offset)
control_bus_length = self.bitcell_array_inst.uy() control_bus_length = self.max_y_offset - self.min_y_offset
self.bus_xoffset = self.create_vertical_bus(layer="metal2", self.bus_xoffset = self.create_bus(layer="metal2",
pitch=self.m2_pitch, pitch=self.m2_pitch,
offset=control_bus_offset, offset=control_bus_offset,
names=self.control_signals, names=self.control_signals,
length=control_bus_length) length=control_bus_length,
vertical=True,
make_pins=(self.num_banks==1))
@ -603,20 +574,6 @@ class bank(design.design):
self.add_path("metal2",[sense_amp_br, vector(sense_amp_br.x,yoffset), self.add_path("metal2",[sense_amp_br, vector(sense_amp_br.x,yoffset),
vector(connect_br.x,yoffset), connect_br]) vector(connect_br.x,yoffset), connect_br])
def route_sense_amp_to_trigate(self):
""" Routing of sense amp output to tri_gate input """
for i in range(self.word_size):
# Connection of data_out of sense amp to data_in
tri_gate_in = self.tri_gate_array_inst.get_pin("in[{}]".format(i)).lc()
sa_data_out = self.sense_amp_array_inst.get_pin("data[{}]".format(i)).bc()
self.add_via_center(layers=("metal2", "via2", "metal3"),
offset=tri_gate_in)
self.add_via_center(layers=("metal2", "via2", "metal3"),
offset=sa_data_out)
self.add_path("metal3",[sa_data_out,tri_gate_in])
def route_sense_amp_out(self): def route_sense_amp_out(self):
""" Add pins for the sense amp output """ """ Add pins for the sense amp output """
for i in range(self.word_size): for i in range(self.word_size):
@ -627,17 +584,6 @@ class bank(design.design):
height=data_pin.height(), height=data_pin.height(),
width=data_pin.width()), width=data_pin.width()),
def route_tri_gate_out(self):
""" Metal 3 routing of tri_gate output data """
for i in range(self.word_size):
data_pin = self.tri_gate_array_inst.get_pin("out[{}]".format(i))
self.add_layout_pin_rect_center(text="dout[{}]".format(i),
layer=data_pin.layer,
offset=data_pin.center(),
height=data_pin.height(),
width=data_pin.width()),
def route_row_decoder(self): def route_row_decoder(self):
""" Routes the row decoder inputs and supplies """ """ Routes the row decoder inputs and supplies """
@ -782,8 +728,6 @@ class bank(design.design):
# Connection from the central bus to the main control block crosses # Connection from the central bus to the main control block crosses
# pre-decoder and this connection is in metal3 # pre-decoder and this connection is in metal3
connection = [] connection = []
#connection.append((self.prefix+"tri_en_bar", self.tri_gate_array_inst.get_pin("en_bar").lc()))
#connection.append((self.prefix+"tri_en", self.tri_gate_array_inst.get_pin("en").lc()))
connection.append((self.prefix+"clk_buf_bar", self.precharge_array_inst.get_pin("en").lc())) connection.append((self.prefix+"clk_buf_bar", self.precharge_array_inst.get_pin("en").lc()))
connection.append((self.prefix+"w_en", self.write_driver_array_inst.get_pin("en").lc())) connection.append((self.prefix+"w_en", self.write_driver_array_inst.get_pin("en").lc()))
connection.append((self.prefix+"s_en", self.sense_amp_array_inst.get_pin("en").lc())) connection.append((self.prefix+"s_en", self.sense_amp_array_inst.get_pin("en").lc()))
@ -807,52 +751,7 @@ class bank(design.design):
offset=control_via_pos, offset=control_via_pos,
rotate=90) rotate=90)
def add_control_pins(self):
""" Add the control signal input pins """
for ctrl in self.control_signals:
# xoffsets are the center of the rail
x_offset = self.bus_xoffset[ctrl].x - 0.5*self.m2_width
if self.num_banks > 1:
# it's not an input pin if we have multiple banks
self.add_label_pin(text=ctrl,
layer="metal2",
offset=vector(x_offset, self.min_y_offset),
width=self.m2_width,
height=self.max_y_offset-self.min_y_offset)
else:
self.add_layout_pin(text=ctrl,
layer="metal2",
offset=vector(x_offset, self.min_y_offset),
width=self.m2_width,
height=self.max_y_offset-self.min_y_offset)
def connect_rail_from_right(self,inst, pin, rail):
""" Helper routine to connect an unrotated/mirrored oriented instance to the rails """
in_pin = inst.get_pin(pin).lc()
rail_pos = vector(self.rail_1_x_offsets[rail], in_pin.y)
self.add_wire(("metal3","via2","metal2"),[in_pin, rail_pos, rail_pos - vector(0,self.m2_pitch)])
# Bring it up to M2 for M2/M3 routing
self.add_via(layers=("metal1","via1","metal2"),
offset=in_pin + contact.m1m2.offset,
rotate=90)
self.add_via(layers=("metal2","via2","metal3"),
offset=in_pin + self.m2m3_via_offset,
rotate=90)
def connect_rail_from_left(self,inst, pin, rail):
""" Helper routine to connect an unrotated/mirrored oriented instance to the rails """
in_pin = inst.get_pin(pin).rc()
rail_pos = vector(self.rail_1_x_offsets[rail], in_pin.y)
self.add_wire(("metal3","via2","metal2"),[in_pin, rail_pos, rail_pos - vector(0,self.m2_pitch)])
self.add_via(layers=("metal1","via1","metal2"),
offset=in_pin + contact.m1m2.offset,
rotate=90)
self.add_via(layers=("metal2","via2","metal3"),
offset=in_pin + self.m2m3_via_offset,
rotate=90)
def analytical_delay(self, slew, load): def analytical_delay(self, slew, load):
""" return analytical delay of the bank""" """ return analytical delay of the bank"""
@ -866,8 +765,6 @@ class bank(design.design):
self.bitcell_array.output_load()) self.bitcell_array.output_load())
# output load of bitcell_array is set to be only small part of bl for sense amp. # output load of bitcell_array is set to be only small part of bl for sense amp.
data_t_DATA_delay = self.tri_gate_array.analytical_delay(bl_t_data_out_delay.slew, load) result = decoder_delay + word_driver_delay + bitcell_array_delay + bl_t_data_out_delay
result = decoder_delay + word_driver_delay + bitcell_array_delay + bl_t_data_out_delay + data_t_DATA_delay
return result return result

View File

@ -19,9 +19,9 @@ class bank_select(design.design):
design.design.__init__(self, name) design.design.__init__(self, name)
# Number of control lines in the bus # Number of control lines in the bus
self.num_control_lines = 6 self.num_control_lines = 4
# The order of the control signals on the control bus: # The order of the control signals on the control bus:
self.input_control_signals = ["clk_buf", "tri_en_bar", "tri_en", "clk_buf_bar", "w_en", "s_en"] self.input_control_signals = ["clk_buf", "clk_buf_bar", "w_en", "s_en"]
# These will be outputs of the gaters if this is multibank # These will be outputs of the gaters if this is multibank
self.control_signals = ["gated_"+str for str in self.input_control_signals] self.control_signals = ["gated_"+str for str in self.input_control_signals]
@ -96,7 +96,7 @@ class bank_select(design.design):
# These require OR (nor2+inv) gates since they are active low. # These require OR (nor2+inv) gates since they are active low.
# (writes occur on clk low) # (writes occur on clk low)
if input_name in ("clk_buf", "tri_en_bar"): if input_name in ("clk_buf"):
self.logic_inst.append(self.add_inst(name=name_nor, self.logic_inst.append(self.add_inst(name=name_nor,
mod=self.nor2, mod=self.nor2,
@ -161,7 +161,7 @@ class bank_select(design.design):
self.add_label_pin(text="bank_sel_bar", self.add_label_pin(text="bank_sel_bar",
layer="metal2", layer="metal2",
offset=vector(xoffset_bank_sel_bar, 0), offset=vector(xoffset_bank_sel_bar, 0),
height=2*self.inv.height) height=self.inv.height)
self.add_via_center(layers=("metal1","via1","metal2"), self.add_via_center(layers=("metal1","via1","metal2"),
offset=bank_sel_bar_pin.rc()) offset=bank_sel_bar_pin.rc())
@ -173,7 +173,7 @@ class bank_select(design.design):
input_name = self.input_control_signals[i] input_name = self.input_control_signals[i]
gated_name = self.control_signals[i] gated_name = self.control_signals[i]
if input_name in ("clk_buf", "tri_en_bar"): if input_name in ("clk_buf"):
xoffset_bank_signal = xoffset_bank_sel_bar xoffset_bank_signal = xoffset_bank_sel_bar
else: else:
xoffset_bank_signal = xoffset_bank_sel xoffset_bank_signal = xoffset_bank_sel

View File

@ -52,7 +52,7 @@ class control_logic(design.design):
dff = dff_inv() dff = dff_inv()
dff_height = dff.height dff_height = dff.height
self.ctrl_dff_array = dff_inv_array(rows=3,columns=1) self.ctrl_dff_array = dff_inv_array(rows=2,columns=1)
self.add_mod(self.ctrl_dff_array) self.add_mod(self.ctrl_dff_array)
self.nand2 = pnand2(height=dff_height) self.nand2 = pnand2(height=dff_height)
@ -93,16 +93,14 @@ class control_logic(design.design):
#self.cell_gap = max(self.m2_pitch,drc["pwell_to_nwell"]) #self.cell_gap = max(self.m2_pitch,drc["pwell_to_nwell"])
# List of input control signals # List of input control signals
self.input_list =["csb","web","oeb"] self.input_list =["csb","web"]
self.dff_output_list =["cs_bar", "cs", "we_bar", "we", "oe_bar", "oe"] self.dff_output_list =["cs_bar", "cs", "we_bar", "we"]
# list of output control signals (for making a vertical bus) # list of output control signals (for making a vertical bus)
self.internal_bus_list = ["clk_buf", "clk_buf_bar", "we", "cs", "oe"] self.internal_bus_list = ["clk_buf", "clk_buf_bar", "we", "cs"]
# leave space for the bus plus one extra space # leave space for the bus plus one extra space
self.internal_bus_width = (len(self.internal_bus_list)+1)*self.m2_pitch self.internal_bus_width = (len(self.internal_bus_list)+1)*self.m2_pitch
# Ooutputs to the bank # Outputs to the bank
self.output_list = ["s_en", "w_en", "clk_buf_bar", "clk_buf"] self.output_list = ["s_en", "w_en", "clk_buf_bar", "clk_buf"]
# # with tri/tri_en
# self.output_list = ["s_en", "w_en", "tri_en", "tri_en_bar", "clk_buf_bar", "clk_buf"]
self.supply_list = ["vdd", "gnd"] self.supply_list = ["vdd", "gnd"]
@ -139,10 +137,11 @@ class control_logic(design.design):
# This offset is used for placement of the control logic in # This offset is used for placement of the control logic in
# the SRAM level. # the SRAM level.
self.control_logic_center = vector(self.ctrl_dff_inst.rx(), self.rbl_inst.by()) self.control_logic_center = vector(self.ctrl_dff_inst.rx(), self.rbl_inst.by())
self.height = self.rbl_inst.uy() # Extra pitch on top and right
self.height = self.rbl_inst.uy() + self.m3_pitch
# Max of modules or logic rows # Max of modules or logic rows
self.width = max(self.rbl_inst.rx(), max([inst.rx() for inst in self.row_end_inst])) self.width = max(self.rbl_inst.rx(), max([inst.rx() for inst in self.row_end_inst])) + self.m2_pitch
def add_routing(self): def add_routing(self):
@ -190,14 +189,14 @@ class control_logic(design.design):
(y_off,mirror)=self.get_offset(row) (y_off,mirror)=self.get_offset(row)
# input: OE, clk_buf_bar,CS output: rbl_in_bar # input: clk_buf_bar,CS output: rbl_in_bar
self.rbl_in_bar_offset = vector(x_off, y_off) self.rbl_in_bar_offset = vector(x_off, y_off)
self.rbl_in_bar_inst=self.add_inst(name="nand3_rbl_in_bar", self.rbl_in_bar_inst=self.add_inst(name="nand3_rbl_in_bar",
mod=self.nand3, mod=self.nand2,
offset=self.rbl_in_bar_offset, offset=self.rbl_in_bar_offset,
mirror=mirror) mirror=mirror)
self.connect_inst(["clk_buf_bar", "oe", "cs", "rbl_in_bar", "vdd", "gnd"]) self.connect_inst(["clk_buf_bar", "cs", "rbl_in_bar", "vdd", "gnd"])
x_off += self.nand3.width x_off += self.nand2.width
# input: rbl_in_bar, output: rbl_in # input: rbl_in_bar, output: rbl_in
self.rbl_in_offset = vector(x_off, y_off) self.rbl_in_offset = vector(x_off, y_off)
@ -237,76 +236,11 @@ class control_logic(design.design):
self.row_end_inst.append(self.s_en_inst) self.row_end_inst.append(self.s_en_inst)
def add_trien_row(self, row):
x_off = self.ctrl_dff_array.width + self.internal_bus_width
(y_off,mirror)=self.get_offset(row)
x_off += self.nand2.width
# BUFFER INVERTERS FOR TRI_EN
tri_en_offset = vector(x_off, y_off)
self.tri_en_inst=self.add_inst(name="inv_tri_en1",
mod=self.inv2,
offset=tri_en_offset,
mirror=mirror)
self.connect_inst(["pre_tri_en_bar", "pre_tri_en1", "vdd", "gnd"])
x_off += self.inv2.width
tri_en_buf1_offset = vector(x_off, y_off)
self.tri_en_buf1_inst=self.add_inst(name="tri_en_buf1",
mod=self.inv2,
offset=tri_en_buf1_offset,
mirror=mirror)
self.connect_inst(["pre_tri_en1", "pre_tri_en_bar1", "vdd", "gnd"])
x_off += self.inv2.width
tri_en_buf2_offset = vector(x_off, y_off)
self.tri_en_buf2_inst=self.add_inst(name="tri_en_buf2",
mod=self.inv8,
offset=tri_en_buf2_offset,
mirror=mirror)
self.connect_inst(["pre_tri_en_bar1", "tri_en", "vdd", "gnd"])
self.row_end_inst.append(self.tri_en_inst)
def add_trien_bar_row(self, row):
x_off = self.ctrl_dff_array.width + self.internal_bus_width
(y_off,mirror)=self.get_offset(row)
# input: OE, clk_buf_bar output: tri_en_bar
tri_en_bar_offset = vector(x_off,y_off)
self.tri_en_bar_inst=self.add_inst(name="nand2_tri_en",
mod=self.nand2,
offset=tri_en_bar_offset,
mirror=mirror)
self.connect_inst(["clk_buf_bar", "oe", "pre_tri_en_bar", "vdd", "gnd"])
x_off += self.nand2.width
# BUFFER INVERTERS FOR TRI_EN
tri_en_bar_buf1_offset = vector(x_off, y_off)
self.tri_en_bar_buf1_inst=self.add_inst(name="tri_en_bar_buf1",
mod=self.inv2,
offset=tri_en_bar_buf1_offset,
mirror=mirror)
self.connect_inst(["pre_tri_en_bar", "pre_tri_en2", "vdd", "gnd"])
x_off += self.inv2.width
tri_en_bar_buf2_offset = vector(x_off, y_off)
self.tri_en_bar_buf2_inst=self.add_inst(name="tri_en_bar_buf2",
mod=self.inv8,
offset=tri_en_bar_buf2_offset,
mirror=mirror)
self.connect_inst(["pre_tri_en2", "tri_en_bar", "vdd", "gnd"])
x_off += self.inv8.width
self.row_end_inst.append(self.tri_en_bar_buf2_inst)
def route_dffs(self): def route_dffs(self):
""" Route the input inverters """ """ Route the input inverters """
dff_out_map = zip(["dout_bar[{}]".format(i) for i in range(3)], ["cs", "we", "oe"]) dff_out_map = zip(["dout_bar[{}]".format(i) for i in range(3)], ["cs", "we"])
self.connect_vertical_bus(dff_out_map, self.ctrl_dff_inst, self.rail_offsets) self.connect_vertical_bus(dff_out_map, self.ctrl_dff_inst, self.rail_offsets)
# Connect the clock rail to the other clock rail # Connect the clock rail to the other clock rail
@ -320,7 +254,6 @@ class control_logic(design.design):
self.copy_layout_pin(self.ctrl_dff_inst, "din[0]", "csb") self.copy_layout_pin(self.ctrl_dff_inst, "din[0]", "csb")
self.copy_layout_pin(self.ctrl_dff_inst, "din[1]", "web") self.copy_layout_pin(self.ctrl_dff_inst, "din[1]", "web")
self.copy_layout_pin(self.ctrl_dff_inst, "din[2]", "oeb")
def add_dffs(self): def add_dffs(self):
@ -388,7 +321,7 @@ class control_logic(design.design):
def route_rbl_in(self): def route_rbl_in(self):
""" Connect the logic for the rbl_in generation """ """ Connect the logic for the rbl_in generation """
rbl_in_map = zip(["A", "B", "C"], ["clk_buf_bar", "oe", "cs"]) rbl_in_map = zip(["A", "B"], ["clk_buf_bar", "cs"])
self.connect_vertical_bus(rbl_in_map, self.rbl_in_bar_inst, self.rail_offsets) self.connect_vertical_bus(rbl_in_map, self.rbl_in_bar_inst, self.rail_offsets)
# Connect the NAND3 output to the inverter # Connect the NAND3 output to the inverter
@ -475,44 +408,6 @@ class control_logic(design.design):
self.connect_output(self.w_en_inst, "Z", "w_en") self.connect_output(self.w_en_inst, "Z", "w_en")
def route_trien(self):
# Connect the NAND2 output to the buffer
tri_en_bar_pos = self.tri_en_bar_inst.get_pin("Z").center()
inv_in_pos = self.tri_en_inst.get_pin("A").center()
mid1 = vector(tri_en_bar_pos.x,inv_in_pos.y)
self.add_wire(("metal1","via1","metal2"),[tri_en_bar_pos,mid1,inv_in_pos])
# Connect the INV output to the buffer
tri_en_pos = self.tri_en_inst.get_pin("Z").center()
inv_in_pos = self.tri_en_buf1_inst.get_pin("A").center()
mid_xoffset = 0.5*(tri_en_pos.x + inv_in_pos.x)
mid1 = vector(mid_xoffset,tri_en_pos.y)
mid2 = vector(mid_xoffset,inv_in_pos.y)
self.add_path("metal1",[tri_en_pos,mid1,mid2,inv_in_pos])
self.add_path("metal1",[self.tri_en_buf1_ist.get_pin("Z").center(), self.tri_en_buf2_inst.get_pin("A").center()])
self.connect_output(self.tri_en_buf2_inst, "Z", "tri_en")
def route_trien_bar(self):
trien_map = zip(["A", "B"], ["clk_buf_bar", "oe"])
self.connect_vertical_bus(trien_map, self.tri_en_bar_inst, self.rail_offsets)
# Connect the NAND2 output to the buffer
tri_en_bar_pos = self.tri_en_bar_inst.get_pin("Z").center()
inv_in_pos = self.tri_en_bar_buf1_inst.get_pin("A").center()
mid_xoffset = 0.5*(tri_en_bar_pos.x + inv_in_pos.x)
mid1 = vector(mid_xoffset,tri_en_bar_pos.y)
mid2 = vector(mid_xoffset,inv_in_pos.y)
self.add_path("metal1",[tri_en_bar_pos,mid1,mid2,inv_in_pos])
self.add_path("metal1",[self.tri_en_bar_buf1_inst.get_pin("Z").center(), self.tri_en_bar_buf2_inst.get_pin("A").center()])
self.connect_output(self.tri_en_bar_buf2_inst, "Z", "tri_en_bar")
def route_sen(self): def route_sen(self):
rbl_out_pos = self.rbl_inst.get_pin("out").bc() rbl_out_pos = self.rbl_inst.get_pin("out").bc()
in_pos = self.pre_s_en_bar_inst.get_pin("A").lc() in_pos = self.pre_s_en_bar_inst.get_pin("A").lc()

View File

@ -125,28 +125,21 @@ class dff_array(design.design):
# Create vertical spines to a single horizontal rail # Create vertical spines to a single horizontal rail
clk_pin = self.dff_insts[0,0].get_pin("clk") clk_pin = self.dff_insts[0,0].get_pin("clk")
debug.check(clk_pin.layer=="metal2","DFF clk pin not on metal2") debug.check(clk_pin.layer=="metal2","DFF clk pin not on metal2")
if self.columns==1: self.add_layout_pin_segment_center(text="clk",
self.add_layout_pin(text="clk", layer="metal3",
layer="metal2", start=vector(0,self.m3_pitch+self.m3_width),
offset=clk_pin.ll().scale(1,0), end=vector(self.width,self.m3_pitch+self.m3_width))
width=self.m2_width, for col in range(self.columns):
height=self.height) clk_pin = self.dff_insts[0,col].get_pin("clk")
else: # Make a vertical strip for each column
self.add_layout_pin_segment_center(text="clk", self.add_rect(layer="metal2",
layer="metal3", offset=clk_pin.ll().scale(1,0),
start=vector(0,self.m3_pitch+self.m3_width), width=self.m2_width,
end=vector(self.width,self.m3_pitch+self.m3_width)) height=self.height)
for col in range(self.columns): # Drop a via to the M3 pin
clk_pin = self.dff_insts[0,col].get_pin("clk") self.add_via_center(layers=("metal2","via2","metal3"),
# Make a vertical strip for each column offset=vector(clk_pin.cx(),self.m3_pitch+self.m3_width))
self.add_rect(layer="metal2",
offset=clk_pin.ll().scale(1,0),
width=self.m2_width,
height=self.height)
# Drop a via to the M3 pin
self.add_via_center(layers=("metal2","via2","metal3"),
offset=vector(clk_pin.cx(),self.m3_pitch+self.m3_width))
def analytical_delay(self, slew, load=0.0): def analytical_delay(self, slew, load=0.0):

View File

@ -42,9 +42,9 @@ class replica_bitline(design.design):
#self.add_lvs_correspondence_points() #self.add_lvs_correspondence_points()
# Plus a pitch for the WL contacts on the RBL # Extra pitch on top and right
self.width = self.rbl_inst.rx() - self.dc_inst.lx() + self.m1_pitch self.width = self.rbl_inst.rx() - self.dc_inst.lx() + self.m2_pitch
self.height = max(self.rbl_inst.uy(), self.dc_inst.uy()) self.height = max(self.rbl_inst.uy(), self.dc_inst.uy()) + self.m3_pitch
self.DRC_LVS() self.DRC_LVS()

View File

@ -29,26 +29,31 @@ class sram_1bank(sram_base):
# No orientation or offset # No orientation or offset
self.bank_inst = self.add_bank(0, [0, 0], 1, 1) self.bank_inst = self.add_bank(0, [0, 0], 1, 1)
control_pos = vector(-self.control_logic.width - self.m3_pitch, # The control logic is placed such that the vertical center (between the delay/RBL and
# the actual control logic is aligned with the vertical center of the bank (between
# the sense amps/column mux and cell array)
# The x-coordinate is placed to allow a single clock wire (plus an extra pitch)
# up to the row address DFFs.
control_pos = vector(-self.control_logic.width - 2*self.m2_pitch,
self.bank.bank_center.y - self.control_logic.control_logic_center.y) self.bank.bank_center.y - self.control_logic.control_logic_center.y)
self.add_control_logic(position=control_pos) self.add_control_logic(position=control_pos)
# Leave room for the control routes to the left of the flops # The row address bits are placed above the control logic aligned on the right.
row_addr_pos = vector(self.control_logic_inst.rx() - self.row_addr_dff.width, row_addr_pos = vector(self.control_logic_inst.rx() - self.row_addr_dff.width,
control_pos.y + self.control_logic.height + self.m1_pitch) self.control_logic_inst.uy())
self.add_row_addr_dff(row_addr_pos) self.add_row_addr_dff(row_addr_pos)
# This is M2 pitch even though it is on M1 to help stem via spacings on the trunk # This is M2 pitch even though it is on M1 to help stem via spacings on the trunk
data_gap = -self.m2_pitch*(self.word_size+1) data_gap = -self.m2_pitch*(self.word_size+1)
# Add the column address below the bank under the control # Add the column address below the bank under the control
# Keep it aligned with the data flops # The column address flops are aligned with the data flops
if self.col_addr_dff: if self.col_addr_dff:
col_addr_pos = vector(self.bank.bank_center.x - self.col_addr_dff.width - self.bank.central_bus_width, col_addr_pos = vector(self.bank.bank_center.x - self.col_addr_dff.width - self.bank.central_bus_width,
data_gap - self.col_addr_dff.height) data_gap - self.col_addr_dff.height)
self.add_col_addr_dff(col_addr_pos) self.add_col_addr_dff(col_addr_pos)
# Add the data flops below the bank # Add the data flops below the bank to the right of the center of bank:
# This relies on the center point of the bank: # This relies on the center point of the bank:
# decoder in upper left, bank in upper right, sensing in lower right. # decoder in upper left, bank in upper right, sensing in lower right.
# These flops go below the sensing and leave a gap to channel route to the # These flops go below the sensing and leave a gap to channel route to the
@ -104,13 +109,44 @@ class sram_1bank(sram_base):
def route_clk(self): def route_clk(self):
""" Route the clock network """ """ Route the clock network """
debug.warning("Clock is top-level must connect.")
# For now, just have four clock pins for the address (x2), data, and control # This is the actual input to the SRAM
if self.col_addr_dff:
self.copy_layout_pin(self.col_addr_dff_inst, "clk")
self.copy_layout_pin(self.row_addr_dff_inst, "clk")
self.copy_layout_pin(self.data_dff_inst, "clk")
self.copy_layout_pin(self.control_logic_inst, "clk") self.copy_layout_pin(self.control_logic_inst, "clk")
# Connect all of these clock pins to the clock in the central bus
# This is something like a "spine" clock distribution. The two spines
# are clk_buf and clk_buf_bar
bank_clk_buf_pin = self.bank_inst.get_pin("clk_buf")
bank_clk_buf_pos = bank_clk_buf_pin.center()
bank_clk_buf_bar_pin = self.bank_inst.get_pin("clk_buf_bar")
bank_clk_buf_bar_pos = bank_clk_buf_bar_pin.center()
if self.col_addr_dff:
dff_clk_pin = self.col_addr_dff_inst.get_pin("clk")
dff_clk_pos = dff_clk_pin.center()
mid_pos = vector(bank_clk_buf_pos.x, dff_clk_pos.y)
self.add_wire(("metal3","via2","metal2"),[dff_clk_pos, mid_pos, bank_clk_buf_pos])
data_dff_clk_pin = self.data_dff_inst.get_pin("clk")
data_dff_clk_pos = data_dff_clk_pin.center()
mid_pos = vector(bank_clk_buf_pos.x, data_dff_clk_pos.y)
self.add_wire(("metal3","via2","metal2"),[data_dff_clk_pos, mid_pos, bank_clk_buf_pos])
# This uses a metal2 track to the right of the control/row addr DFF
# to route vertically.
control_clk_buf_pin = self.control_logic_inst.get_pin("clk_buf")
control_clk_buf_pos = control_clk_buf_pin.rc()
row_addr_clk_pin = self.row_addr_dff_inst.get_pin("clk")
row_addr_clk_pos = row_addr_clk_pin.rc()
mid1_pos = vector(self.row_addr_dff_inst.rx() + self.m2_pitch,
row_addr_clk_pos.y)
mid2_pos = vector(mid1_pos.x,
control_clk_buf_pos.y)
# Note, the via to the control logic is taken care of when we route
# the control logic to the bank
self.add_wire(("metal3","via2","metal2"),[row_addr_clk_pos, mid1_pos, mid2_pos, control_clk_buf_pos])
def route_vdd_gnd(self): def route_vdd_gnd(self):
""" Propagate all vdd/gnd pins up to this level for all modules """ """ Propagate all vdd/gnd pins up to this level for all modules """

View File

@ -150,7 +150,7 @@ class sram_base(design):
""" Add the horizontal and vertical busses """ """ Add the horizontal and vertical busses """
# Vertical bus # Vertical bus
# The order of the control signals on the control bus: # The order of the control signals on the control bus:
self.control_bus_names = ["clk_buf", "tri_en_bar", "tri_en", "clk_buf_bar", "w_en", "s_en"] self.control_bus_names = ["clk_buf", "clk_buf_bar", "w_en", "s_en"]
self.vert_control_bus_positions = self.create_vertical_bus(layer="metal2", self.vert_control_bus_positions = self.create_vertical_bus(layer="metal2",
pitch=self.m2_pitch, pitch=self.m2_pitch,
offset=self.vertical_bus_offset, offset=self.vertical_bus_offset,
@ -328,8 +328,7 @@ class sram_base(design):
temp.append("A[{0}]".format(i)) temp.append("A[{0}]".format(i))
if(self.num_banks > 1): if(self.num_banks > 1):
temp.append("bank_sel[{0}]".format(bank_num)) temp.append("bank_sel[{0}]".format(bank_num))
temp.extend(["s_en", "w_en", "tri_en_bar", "tri_en", temp.extend(["s_en", "w_en", "clk_buf_bar","clk_buf" , "vdd", "gnd"])
"clk_buf_bar","clk_buf" , "vdd", "gnd"])
self.connect_inst(temp) self.connect_inst(temp)
return bank_inst return bank_inst
@ -347,8 +346,7 @@ class sram_base(design):
inputs.append("ADDR[{}]".format(i+self.col_addr_size)) inputs.append("ADDR[{}]".format(i+self.col_addr_size))
outputs.append("A[{}]".format(i+self.col_addr_size)) outputs.append("A[{}]".format(i+self.col_addr_size))
# FIXME clk->clk_buf self.connect_inst(inputs + outputs + ["clk_buf", "vdd", "gnd"])
self.connect_inst(inputs + outputs + ["clk", "vdd", "gnd"])
def add_col_addr_dff(self, position): def add_col_addr_dff(self, position):
@ -363,8 +361,7 @@ class sram_base(design):
inputs.append("ADDR[{}]".format(i)) inputs.append("ADDR[{}]".format(i))
outputs.append("A[{}]".format(i)) outputs.append("A[{}]".format(i))
# FIXME clk->clk_buf self.connect_inst(inputs + outputs + ["clk_buf", "vdd", "gnd"])
self.connect_inst(inputs + outputs + ["clk", "vdd", "gnd"])
def add_data_dff(self, position): def add_data_dff(self, position):
""" Add and place all data flops """ """ Add and place all data flops """
@ -378,8 +375,7 @@ class sram_base(design):
inputs.append("DIN[{}]".format(i)) inputs.append("DIN[{}]".format(i))
outputs.append("BANK_DIN[{}]".format(i)) outputs.append("BANK_DIN[{}]".format(i))
# FIXME clk->clk_buf_bar self.connect_inst(inputs + outputs + ["clk_buf", "vdd", "gnd"])
self.connect_inst(inputs + outputs + ["clk", "vdd", "gnd"])
def add_control_logic(self, position): def add_control_logic(self, position):
""" Add and place control logic """ """ Add and place control logic """

0
compiler/tests/04_precharge_test.py Normal file → Executable file
View File

0
compiler/tests/05_pbitcell_array_test.py Normal file → Executable file
View File

View File

@ -35,7 +35,7 @@ class sram_1bank_test(openram_test):
debug.info(1, "Single bank, eight way column mux with control logic") debug.info(1, "Single bank, eight way column mux with control logic")
a = sram(word_size=2, num_words=128, num_banks=1, name="sram4") a = sram(word_size=2, num_words=128, num_banks=1, name="sram4")
self.local_check(a, final_verification=True) self.local_check(a, final_verification=True)
globals.end_openram() globals.end_openram()
# instantiate a copy of the class to actually run the test # instantiate a copy of the class to actually run the test

View File

@ -51,27 +51,27 @@ class timing_sram_test(openram_test):
data = d.analyze(probe_address, probe_data, slews, loads) data = d.analyze(probe_address, probe_data, slews, loads)
if OPTS.tech_name == "freepdk45": if OPTS.tech_name == "freepdk45":
golden_data = {'delay_hl': [2.5614], golden_data = {'delay_hl': [2.5829000000000004],
'delay_lh': [0.22929839999999999], 'delay_lh': [0.2255964],
'leakage_power': 0.0020326, 'leakage_power': 0.0019498999999999996,
'min_period': 4.844, 'min_period': 4.844,
'read0_power': [0.0497676], 'read0_power': [0.055371399999999994],
'read1_power': [0.0463576], 'read1_power': [0.0520225],
'slew_hl': [0.1119293], 'slew_hl': [0.0794261],
'slew_lh': [0.0237043], 'slew_lh': [0.0236264],
'write0_power': [0.0494321], 'write0_power': [0.06545659999999999],
'write1_power': [0.0457268]} 'write1_power': [0.057846299999999996]}
elif OPTS.tech_name == "scn3me_subm": elif OPTS.tech_name == "scn3me_subm":
golden_data = {'delay_hl': [6.0052], golden_data = {'delay_hl': [4.0249],
'delay_lh': [2.2886], 'delay_lh': [2.2611],
'leakage_power': 0.025629199999999998, 'leakage_power': 0.0257389,
'min_period': 9.375, 'min_period': 4.688,
'read0_power': [8.8721], 'read0_power': [24.9279],
'read1_power': [8.3179], 'read1_power': [24.0219],
'slew_hl': [1.0746], 'slew_hl': [0.8500753999999999],
'slew_lh': [0.413426], 'slew_lh': [0.4122653],
'write0_power': [8.6601], 'write0_power': [28.197600000000005],
'write1_power': [8.0397]} 'write1_power': [25.685]}
else: else:
self.assertTrue(False) # other techs fail self.assertTrue(False) # other techs fail
# Check if no too many or too few results # Check if no too many or too few results

View File

@ -50,27 +50,27 @@ class timing_sram_test(openram_test):
data = d.analyze(probe_address, probe_data, slews, loads) data = d.analyze(probe_address, probe_data, slews, loads)
if OPTS.tech_name == "freepdk45": if OPTS.tech_name == "freepdk45":
golden_data = {'delay_hl': [2.562671], golden_data = {'delay_hl': [2.584251],
'delay_lh': [0.2320771], 'delay_lh': [0.22870469999999998],
'leakage_power': 0.00102373, 'leakage_power': 0.0009567935,
'min_period': 4.844, 'min_period': 4.844,
'read0_power': [0.047404110000000006], 'read0_power': [0.0547588],
'read1_power': [0.0438884], 'read1_power': [0.051159970000000006],
'slew_hl': [0.1140206], 'slew_hl': [0.08164099999999999],
'slew_lh': [0.02492785], 'slew_lh': [0.025474979999999998],
'write0_power': [0.04765188], 'write0_power': [0.06513271999999999],
'write1_power': [0.04434999]} 'write1_power': [0.058057000000000004]}
elif OPTS.tech_name == "scn3me_subm": elif OPTS.tech_name == "scn3me_subm":
golden_data = {'delay_hl': [11.69536], golden_data = {'delay_hl': [4.221382999999999],
'delay_lh': [1.260921], 'delay_lh': [2.6459520000000003],
'leakage_power': 0.00039469710000000004, 'leakage_power': 0.0013865260000000001,
'min_period': 20.0, 'min_period': 4.688,
'read0_power': [4.40238], 'read0_power': [26.699669999999998],
'read1_power': [4.126633], 'read1_power': [26.13123],
'slew_hl': [1.259555], 'slew_hl': [0.9821776000000001],
'slew_lh': [0.9150649], 'slew_lh': [1.5791520000000001],
'write0_power': [4.988347], 'write0_power': [30.71939],
'write1_power': [4.473887]} 'write1_power': [27.44753]}
else: else:
self.assertTrue(False) # other techs fail self.assertTrue(False) # other techs fail

View File

@ -78,6 +78,7 @@ def write_magic_script(cell_name, gds_name, extract=False):
f = open(run_file, "w") f = open(run_file, "w")
f.write("#!/bin/sh\n") f.write("#!/bin/sh\n")
f.write("{} -dnull -noconsole << EOF\n".format(OPTS.drc_exe[1])) f.write("{} -dnull -noconsole << EOF\n".format(OPTS.drc_exe[1]))
f.write("path sys +{}/tech\n".format(OPTS.openram_tech))
f.write("tech load SCN3ME_SUBM.30\n") f.write("tech load SCN3ME_SUBM.30\n")
#gf.write("scalegrid 1 8\n") #gf.write("scalegrid 1 8\n")
#f.write("gds rescale no\n") #f.write("gds rescale no\n")

View File

@ -261,7 +261,7 @@ spice["nom_temperature"] = 25 # Nominal temperature (celcius)
#FIXME: We don't use these everywhere... #FIXME: We don't use these everywhere...
spice["vdd_name"] = "vdd" spice["vdd_name"] = "vdd"
spice["gnd_name"] = "gnd" spice["gnd_name"] = "gnd"
spice["control_signals"] = ["CSb", "WEb", "OEb"] spice["control_signals"] = ["CSB", "WEB"]
spice["data_name"] = "DATA" spice["data_name"] = "DATA"
spice["addr_name"] = "ADDR" spice["addr_name"] = "ADDR"
spice["minwidth_tx"] = drc["minwidth_tx"] spice["minwidth_tx"] = drc["minwidth_tx"]

View File

@ -0,0 +1,10 @@
The file SCN3ME_SUBM.30.tech is from qflow 1.2 and has the following
license information:
---------------------------------------------------------------
Tim Edwards
Open Circuit Design
v1.0 April 2013
v1.1 May 2015
v1.2 April 2017
---------------------------------------------------------------
GPL Copyright (c) 2017

File diff suppressed because it is too large Load Diff

View File

@ -224,7 +224,7 @@ spice["nom_temperature"] = 25 # Nominal temperature (celcius)
#FIXME: We don't use these everywhere... #FIXME: We don't use these everywhere...
spice["vdd_name"] = "vdd" spice["vdd_name"] = "vdd"
spice["gnd_name"] = "gnd" spice["gnd_name"] = "gnd"
spice["control_signals"] = ["CSb", "WEb", "OEb"] spice["control_signals"] = ["CSB", "WEB"]
spice["data_name"] = "DATA" spice["data_name"] = "DATA"
spice["addr_name"] = "ADDR" spice["addr_name"] = "ADDR"
spice["minwidth_tx"] = drc["minwidth_tx"] spice["minwidth_tx"] = drc["minwidth_tx"]