mirror of https://github.com/VLSIDA/OpenRAM.git
Merge branch 'dev' into cacti_model
This commit is contained in:
commit
1e08005639
|
|
@ -93,9 +93,9 @@ class cell:
|
||||||
# It is assumed it is [nwell, pwell]
|
# It is assumed it is [nwell, pwell]
|
||||||
self._body_bias = body_bias
|
self._body_bias = body_bias
|
||||||
self._port_map['vnb'] = body_bias[0]
|
self._port_map['vnb'] = body_bias[0]
|
||||||
self._port_types['vnb'] = "POWER"
|
self._port_types['vnb'] = "GROUND"
|
||||||
self._port_map['vpb'] = body_bias[1]
|
self._port_map['vpb'] = body_bias[1]
|
||||||
self._port_types['vpb'] = "GROUND"
|
self._port_types['vpb'] = "POWER"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def port_types(self):
|
def port_types(self):
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ class pin_layout:
|
||||||
from tech import layer_override_name
|
from tech import layer_override_name
|
||||||
if layer_override[name]:
|
if layer_override[name]:
|
||||||
self.lpp = layer_override[name]
|
self.lpp = layer_override[name]
|
||||||
self.layer = "m1"
|
self.layer = "pwellp"
|
||||||
self._recompute_hash()
|
self._recompute_hash()
|
||||||
return
|
return
|
||||||
except:
|
except:
|
||||||
|
|
@ -406,6 +406,13 @@ class pin_layout:
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from tech import label_purpose
|
from tech import label_purpose
|
||||||
|
try:
|
||||||
|
from tech import layer_override_purpose
|
||||||
|
if pin_layer_num in layer_override_purpose:
|
||||||
|
layer_num = layer_override_purpose[pin_layer_num][0]
|
||||||
|
label_purpose = layer_override_purpose[pin_layer_num][1]
|
||||||
|
except:
|
||||||
|
pass
|
||||||
except ImportError:
|
except ImportError:
|
||||||
label_purpose = purpose
|
label_purpose = purpose
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,11 @@ class functional(simulation):
|
||||||
self.create_graph()
|
self.create_graph()
|
||||||
self.set_internal_spice_names()
|
self.set_internal_spice_names()
|
||||||
self.q_name, self.qbar_name = self.get_bit_name()
|
self.q_name, self.qbar_name = self.get_bit_name()
|
||||||
debug.info(2, "q name={0}\nqbar name={1}".format(self.q_name, self.qbar_name))
|
debug.info(2, "q:\t\t{0}".format(self.q_name))
|
||||||
|
debug.info(2, "qbar:\t{0}".format(self.qbar_name))
|
||||||
|
debug.info(2, "s_en:\t{0}".format(self.sen_name))
|
||||||
|
debug.info(2, "bl:\t{0}".format(self.bl_name))
|
||||||
|
debug.info(2, "br:\t{0}".format(self.br_name))
|
||||||
|
|
||||||
# Number of checks can be changed
|
# Number of checks can be changed
|
||||||
self.num_cycles = cycles
|
self.num_cycles = cycles
|
||||||
|
|
@ -141,23 +145,25 @@ class functional(simulation):
|
||||||
comment = self.gen_cycle_comment("noop", "0" * self.word_size, "0" * self.addr_size, "0" * self.num_wmasks, 0, self.t_current)
|
comment = self.gen_cycle_comment("noop", "0" * self.word_size, "0" * self.addr_size, "0" * self.num_wmasks, 0, self.t_current)
|
||||||
self.add_noop_all_ports(comment)
|
self.add_noop_all_ports(comment)
|
||||||
|
|
||||||
# 1. Write all the write ports first to seed a bunch of locations.
|
|
||||||
for port in self.write_ports:
|
|
||||||
addr = self.gen_addr()
|
|
||||||
(word, spare) = self.gen_data()
|
|
||||||
combined_word = self.combine_word(spare, word)
|
|
||||||
comment = self.gen_cycle_comment("write", combined_word, addr, "1" * self.num_wmasks, port, self.t_current)
|
|
||||||
self.add_write_one_port(comment, addr, spare + word, "1" * self.num_wmasks, port)
|
|
||||||
self.stored_words[addr] = word
|
|
||||||
self.stored_spares[addr[:self.addr_spare_index]] = spare
|
|
||||||
|
|
||||||
# All other read-only ports are noops.
|
# 1. Write all the write ports 2x to seed a bunch of locations.
|
||||||
for port in self.read_ports:
|
for i in range(3):
|
||||||
if port not in self.write_ports:
|
for port in self.write_ports:
|
||||||
self.add_noop_one_port(port)
|
addr = self.gen_addr()
|
||||||
self.cycle_times.append(self.t_current)
|
(word, spare) = self.gen_data()
|
||||||
self.t_current += self.period
|
combined_word = self.combine_word(spare, word)
|
||||||
self.check_lengths()
|
comment = self.gen_cycle_comment("write", combined_word, addr, "1" * self.num_wmasks, port, self.t_current)
|
||||||
|
self.add_write_one_port(comment, addr, spare + word, "1" * self.num_wmasks, port)
|
||||||
|
self.stored_words[addr] = word
|
||||||
|
self.stored_spares[addr[:self.addr_spare_index]] = spare
|
||||||
|
|
||||||
|
# All other read-only ports are noops.
|
||||||
|
for port in self.read_ports:
|
||||||
|
if port not in self.write_ports:
|
||||||
|
self.add_noop_one_port(port)
|
||||||
|
self.cycle_times.append(self.t_current)
|
||||||
|
self.t_current += self.period
|
||||||
|
self.check_lengths()
|
||||||
|
|
||||||
# 2. Read at least once. For multiport, it is important that one
|
# 2. Read at least once. For multiport, it is important that one
|
||||||
# read cycle uses all RW and R port to read from the same
|
# read cycle uses all RW and R port to read from the same
|
||||||
|
|
@ -297,38 +303,6 @@ class functional(simulation):
|
||||||
self.read_results.append([sp_read_value, dout_port, eo_period, cycle])
|
self.read_results.append([sp_read_value, dout_port, eo_period, cycle])
|
||||||
return (1, "SUCCESS")
|
return (1, "SUCCESS")
|
||||||
|
|
||||||
def combine_word(self, spare, word):
|
|
||||||
if len(spare) > 0:
|
|
||||||
return spare + "+" + word
|
|
||||||
|
|
||||||
return word
|
|
||||||
|
|
||||||
def format_value(self, value):
|
|
||||||
""" Format in better readable manner """
|
|
||||||
|
|
||||||
def delineate(word):
|
|
||||||
# Create list of chars in reverse order
|
|
||||||
split_word = list(reversed([x for x in word]))
|
|
||||||
# Add underscore every 4th char
|
|
||||||
split_word2 = [x + '_' * (n != 0 and n % 4 == 0) for n, x in enumerate(split_word)]
|
|
||||||
# Join the word unreversed back together
|
|
||||||
new_word = ''.join(reversed(split_word2))
|
|
||||||
return(new_word)
|
|
||||||
|
|
||||||
# Split extra cols
|
|
||||||
if self.num_spare_cols > 0:
|
|
||||||
vals = value[self.num_spare_cols:]
|
|
||||||
spare_vals = value[:self.num_spare_cols]
|
|
||||||
else:
|
|
||||||
vals = value
|
|
||||||
spare_vals = ""
|
|
||||||
|
|
||||||
# Insert underscores
|
|
||||||
vals = delineate(vals)
|
|
||||||
spare_vals = delineate(spare_vals)
|
|
||||||
|
|
||||||
return self.combine_word(spare_vals, vals)
|
|
||||||
|
|
||||||
def check_stim_results(self):
|
def check_stim_results(self):
|
||||||
for i in range(len(self.read_check)):
|
for i in range(len(self.read_check)):
|
||||||
if self.read_check[i][0] != self.read_results[i][0]:
|
if self.read_check[i][0] != self.read_results[i][0]:
|
||||||
|
|
@ -372,7 +346,8 @@ class functional(simulation):
|
||||||
|
|
||||||
def gen_data(self):
|
def gen_data(self):
|
||||||
""" Generates a random word to write. """
|
""" Generates a random word to write. """
|
||||||
random_value = random.randint(0, self.max_data)
|
# Don't use 0 or max value
|
||||||
|
random_value = random.randint(1, self.max_data - 1)
|
||||||
data_bits = binary_repr(random_value, self.word_size)
|
data_bits = binary_repr(random_value, self.word_size)
|
||||||
if self.num_spare_cols>0:
|
if self.num_spare_cols>0:
|
||||||
random_value = random.randint(0, self.max_col_data)
|
random_value = random.randint(0, self.max_col_data)
|
||||||
|
|
@ -431,11 +406,11 @@ class functional(simulation):
|
||||||
|
|
||||||
# Write important signals to stim file
|
# Write important signals to stim file
|
||||||
self.sf.write("\n\n* Important signals for debug\n")
|
self.sf.write("\n\n* Important signals for debug\n")
|
||||||
self.sf.write("* bl: {0}\n".format(self.bl_name.format(port)))
|
self.sf.write("* bl:\t{0}\n".format(self.bl_name.format(port)))
|
||||||
self.sf.write("* br: {0}\n".format(self.br_name.format(port)))
|
self.sf.write("* br:\t{0}\n".format(self.br_name.format(port)))
|
||||||
self.sf.write("* s_en: {0}\n".format(self.sen_name))
|
self.sf.write("* s_en:\t{0}\n".format(self.sen_name))
|
||||||
self.sf.write("* q: {0}\n".format(self.q_name))
|
self.sf.write("* q:\t{0}\n".format(self.q_name))
|
||||||
self.sf.write("* qbar: {0}\n".format(self.qbar_name))
|
self.sf.write("* qbar:\t{0}\n".format(self.qbar_name))
|
||||||
|
|
||||||
# Write debug comments to stim file
|
# Write debug comments to stim file
|
||||||
self.sf.write("\n\n* Sequence of operations\n")
|
self.sf.write("\n\n* Sequence of operations\n")
|
||||||
|
|
@ -498,7 +473,7 @@ class functional(simulation):
|
||||||
|
|
||||||
for (word, dout_port, eo_period, cycle) in self.read_check:
|
for (word, dout_port, eo_period, cycle) in self.read_check:
|
||||||
t_initial = eo_period
|
t_initial = eo_period
|
||||||
t_final = eo_period
|
t_final = eo_period + 0.01 * self.period
|
||||||
num_bits = self.word_size + self.num_spare_cols
|
num_bits = self.word_size + self.num_spare_cols
|
||||||
for bit in range(num_bits):
|
for bit in range(num_bits):
|
||||||
signal_name = "{0}_{1}".format(dout_port, bit)
|
signal_name = "{0}_{1}".format(dout_port, bit)
|
||||||
|
|
|
||||||
|
|
@ -372,6 +372,38 @@ class simulation():
|
||||||
time_spacing,
|
time_spacing,
|
||||||
comment))
|
comment))
|
||||||
|
|
||||||
|
def combine_word(self, spare, word):
|
||||||
|
if len(spare) > 0:
|
||||||
|
return spare + "+" + word
|
||||||
|
|
||||||
|
return word
|
||||||
|
|
||||||
|
def format_value(self, value):
|
||||||
|
""" Format in better readable manner """
|
||||||
|
|
||||||
|
def delineate(word):
|
||||||
|
# Create list of chars in reverse order
|
||||||
|
split_word = list(reversed([x for x in word]))
|
||||||
|
# Add underscore every 4th char
|
||||||
|
split_word2 = [x + '_' * (n != 0 and n % 4 == 0) for n, x in enumerate(split_word)]
|
||||||
|
# Join the word unreversed back together
|
||||||
|
new_word = ''.join(reversed(split_word2))
|
||||||
|
return(new_word)
|
||||||
|
|
||||||
|
# Split extra cols
|
||||||
|
if self.num_spare_cols > 0:
|
||||||
|
vals = value[self.num_spare_cols:]
|
||||||
|
spare_vals = value[:self.num_spare_cols]
|
||||||
|
else:
|
||||||
|
vals = value
|
||||||
|
spare_vals = ""
|
||||||
|
|
||||||
|
# Insert underscores
|
||||||
|
vals = delineate(vals)
|
||||||
|
spare_vals = delineate(spare_vals)
|
||||||
|
|
||||||
|
return self.combine_word(spare_vals, vals)
|
||||||
|
|
||||||
def gen_cycle_comment(self, op, word, addr, wmask, port, t_current):
|
def gen_cycle_comment(self, op, word, addr, wmask, port, t_current):
|
||||||
if op == "noop":
|
if op == "noop":
|
||||||
str = "\tIdle during cycle {0} ({1}ns - {2}ns)"
|
str = "\tIdle during cycle {0} ({1}ns - {2}ns)"
|
||||||
|
|
@ -483,8 +515,6 @@ class simulation():
|
||||||
self.sen_name = sen_with_port
|
self.sen_name = sen_with_port
|
||||||
debug.warning("Error occurred while determining SEN name. Can cause faults in simulation.")
|
debug.warning("Error occurred while determining SEN name. Can cause faults in simulation.")
|
||||||
|
|
||||||
debug.info(2, "s_en name = {}".format(self.sen_name))
|
|
||||||
|
|
||||||
column_addr = self.get_column_addr()
|
column_addr = self.get_column_addr()
|
||||||
bl_name_port, br_name_port = self.get_bl_name(self.graph.all_paths, port)
|
bl_name_port, br_name_port = self.get_bl_name(self.graph.all_paths, port)
|
||||||
port_pos = -1 - len(str(column_addr)) - len(str(port))
|
port_pos = -1 - len(str(column_addr)) - len(str(port))
|
||||||
|
|
@ -505,11 +535,12 @@ class simulation():
|
||||||
'{}{}_{}'.format(self.dout_name, port, self.probe_data))
|
'{}{}_{}'.format(self.dout_name, port, self.probe_data))
|
||||||
|
|
||||||
self.sen_name = self.get_sen_name(self.graph.all_paths)
|
self.sen_name = self.get_sen_name(self.graph.all_paths)
|
||||||
debug.info(2, "s_en name = {}".format(self.sen_name))
|
#debug.info(2, "s_en {}".format(self.sen_name))
|
||||||
|
|
||||||
self.bl_name = "bl{0}_{1}".format(port, OPTS.word_size - 1)
|
self.bl_name = "bl{0}_{1}".format(port, OPTS.word_size - 1)
|
||||||
self.br_name = "br{0}_{1}".format(port, OPTS.word_size - 1)
|
self.br_name = "br{0}_{1}".format(port, OPTS.word_size - 1)
|
||||||
debug.info(2, "bl name={}, br name={}".format(self.bl_name, self.br_name))
|
# debug.info(2, "bl name={0}".format(self.bl_name))
|
||||||
|
# debug.info(2, "br name={0}".format(self.br_name))
|
||||||
|
|
||||||
def get_sen_name(self, paths, assumed_port=None):
|
def get_sen_name(self, paths, assumed_port=None):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -222,7 +222,7 @@ class stimuli():
|
||||||
|
|
||||||
def gen_meas_value(self, meas_name, dout, t_initial, t_final):
|
def gen_meas_value(self, meas_name, dout, t_initial, t_final):
|
||||||
measure_string=".meas tran {0} FIND v({1}) AT={2}n\n\n".format(meas_name.lower(), dout, (t_initial + t_final) / 2)
|
measure_string=".meas tran {0} FIND v({1}) AT={2}n\n\n".format(meas_name.lower(), dout, (t_initial + t_final) / 2)
|
||||||
# measure_string=".meas tran {0} AVG v({1}) FROM={2}n TO={3}n\n\n".format(meas_name.lower(), dout, t_initial, t_final)
|
#measure_string=".meas tran {0} AVG v({1}) FROM={2}n TO={3}n\n\n".format(meas_name.lower(), dout, t_initial, t_final)
|
||||||
self.sf.write(measure_string)
|
self.sf.write(measure_string)
|
||||||
|
|
||||||
def write_control(self, end_time, runlvl=4):
|
def write_control(self, end_time, runlvl=4):
|
||||||
|
|
@ -237,12 +237,13 @@ class stimuli():
|
||||||
reltol = 0.005 # 0.5%
|
reltol = 0.005 # 0.5%
|
||||||
else:
|
else:
|
||||||
reltol = 0.001 # 0.1%
|
reltol = 0.001 # 0.1%
|
||||||
timestep = 10 # ps, was 5ps but ngspice was complaining the timestep was too small in certain tests.
|
timestep = 10 # ps
|
||||||
|
|
||||||
if OPTS.spice_name == "ngspice":
|
if OPTS.spice_name == "ngspice":
|
||||||
self.sf.write(".TEMP {}\n".format(self.temperature))
|
self.sf.write(".TEMP {}\n".format(self.temperature))
|
||||||
# UIC is needed for ngspice to converge
|
# UIC is needed for ngspice to converge
|
||||||
self.sf.write(".TRAN {0}p {1}n UIC\n".format(timestep, end_time))
|
# Format: .tran tstep tstop < tstart < tmax >>
|
||||||
|
self.sf.write(".TRAN {0}p {1}n 0n {0}p UIC\n".format(timestep, end_time))
|
||||||
# ngspice sometimes has convergence problems if not using gear method
|
# ngspice sometimes has convergence problems if not using gear method
|
||||||
# which is more accurate, but slower than the default trapezoid method
|
# which is more accurate, but slower than the default trapezoid method
|
||||||
# Do not remove this or it may not converge due to some "pa_00" nodes
|
# Do not remove this or it may not converge due to some "pa_00" nodes
|
||||||
|
|
@ -268,7 +269,8 @@ class stimuli():
|
||||||
self.sf.write("simulator lang=spice\n")
|
self.sf.write("simulator lang=spice\n")
|
||||||
elif OPTS.spice_name in ["hspice", "xa"]:
|
elif OPTS.spice_name in ["hspice", "xa"]:
|
||||||
self.sf.write(".TEMP {}\n".format(self.temperature))
|
self.sf.write(".TEMP {}\n".format(self.temperature))
|
||||||
self.sf.write(".TRAN {0}p {1}n UIC\n".format(timestep, end_time))
|
# Format: .tran tstep tstop < tstart < tmax >>
|
||||||
|
self.sf.write(".TRAN {0}p {1}n 0n {0}p UIC\n".format(timestep, end_time))
|
||||||
self.sf.write(".OPTIONS POST=1 RUNLVL={0} PROBE\n".format(runlvl))
|
self.sf.write(".OPTIONS POST=1 RUNLVL={0} PROBE\n".format(runlvl))
|
||||||
self.sf.write(".OPTIONS PSF=1 \n")
|
self.sf.write(".OPTIONS PSF=1 \n")
|
||||||
self.sf.write(".OPTIONS HIER_DELIM=1 \n")
|
self.sf.write(".OPTIONS HIER_DELIM=1 \n")
|
||||||
|
|
@ -276,7 +278,9 @@ class stimuli():
|
||||||
self.sf.write(".OPTIONS DEVICE TEMP={}\n".format(self.temperature))
|
self.sf.write(".OPTIONS DEVICE TEMP={}\n".format(self.temperature))
|
||||||
self.sf.write(".OPTIONS MEASURE MEASFAIL=1\n")
|
self.sf.write(".OPTIONS MEASURE MEASFAIL=1\n")
|
||||||
self.sf.write(".OPTIONS LINSOL type=klu\n")
|
self.sf.write(".OPTIONS LINSOL type=klu\n")
|
||||||
self.sf.write(".TRAN {0}p {1}n\n".format(timestep, end_time))
|
self.sf.write(".OPTIONS TIMEINT RELTOL=1e-6 ABSTOL=1e-10 method=gear minorder=2\n")
|
||||||
|
# Format: .TRAN <initial step> <final time> <start time> <step ceiling>
|
||||||
|
self.sf.write(".TRAN {0}p {1}n 0n {0}p\n".format(timestep, end_time))
|
||||||
elif OPTS.spice_name:
|
elif OPTS.spice_name:
|
||||||
debug.error("Unkown spice simulator {}".format(OPTS.spice_name), -1)
|
debug.error("Unkown spice simulator {}".format(OPTS.spice_name), -1)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ nominal_corner_only = True
|
||||||
route_supplies = "ring"
|
route_supplies = "ring"
|
||||||
#route_supplies = "left"
|
#route_supplies = "left"
|
||||||
check_lvsdrc = True
|
check_lvsdrc = True
|
||||||
|
uniquify = True
|
||||||
#perimeter_pins = False
|
#perimeter_pins = False
|
||||||
#netlist_only = True
|
#netlist_only = True
|
||||||
#analytical_delay = False
|
#analytical_delay = False
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,7 @@ class VlsiLayout:
|
||||||
coordinatesRotate.extend((newX,newY))
|
coordinatesRotate.extend((newX,newY))
|
||||||
return coordinatesRotate
|
return coordinatesRotate
|
||||||
|
|
||||||
def uniquify(self):
|
def uniquify(self, prefix_name=None):
|
||||||
new_structures = {}
|
new_structures = {}
|
||||||
if self.rootStructureName[-1] == "\x00":
|
if self.rootStructureName[-1] == "\x00":
|
||||||
prefix = self.rootStructureName[0:-1] + "_"
|
prefix = self.rootStructureName[0:-1] + "_"
|
||||||
|
|
@ -92,7 +92,10 @@ class VlsiLayout:
|
||||||
base_name = name[0:-1]
|
base_name = name[0:-1]
|
||||||
else:
|
else:
|
||||||
base_name = name
|
base_name = name
|
||||||
if name != self.rootStructureName:
|
# Don't do library cells
|
||||||
|
if prefix_name and base_name.startswith(prefix_name):
|
||||||
|
new_name = name
|
||||||
|
elif name != self.rootStructureName:
|
||||||
new_name = self.padText(prefix + base_name)
|
new_name = self.padText(prefix + base_name)
|
||||||
else:
|
else:
|
||||||
new_name = name
|
new_name = name
|
||||||
|
|
@ -105,7 +108,11 @@ class VlsiLayout:
|
||||||
base_sref_name = sref.sName[0:-1]
|
base_sref_name = sref.sName[0:-1]
|
||||||
else:
|
else:
|
||||||
base_sref_name = sref.sName
|
base_sref_name = sref.sName
|
||||||
new_sref_name = self.padText(prefix + base_sref_name)
|
# Don't do library cells
|
||||||
|
if prefix_name and base_sref_name.startswith(prefix_name):
|
||||||
|
new_sref_name = sref.sName
|
||||||
|
else:
|
||||||
|
new_sref_name = self.padText(prefix + base_sref_name)
|
||||||
sref.sName = new_sref_name
|
sref.sName = new_sref_name
|
||||||
#print("SREF: {0} -> {1}".format(base_sref_name, new_sref_name))
|
#print("SREF: {0} -> {1}".format(base_sref_name, new_sref_name))
|
||||||
self.structures = new_structures
|
self.structures = new_structures
|
||||||
|
|
@ -770,7 +777,13 @@ class VlsiLayout:
|
||||||
from tech import layer_override
|
from tech import layer_override
|
||||||
if layer_override[label_text]:
|
if layer_override[label_text]:
|
||||||
shapes = self.getAllShapes((layer_override[label_text][0], None))
|
shapes = self.getAllShapes((layer_override[label_text][0], None))
|
||||||
lpp = layer_override[label_text]
|
if not shapes:
|
||||||
|
shapes = self.getAllShapes(lpp)
|
||||||
|
else:
|
||||||
|
lpp = layer_override[label_text]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
for boundary in shapes:
|
for boundary in shapes:
|
||||||
|
|
|
||||||
|
|
@ -620,7 +620,7 @@ class bank(design.design):
|
||||||
self.copy_power_pins(inst, "gnd", add_vias=False)
|
self.copy_power_pins(inst, "gnd", add_vias=False)
|
||||||
|
|
||||||
if 'vpb' in self.bitcell_array_inst.mod.pins and 'vnb' in self.bitcell_array_inst.mod.pins:
|
if 'vpb' in self.bitcell_array_inst.mod.pins and 'vnb' in self.bitcell_array_inst.mod.pins:
|
||||||
for pin_name, supply_name in zip(['vpb','vnb'],['gnd','vdd']):
|
for pin_name, supply_name in zip(['vnb','vpb'],['gnd','vdd']):
|
||||||
self.copy_power_pins(self.bitcell_array_inst, pin_name, new_name=supply_name)
|
self.copy_power_pins(self.bitcell_array_inst, pin_name, new_name=supply_name)
|
||||||
|
|
||||||
# If we use the pinvbuf as the decoder, we need to add power pins.
|
# If we use the pinvbuf as the decoder, we need to add power pins.
|
||||||
|
|
|
||||||
|
|
@ -162,9 +162,6 @@ class bitcell_base_array(design.design):
|
||||||
inst = self.cell_inst[row, col]
|
inst = self.cell_inst[row, col]
|
||||||
for pin_name in ["vdd", "gnd"]:
|
for pin_name in ["vdd", "gnd"]:
|
||||||
self.copy_layout_pin(inst, pin_name)
|
self.copy_layout_pin(inst, pin_name)
|
||||||
if row == 2: #add only 1 label per col
|
|
||||||
for pin_name in ["vdd", "gnd"]:
|
|
||||||
self.copy_layout_pin(inst, pin_name)
|
|
||||||
|
|
||||||
def add_layout_pins(self):
|
def add_layout_pins(self):
|
||||||
""" Add the layout pins """
|
""" Add the layout pins """
|
||||||
|
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
import sys
|
|
||||||
from gdsMill import gdsMill
|
|
||||||
|
|
||||||
if len(sys.argv) < 3:
|
|
||||||
print("Script to prefix every instance and structure with the root cell name to provide unique namespace.")
|
|
||||||
print("Usage: {0} in.gds out.gds".format(sys.argv[0]))
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
gds_file = sys.argv[1]
|
|
||||||
gds = gdsMill.VlsiLayout()
|
|
||||||
reader = gdsMill.Gds2reader(gds)
|
|
||||||
reader.loadFromFile(gds_file)
|
|
||||||
|
|
||||||
gds.uniquify()
|
|
||||||
|
|
||||||
writer = gdsMill.Gds2writer(gds)
|
|
||||||
writer.writeToFile(sys.argv[2])
|
|
||||||
|
|
@ -69,7 +69,12 @@ class sram():
|
||||||
reader = gdsMill.Gds2reader(gds)
|
reader = gdsMill.Gds2reader(gds)
|
||||||
reader.loadFromFile(name)
|
reader.loadFromFile(name)
|
||||||
|
|
||||||
gds.uniquify()
|
# Uniquify but skip the library cells since they are hard coded
|
||||||
|
try:
|
||||||
|
from tech import library_prefix_name
|
||||||
|
except ImportError:
|
||||||
|
library_prefix_name = None
|
||||||
|
gds.uniquify(library_prefix_name)
|
||||||
|
|
||||||
writer = gdsMill.Gds2writer(gds)
|
writer = gdsMill.Gds2writer(gds)
|
||||||
unique_name = name.replace(".gds", "_unique.gds")
|
unique_name = name.replace(".gds", "_unique.gds")
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,11 @@ class sram_config:
|
||||||
def __init__(self, word_size, num_words, write_size=None, num_banks=1, words_per_row=None, num_spare_rows=0, num_spare_cols=0):
|
def __init__(self, word_size, num_words, write_size=None, num_banks=1, words_per_row=None, num_spare_rows=0, num_spare_cols=0):
|
||||||
self.word_size = word_size
|
self.word_size = word_size
|
||||||
self.num_words = num_words
|
self.num_words = num_words
|
||||||
self.write_size = write_size
|
# Don't add a write mask if it is the same size as the data word
|
||||||
|
if write_size and write_size==word_size:
|
||||||
|
self.write_size = None
|
||||||
|
else:
|
||||||
|
self.write_size = write_size
|
||||||
self.num_banks = num_banks
|
self.num_banks = num_banks
|
||||||
self.num_spare_rows = num_spare_rows
|
self.num_spare_rows = num_spare_rows
|
||||||
self.num_spare_cols = num_spare_cols
|
self.num_spare_cols = num_spare_cols
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,15 @@ class array_test(openram_test):
|
||||||
globals.init_openram(config_file)
|
globals.init_openram(config_file)
|
||||||
|
|
||||||
debug.info(2, "Testing 8x8 array for 6t_cell")
|
debug.info(2, "Testing 8x8 array for 6t_cell")
|
||||||
a = factory.create(module_type="bitcell_array", cols=8, rows=8)
|
|
||||||
|
if OPTS.tech_name == "sky130":
|
||||||
|
num_spare_rows = 1
|
||||||
|
num_spare_cols = 1
|
||||||
|
else:
|
||||||
|
num_spare_rows = 0
|
||||||
|
num_spare_cols = 0
|
||||||
|
|
||||||
|
a = factory.create(module_type="bitcell_array", cols=8 + num_spare_cols, rows=8 + num_spare_rows)
|
||||||
self.local_check(a)
|
self.local_check(a)
|
||||||
|
|
||||||
globals.end_openram()
|
globals.end_openram()
|
||||||
|
|
|
||||||
|
|
@ -19,9 +19,19 @@ class replica_column_test(openram_test):
|
||||||
def runTest(self):
|
def runTest(self):
|
||||||
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
|
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
|
||||||
globals.init_openram(config_file)
|
globals.init_openram(config_file)
|
||||||
|
if OPTS.tech_name == "sky130":
|
||||||
|
num_spare_rows = 1
|
||||||
|
num_spare_cols = 1
|
||||||
|
else:
|
||||||
|
num_spare_rows = 0
|
||||||
|
num_spare_cols = 0
|
||||||
|
|
||||||
debug.info(2, "Testing replica column for single port")
|
debug.info(2, "Testing replica column for single port")
|
||||||
a = factory.create(module_type="replica_column", rows=4, rbl=[1, 0], replica_bit=1)
|
a = factory.create(module_type="replica_column",
|
||||||
|
rows=4 + num_spare_rows,
|
||||||
|
rbl=[1, 0],
|
||||||
|
replica_bit=1,
|
||||||
|
column_offset=num_spare_cols)
|
||||||
self.local_check(a)
|
self.local_check(a)
|
||||||
|
|
||||||
globals.end_openram()
|
globals.end_openram()
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# See LICENSE for licensing information.
|
||||||
|
#
|
||||||
|
# Copyright (c) 2016-2021 Regents of the University of California and The Board
|
||||||
|
# of Regents for the Oklahoma Agricultural and Mechanical College
|
||||||
|
# (acting for and on behalf of Oklahoma State University)
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
import unittest
|
||||||
|
from testutils import *
|
||||||
|
import sys, os
|
||||||
|
sys.path.append(os.getenv("OPENRAM_HOME"))
|
||||||
|
import globals
|
||||||
|
from globals import OPTS
|
||||||
|
from sram_factory import factory
|
||||||
|
import debug
|
||||||
|
|
||||||
|
|
||||||
|
@unittest.skip("SKIPPING 50_riscv_func_test")
|
||||||
|
class riscv_func_test(openram_test):
|
||||||
|
|
||||||
|
def runTest(self):
|
||||||
|
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
|
||||||
|
globals.init_openram(config_file)
|
||||||
|
OPTS.analytical_delay = False
|
||||||
|
OPTS.netlist_only = True
|
||||||
|
OPTS.trim_netlist = False
|
||||||
|
|
||||||
|
#OPTS.local_array_size = 16
|
||||||
|
OPTS.num_rw_ports = 1
|
||||||
|
OPTS.num_r_ports = 1
|
||||||
|
OPTS.num_w_ports = 0
|
||||||
|
globals.setup_bitcell()
|
||||||
|
|
||||||
|
# This is a hack to reload the characterizer __init__ with the spice version
|
||||||
|
from importlib import reload
|
||||||
|
import characterizer
|
||||||
|
reload(characterizer)
|
||||||
|
from characterizer import functional
|
||||||
|
from sram_config import sram_config
|
||||||
|
c = sram_config(word_size=32,
|
||||||
|
write_size=8,
|
||||||
|
num_words=256,
|
||||||
|
num_banks=1)
|
||||||
|
|
||||||
|
debug.info(1, "Functional test RISC-V memory"
|
||||||
|
"{} bit words, {} words, {} words per row, {} banks".format(c.word_size,
|
||||||
|
c.num_words,
|
||||||
|
c.words_per_row,
|
||||||
|
c.num_banks))
|
||||||
|
s = factory.create(module_type="sram", sram_config=c)
|
||||||
|
corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0])
|
||||||
|
f = functional(s.s, corner=corner, cycles=100)
|
||||||
|
(fail, error) = f.run()
|
||||||
|
self.assertTrue(fail, error)
|
||||||
|
|
||||||
|
globals.end_openram()
|
||||||
|
|
||||||
|
# instantiate a copy 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(testRunner=debugTestRunner())
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# See LICENSE for licensing information.
|
||||||
|
#
|
||||||
|
# Copyright (c) 2016-2021 Regents of the University of California and The Board
|
||||||
|
# of Regents for the Oklahoma Agricultural and Mechanical College
|
||||||
|
# (acting for and on behalf of Oklahoma State University)
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
import unittest
|
||||||
|
from testutils import *
|
||||||
|
import sys, os
|
||||||
|
sys.path.append(os.getenv("OPENRAM_HOME"))
|
||||||
|
import globals
|
||||||
|
from globals import OPTS
|
||||||
|
from sram_factory import factory
|
||||||
|
import debug
|
||||||
|
|
||||||
|
|
||||||
|
@unittest.skip("SKIPPING 50_riscv_func_test")
|
||||||
|
class riscv_func_test(openram_test):
|
||||||
|
|
||||||
|
def runTest(self):
|
||||||
|
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
|
||||||
|
globals.init_openram(config_file)
|
||||||
|
OPTS.analytical_delay = False
|
||||||
|
OPTS.netlist_only = True
|
||||||
|
OPTS.trim_netlist = False
|
||||||
|
|
||||||
|
#OPTS.local_array_size = 16
|
||||||
|
OPTS.num_rw_ports = 1
|
||||||
|
OPTS.num_r_ports = 0
|
||||||
|
OPTS.num_w_ports = 0
|
||||||
|
globals.setup_bitcell()
|
||||||
|
|
||||||
|
# This is a hack to reload the characterizer __init__ with the spice version
|
||||||
|
from importlib import reload
|
||||||
|
import characterizer
|
||||||
|
reload(characterizer)
|
||||||
|
from characterizer import functional
|
||||||
|
from sram_config import sram_config
|
||||||
|
c = sram_config(word_size=32,
|
||||||
|
write_size=8,
|
||||||
|
num_words=256,
|
||||||
|
num_banks=1,
|
||||||
|
num_spare_rows=1,
|
||||||
|
num_spare_cols=1)
|
||||||
|
|
||||||
|
debug.info(1, "Functional test RISC-V memory"
|
||||||
|
"{} bit words, {} words, {} words per row, {} banks".format(c.word_size,
|
||||||
|
c.num_words,
|
||||||
|
c.words_per_row,
|
||||||
|
c.num_banks))
|
||||||
|
s = factory.create(module_type="sram", sram_config=c)
|
||||||
|
corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0])
|
||||||
|
f = functional(s.s, corner=corner, cycles=3)
|
||||||
|
(fail, error) = f.run()
|
||||||
|
self.assertTrue(fail, error)
|
||||||
|
|
||||||
|
globals.end_openram()
|
||||||
|
|
||||||
|
# instantiate a copy 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(testRunner=debugTestRunner())
|
||||||
|
|
@ -16,7 +16,7 @@ from sram_factory import factory
|
||||||
import debug
|
import debug
|
||||||
|
|
||||||
|
|
||||||
# @unittest.skip("SKIPPING 50_riscv_func_test")
|
@unittest.skip("SKIPPING 50_riscv_func_test")
|
||||||
class riscv_func_test(openram_test):
|
class riscv_func_test(openram_test):
|
||||||
|
|
||||||
def runTest(self):
|
def runTest(self):
|
||||||
|
|
@ -24,6 +24,8 @@ class riscv_func_test(openram_test):
|
||||||
globals.init_openram(config_file)
|
globals.init_openram(config_file)
|
||||||
OPTS.analytical_delay = False
|
OPTS.analytical_delay = False
|
||||||
OPTS.netlist_only = True
|
OPTS.netlist_only = True
|
||||||
|
OPTS.trim_netlist = False
|
||||||
|
|
||||||
OPTS.num_rw_ports = 1
|
OPTS.num_rw_ports = 1
|
||||||
OPTS.num_w_ports = 0
|
OPTS.num_w_ports = 0
|
||||||
OPTS.num_r_ports = 1
|
OPTS.num_r_ports = 1
|
||||||
|
|
@ -48,7 +50,7 @@ class riscv_func_test(openram_test):
|
||||||
c.num_banks))
|
c.num_banks))
|
||||||
s = factory.create(module_type="sram", sram_config=c)
|
s = factory.create(module_type="sram", sram_config=c)
|
||||||
corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0])
|
corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0])
|
||||||
f = functional(s.s, corner=corner, cycles=50)
|
f = functional(s.s, corner=corner, cycles=25)
|
||||||
(fail, error) = f.run()
|
(fail, error) = f.run()
|
||||||
self.assertTrue(fail, error)
|
self.assertTrue(fail, error)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ from sram_factory import factory
|
||||||
import debug
|
import debug
|
||||||
|
|
||||||
|
|
||||||
@unittest.skip("SKIPPING 50_riscv_phys_test")
|
# @unittest.skip("SKIPPING 50_riscv_phys_test")
|
||||||
class riscv_phys_test(openram_test):
|
class riscv_phys_test(openram_test):
|
||||||
|
|
||||||
def runTest(self):
|
def runTest(self):
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ from sram_factory import factory
|
||||||
import debug
|
import debug
|
||||||
|
|
||||||
|
|
||||||
# @unittest.skip("SKIPPING 50_riscv_func_test")
|
@unittest.skip("SKIPPING 50_riscv_func_test")
|
||||||
class riscv_func_test(openram_test):
|
class riscv_func_test(openram_test):
|
||||||
|
|
||||||
def runTest(self):
|
def runTest(self):
|
||||||
|
|
@ -24,6 +24,15 @@ class riscv_func_test(openram_test):
|
||||||
globals.init_openram(config_file)
|
globals.init_openram(config_file)
|
||||||
OPTS.analytical_delay = False
|
OPTS.analytical_delay = False
|
||||||
OPTS.netlist_only = True
|
OPTS.netlist_only = True
|
||||||
|
OPTS.trim_netlist = False
|
||||||
|
|
||||||
|
if OPTS.tech_name == "sky130":
|
||||||
|
num_spare_rows = 1
|
||||||
|
num_spare_cols = 1
|
||||||
|
else:
|
||||||
|
num_spare_rows = 0
|
||||||
|
num_spare_cols = 0
|
||||||
|
|
||||||
OPTS.num_rw_ports = 1
|
OPTS.num_rw_ports = 1
|
||||||
OPTS.num_w_ports = 0
|
OPTS.num_w_ports = 0
|
||||||
OPTS.num_r_ports = 0
|
OPTS.num_r_ports = 0
|
||||||
|
|
@ -37,8 +46,10 @@ class riscv_func_test(openram_test):
|
||||||
from sram_config import sram_config
|
from sram_config import sram_config
|
||||||
c = sram_config(word_size=32,
|
c = sram_config(word_size=32,
|
||||||
write_size=8,
|
write_size=8,
|
||||||
num_words=32,
|
num_words=64,
|
||||||
num_banks=1)
|
num_banks=1,
|
||||||
|
num_spare_cols=num_spare_cols,
|
||||||
|
num_spare_rows=num_spare_rows)
|
||||||
c.words_per_row=1
|
c.words_per_row=1
|
||||||
c.recompute_sizes()
|
c.recompute_sizes()
|
||||||
debug.info(1, "Functional test RISC-V memory"
|
debug.info(1, "Functional test RISC-V memory"
|
||||||
|
|
@ -48,7 +59,7 @@ class riscv_func_test(openram_test):
|
||||||
c.num_banks))
|
c.num_banks))
|
||||||
s = factory.create(module_type="sram", sram_config=c)
|
s = factory.create(module_type="sram", sram_config=c)
|
||||||
corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0])
|
corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0])
|
||||||
f = functional(s.s, corner=corner, cycles=50)
|
f = functional(s.s, corner=corner, cycles=25)
|
||||||
(fail, error) = f.run()
|
(fail, error) = f.run()
|
||||||
self.assertTrue(fail, error)
|
self.assertTrue(fail, error)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,62 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# See LICENSE for licensing information.
|
||||||
|
#
|
||||||
|
# Copyright (c) 2016-2021 Regents of the University of California and The Board
|
||||||
|
# of Regents for the Oklahoma Agricultural and Mechanical College
|
||||||
|
# (acting for and on behalf of Oklahoma State University)
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
import unittest
|
||||||
|
from testutils import *
|
||||||
|
import sys, os
|
||||||
|
sys.path.append(os.getenv("OPENRAM_HOME"))
|
||||||
|
import globals
|
||||||
|
from globals import OPTS
|
||||||
|
from sram_factory import factory
|
||||||
|
import debug
|
||||||
|
|
||||||
|
|
||||||
|
# @unittest.skip("SKIPPING 50_riscv_phys_test")
|
||||||
|
class riscv_phys_test(openram_test):
|
||||||
|
|
||||||
|
def runTest(self):
|
||||||
|
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
|
||||||
|
globals.init_openram(config_file)
|
||||||
|
from sram_config import sram_config
|
||||||
|
|
||||||
|
OPTS.num_rw_ports = 1
|
||||||
|
OPTS.num_r_ports = 1
|
||||||
|
OPTS.num_w_ports = 0
|
||||||
|
OPTS.local_array_size = 16
|
||||||
|
globals.setup_bitcell()
|
||||||
|
OPTS.route_supplies = False
|
||||||
|
OPTS.perimeter_pins = False
|
||||||
|
|
||||||
|
c = sram_config(word_size=32,
|
||||||
|
write_size=8,
|
||||||
|
num_words=32,
|
||||||
|
num_banks=1,
|
||||||
|
num_spare_rows=1,
|
||||||
|
num_spare_cols=1)
|
||||||
|
c.words_per_row=2
|
||||||
|
c.recompute_sizes()
|
||||||
|
debug.info(1, "Layout test for {}rw,{}r,{}w sram "
|
||||||
|
"with {} bit words, {} words, {} words per "
|
||||||
|
"row, {} banks".format(OPTS.num_rw_ports,
|
||||||
|
OPTS.num_r_ports,
|
||||||
|
OPTS.num_w_ports,
|
||||||
|
c.word_size,
|
||||||
|
c.num_words,
|
||||||
|
c.words_per_row,
|
||||||
|
c.num_banks))
|
||||||
|
a = factory.create(module_type="sram", sram_config=c)
|
||||||
|
self.local_check(a, final_verification=True)
|
||||||
|
|
||||||
|
globals.end_openram()
|
||||||
|
|
||||||
|
# instantiate a copy 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(testRunner=debugTestRunner())
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# See LICENSE for licensing information.
|
||||||
|
#
|
||||||
|
# Copyright (c) 2016-2021 Regents of the University of California and The Board
|
||||||
|
# of Regents for the Oklahoma Agricultural and Mechanical College
|
||||||
|
# (acting for and on behalf of Oklahoma State University)
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
import unittest
|
||||||
|
from testutils import *
|
||||||
|
import sys, os
|
||||||
|
sys.path.append(os.getenv("OPENRAM_HOME"))
|
||||||
|
import globals
|
||||||
|
from globals import OPTS
|
||||||
|
from sram_factory import factory
|
||||||
|
import debug
|
||||||
|
|
||||||
|
|
||||||
|
@unittest.skip("SKIPPING 50_riscv_func_test")
|
||||||
|
class riscv_func_test(openram_test):
|
||||||
|
|
||||||
|
def runTest(self):
|
||||||
|
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
|
||||||
|
globals.init_openram(config_file)
|
||||||
|
OPTS.analytical_delay = False
|
||||||
|
OPTS.netlist_only = True
|
||||||
|
OPTS.trim_netlist = False
|
||||||
|
|
||||||
|
#OPTS.local_array_size = 16
|
||||||
|
OPTS.num_rw_ports = 1
|
||||||
|
OPTS.num_r_ports = 1
|
||||||
|
OPTS.num_w_ports = 0
|
||||||
|
globals.setup_bitcell()
|
||||||
|
|
||||||
|
# This is a hack to reload the characterizer __init__ with the spice version
|
||||||
|
from importlib import reload
|
||||||
|
import characterizer
|
||||||
|
reload(characterizer)
|
||||||
|
from characterizer import functional
|
||||||
|
from sram_config import sram_config
|
||||||
|
c = sram_config(word_size=32,
|
||||||
|
write_size=8,
|
||||||
|
num_words=512,
|
||||||
|
num_banks=1)
|
||||||
|
|
||||||
|
debug.info(1, "Functional test RISC-V memory"
|
||||||
|
"{} bit words, {} words, {} words per row, {} banks".format(c.word_size,
|
||||||
|
c.num_words,
|
||||||
|
c.words_per_row,
|
||||||
|
c.num_banks))
|
||||||
|
s = factory.create(module_type="sram", sram_config=c)
|
||||||
|
corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0])
|
||||||
|
f = functional(s.s, corner=corner, cycles=100)
|
||||||
|
(fail, error) = f.run()
|
||||||
|
self.assertTrue(fail, error)
|
||||||
|
|
||||||
|
globals.end_openram()
|
||||||
|
|
||||||
|
# instantiate a copy 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(testRunner=debugTestRunner())
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# See LICENSE for licensing information.
|
||||||
|
#
|
||||||
|
# Copyright (c) 2016-2021 Regents of the University of California and The Board
|
||||||
|
# of Regents for the Oklahoma Agricultural and Mechanical College
|
||||||
|
# (acting for and on behalf of Oklahoma State University)
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
import unittest
|
||||||
|
from testutils import *
|
||||||
|
import sys, os
|
||||||
|
sys.path.append(os.getenv("OPENRAM_HOME"))
|
||||||
|
import globals
|
||||||
|
from globals import OPTS
|
||||||
|
from sram_factory import factory
|
||||||
|
import debug
|
||||||
|
|
||||||
|
|
||||||
|
@unittest.skip("SKIPPING 50_riscv_func_test")
|
||||||
|
class riscv_func_test(openram_test):
|
||||||
|
|
||||||
|
def runTest(self):
|
||||||
|
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
|
||||||
|
globals.init_openram(config_file)
|
||||||
|
OPTS.analytical_delay = False
|
||||||
|
OPTS.netlist_only = True
|
||||||
|
OPTS.trim_netlist = False
|
||||||
|
|
||||||
|
#OPTS.local_array_size = 16
|
||||||
|
OPTS.num_rw_ports = 1
|
||||||
|
OPTS.num_r_ports = 0
|
||||||
|
OPTS.num_w_ports = 0
|
||||||
|
globals.setup_bitcell()
|
||||||
|
|
||||||
|
# This is a hack to reload the characterizer __init__ with the spice version
|
||||||
|
from importlib import reload
|
||||||
|
import characterizer
|
||||||
|
reload(characterizer)
|
||||||
|
from characterizer import functional
|
||||||
|
from sram_config import sram_config
|
||||||
|
c = sram_config(word_size=32,
|
||||||
|
write_size=8,
|
||||||
|
num_words=512,
|
||||||
|
num_banks=1,
|
||||||
|
num_spare_rows=1,
|
||||||
|
num_spare_cols=1)
|
||||||
|
|
||||||
|
debug.info(1, "Functional test RISC-V memory"
|
||||||
|
"{} bit words, {} words, {} words per row, {} banks".format(c.word_size,
|
||||||
|
c.num_words,
|
||||||
|
c.words_per_row,
|
||||||
|
c.num_banks))
|
||||||
|
s = factory.create(module_type="sram", sram_config=c)
|
||||||
|
corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0])
|
||||||
|
f = functional(s.s, corner=corner, cycles=100)
|
||||||
|
(fail, error) = f.run()
|
||||||
|
self.assertTrue(fail, error)
|
||||||
|
|
||||||
|
globals.end_openram()
|
||||||
|
|
||||||
|
# instantiate a copy 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(testRunner=debugTestRunner())
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# See LICENSE for licensing information.
|
||||||
|
#
|
||||||
|
# Copyright (c) 2016-2021 Regents of the University of California and The Board
|
||||||
|
# of Regents for the Oklahoma Agricultural and Mechanical College
|
||||||
|
# (acting for and on behalf of Oklahoma State University)
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
import unittest
|
||||||
|
from testutils import *
|
||||||
|
import sys, os
|
||||||
|
sys.path.append(os.getenv("OPENRAM_HOME"))
|
||||||
|
import globals
|
||||||
|
from globals import OPTS
|
||||||
|
from sram_factory import factory
|
||||||
|
import debug
|
||||||
|
|
||||||
|
|
||||||
|
@unittest.skip("SKIPPING 50_riscv_func_test")
|
||||||
|
class riscv_func_test(openram_test):
|
||||||
|
|
||||||
|
def runTest(self):
|
||||||
|
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
|
||||||
|
globals.init_openram(config_file)
|
||||||
|
OPTS.analytical_delay = False
|
||||||
|
OPTS.netlist_only = True
|
||||||
|
OPTS.trim_netlist = False
|
||||||
|
|
||||||
|
#OPTS.local_array_size = 16
|
||||||
|
OPTS.num_rw_ports = 1
|
||||||
|
OPTS.num_r_ports = 1
|
||||||
|
OPTS.num_w_ports = 0
|
||||||
|
globals.setup_bitcell()
|
||||||
|
|
||||||
|
# This is a hack to reload the characterizer __init__ with the spice version
|
||||||
|
from importlib import reload
|
||||||
|
import characterizer
|
||||||
|
reload(characterizer)
|
||||||
|
from characterizer import functional
|
||||||
|
from sram_config import sram_config
|
||||||
|
c = sram_config(word_size=32,
|
||||||
|
write_size=8,
|
||||||
|
num_words=1024,
|
||||||
|
num_banks=1)
|
||||||
|
|
||||||
|
debug.info(1, "Functional test RISC-V memory"
|
||||||
|
"{} bit words, {} words, {} words per row, {} banks".format(c.word_size,
|
||||||
|
c.num_words,
|
||||||
|
c.words_per_row,
|
||||||
|
c.num_banks))
|
||||||
|
s = factory.create(module_type="sram", sram_config=c)
|
||||||
|
corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0])
|
||||||
|
f = functional(s.s, corner=corner)
|
||||||
|
(fail, error) = f.run()
|
||||||
|
self.assertTrue(fail, error)
|
||||||
|
|
||||||
|
globals.end_openram()
|
||||||
|
|
||||||
|
# instantiate a copy 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(testRunner=debugTestRunner())
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# See LICENSE for licensing information.
|
||||||
|
#
|
||||||
|
# Copyright (c) 2016-2021 Regents of the University of California and The Board
|
||||||
|
# of Regents for the Oklahoma Agricultural and Mechanical College
|
||||||
|
# (acting for and on behalf of Oklahoma State University)
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
import unittest
|
||||||
|
from testutils import *
|
||||||
|
import sys, os
|
||||||
|
sys.path.append(os.getenv("OPENRAM_HOME"))
|
||||||
|
import globals
|
||||||
|
from globals import OPTS
|
||||||
|
from sram_factory import factory
|
||||||
|
import debug
|
||||||
|
|
||||||
|
|
||||||
|
@unittest.skip("SKIPPING 50_riscv_func_test")
|
||||||
|
class riscv_func_test(openram_test):
|
||||||
|
|
||||||
|
def runTest(self):
|
||||||
|
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
|
||||||
|
globals.init_openram(config_file)
|
||||||
|
OPTS.analytical_delay = False
|
||||||
|
OPTS.netlist_only = True
|
||||||
|
OPTS.trim_netlist = False
|
||||||
|
|
||||||
|
#OPTS.local_array_size = 16
|
||||||
|
OPTS.num_rw_ports = 1
|
||||||
|
OPTS.num_r_ports = 0
|
||||||
|
OPTS.num_w_ports = 0
|
||||||
|
globals.setup_bitcell()
|
||||||
|
|
||||||
|
# This is a hack to reload the characterizer __init__ with the spice version
|
||||||
|
from importlib import reload
|
||||||
|
import characterizer
|
||||||
|
reload(characterizer)
|
||||||
|
from characterizer import functional
|
||||||
|
from sram_config import sram_config
|
||||||
|
c = sram_config(word_size=32,
|
||||||
|
write_size=8,
|
||||||
|
num_words=1024,
|
||||||
|
num_banks=1,
|
||||||
|
num_spare_rows=1,
|
||||||
|
num_spare_cols=1)
|
||||||
|
|
||||||
|
debug.info(1, "Functional test RISC-V memory"
|
||||||
|
"{} bit words, {} words, {} words per row, {} banks".format(c.word_size,
|
||||||
|
c.num_words,
|
||||||
|
c.words_per_row,
|
||||||
|
c.num_banks))
|
||||||
|
s = factory.create(module_type="sram", sram_config=c)
|
||||||
|
corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0])
|
||||||
|
f = functional(s.s, corner=corner)
|
||||||
|
(fail, error) = f.run()
|
||||||
|
self.assertTrue(fail, error)
|
||||||
|
|
||||||
|
globals.end_openram()
|
||||||
|
|
||||||
|
# instantiate a copy 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(testRunner=debugTestRunner())
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# See LICENSE for licensing information.
|
||||||
|
#
|
||||||
|
# Copyright (c) 2016-2021 Regents of the University of California and The Board
|
||||||
|
# of Regents for the Oklahoma Agricultural and Mechanical College
|
||||||
|
# (acting for and on behalf of Oklahoma State University)
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
import unittest
|
||||||
|
from testutils import *
|
||||||
|
import sys, os
|
||||||
|
sys.path.append(os.getenv("OPENRAM_HOME"))
|
||||||
|
import globals
|
||||||
|
from globals import OPTS
|
||||||
|
from sram_factory import factory
|
||||||
|
import debug
|
||||||
|
|
||||||
|
|
||||||
|
@unittest.skip("SKIPPING 50_riscv_func_test")
|
||||||
|
class riscv_func_test(openram_test):
|
||||||
|
|
||||||
|
def runTest(self):
|
||||||
|
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
|
||||||
|
globals.init_openram(config_file)
|
||||||
|
OPTS.analytical_delay = False
|
||||||
|
OPTS.netlist_only = True
|
||||||
|
OPTS.trim_netlist = False
|
||||||
|
|
||||||
|
#OPTS.local_array_size = 16
|
||||||
|
OPTS.num_rw_ports = 1
|
||||||
|
OPTS.num_r_ports = 1
|
||||||
|
OPTS.num_w_ports = 0
|
||||||
|
globals.setup_bitcell()
|
||||||
|
|
||||||
|
# This is a hack to reload the characterizer __init__ with the spice version
|
||||||
|
from importlib import reload
|
||||||
|
import characterizer
|
||||||
|
reload(characterizer)
|
||||||
|
from characterizer import functional
|
||||||
|
from sram_config import sram_config
|
||||||
|
c = sram_config(word_size=32,
|
||||||
|
write_size=8,
|
||||||
|
num_words=128,
|
||||||
|
num_banks=1)
|
||||||
|
|
||||||
|
debug.info(1, "Functional test RISC-V memory"
|
||||||
|
"{} bit words, {} words, {} words per row, {} banks".format(c.word_size,
|
||||||
|
c.num_words,
|
||||||
|
c.words_per_row,
|
||||||
|
c.num_banks))
|
||||||
|
s = factory.create(module_type="sram", sram_config=c)
|
||||||
|
corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0])
|
||||||
|
f = functional(s.s, corner=corner, cycles=100)
|
||||||
|
(fail, error) = f.run()
|
||||||
|
self.assertTrue(fail, error)
|
||||||
|
|
||||||
|
globals.end_openram()
|
||||||
|
|
||||||
|
# instantiate a copy 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(testRunner=debugTestRunner())
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# See LICENSE for licensing information.
|
||||||
|
#
|
||||||
|
# Copyright (c) 2016-2021 Regents of the University of California and The Board
|
||||||
|
# of Regents for the Oklahoma Agricultural and Mechanical College
|
||||||
|
# (acting for and on behalf of Oklahoma State University)
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
import unittest
|
||||||
|
from testutils import *
|
||||||
|
import sys, os
|
||||||
|
sys.path.append(os.getenv("OPENRAM_HOME"))
|
||||||
|
import globals
|
||||||
|
from globals import OPTS
|
||||||
|
from sram_factory import factory
|
||||||
|
import debug
|
||||||
|
|
||||||
|
|
||||||
|
@unittest.skip("SKIPPING 50_riscv_func_test")
|
||||||
|
class riscv_func_test(openram_test):
|
||||||
|
|
||||||
|
def runTest(self):
|
||||||
|
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
|
||||||
|
globals.init_openram(config_file)
|
||||||
|
OPTS.analytical_delay = False
|
||||||
|
OPTS.netlist_only = True
|
||||||
|
OPTS.trim_netlist = False
|
||||||
|
|
||||||
|
#OPTS.local_array_size = 16
|
||||||
|
OPTS.num_rw_ports = 1
|
||||||
|
OPTS.num_r_ports = 0
|
||||||
|
OPTS.num_w_ports = 0
|
||||||
|
globals.setup_bitcell()
|
||||||
|
|
||||||
|
# This is a hack to reload the characterizer __init__ with the spice version
|
||||||
|
from importlib import reload
|
||||||
|
import characterizer
|
||||||
|
reload(characterizer)
|
||||||
|
from characterizer import functional
|
||||||
|
from sram_config import sram_config
|
||||||
|
c = sram_config(word_size=32,
|
||||||
|
write_size=8,
|
||||||
|
num_words=128,
|
||||||
|
num_banks=1,
|
||||||
|
num_spare_rows=1,
|
||||||
|
num_spare_cols=1)
|
||||||
|
|
||||||
|
debug.info(1, "Functional test RISC-V memory"
|
||||||
|
"{} bit words, {} words, {} words per row, {} banks".format(c.word_size,
|
||||||
|
c.num_words,
|
||||||
|
c.words_per_row,
|
||||||
|
c.num_banks))
|
||||||
|
s = factory.create(module_type="sram", sram_config=c)
|
||||||
|
corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0])
|
||||||
|
f = functional(s.s, corner=corner, cycles=25)
|
||||||
|
(fail, error) = f.run()
|
||||||
|
self.assertTrue(fail, error)
|
||||||
|
|
||||||
|
globals.end_openram()
|
||||||
|
|
||||||
|
# instantiate a copy 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(testRunner=debugTestRunner())
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# See LICENSE for licensing information.
|
||||||
|
#
|
||||||
|
# Copyright (c) 2016-2021 Regents of the University of California and The Board
|
||||||
|
# of Regents for the Oklahoma Agricultural and Mechanical College
|
||||||
|
# (acting for and on behalf of Oklahoma State University)
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
import unittest
|
||||||
|
from testutils import *
|
||||||
|
import sys, os
|
||||||
|
sys.path.append(os.getenv("OPENRAM_HOME"))
|
||||||
|
import globals
|
||||||
|
from globals import OPTS
|
||||||
|
from sram_factory import factory
|
||||||
|
import debug
|
||||||
|
|
||||||
|
|
||||||
|
@unittest.skip("SKIPPING 50_riscv_func_test")
|
||||||
|
class riscv_func_test(openram_test):
|
||||||
|
|
||||||
|
def runTest(self):
|
||||||
|
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
|
||||||
|
globals.init_openram(config_file)
|
||||||
|
OPTS.analytical_delay = False
|
||||||
|
OPTS.netlist_only = True
|
||||||
|
OPTS.trim_netlist = False
|
||||||
|
|
||||||
|
OPTS.local_array_size = 16
|
||||||
|
OPTS.num_rw_ports = 1
|
||||||
|
OPTS.num_r_ports = 1
|
||||||
|
OPTS.num_w_ports = 0
|
||||||
|
globals.setup_bitcell()
|
||||||
|
|
||||||
|
# This is a hack to reload the characterizer __init__ with the spice version
|
||||||
|
from importlib import reload
|
||||||
|
import characterizer
|
||||||
|
reload(characterizer)
|
||||||
|
from characterizer import functional
|
||||||
|
from sram_config import sram_config
|
||||||
|
c = sram_config(word_size=32,
|
||||||
|
write_size=8,
|
||||||
|
num_words=2048,
|
||||||
|
num_banks=1)
|
||||||
|
|
||||||
|
debug.info(1, "Functional test RISC-V memory"
|
||||||
|
"{} bit words, {} words, {} words per row, {} banks".format(c.word_size,
|
||||||
|
c.num_words,
|
||||||
|
c.words_per_row,
|
||||||
|
c.num_banks))
|
||||||
|
s = factory.create(module_type="sram", sram_config=c)
|
||||||
|
corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0])
|
||||||
|
f = functional(s.s, corner=corner, cycles=100)
|
||||||
|
(fail, error) = f.run()
|
||||||
|
self.assertTrue(fail, error)
|
||||||
|
|
||||||
|
globals.end_openram()
|
||||||
|
|
||||||
|
# instantiate a copy 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(testRunner=debugTestRunner())
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# See LICENSE for licensing information.
|
||||||
|
#
|
||||||
|
# Copyright (c) 2016-2021 Regents of the University of California and The Board
|
||||||
|
# of Regents for the Oklahoma Agricultural and Mechanical College
|
||||||
|
# (acting for and on behalf of Oklahoma State University)
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
import unittest
|
||||||
|
from testutils import *
|
||||||
|
import sys, os
|
||||||
|
sys.path.append(os.getenv("OPENRAM_HOME"))
|
||||||
|
import globals
|
||||||
|
from globals import OPTS
|
||||||
|
from sram_factory import factory
|
||||||
|
import debug
|
||||||
|
|
||||||
|
|
||||||
|
@unittest.skip("SKIPPING 50_riscv_func_test")
|
||||||
|
class riscv_func_test(openram_test):
|
||||||
|
|
||||||
|
def runTest(self):
|
||||||
|
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
|
||||||
|
globals.init_openram(config_file)
|
||||||
|
OPTS.analytical_delay = False
|
||||||
|
OPTS.netlist_only = True
|
||||||
|
OPTS.trim_netlist = False
|
||||||
|
|
||||||
|
OPTS.local_array_size = 16
|
||||||
|
OPTS.num_rw_ports = 1
|
||||||
|
OPTS.num_r_ports = 0
|
||||||
|
OPTS.num_w_ports = 0
|
||||||
|
globals.setup_bitcell()
|
||||||
|
|
||||||
|
# This is a hack to reload the characterizer __init__ with the spice version
|
||||||
|
from importlib import reload
|
||||||
|
import characterizer
|
||||||
|
reload(characterizer)
|
||||||
|
from characterizer import functional
|
||||||
|
from sram_config import sram_config
|
||||||
|
c = sram_config(word_size=32,
|
||||||
|
write_size=8,
|
||||||
|
num_words=2048,
|
||||||
|
num_banks=1,
|
||||||
|
num_spare_rows=1,
|
||||||
|
num_spare_cols=1)
|
||||||
|
|
||||||
|
debug.info(1, "Functional test RISC-V memory"
|
||||||
|
"{} bit words, {} words, {} words per row, {} banks".format(c.word_size,
|
||||||
|
c.num_words,
|
||||||
|
c.words_per_row,
|
||||||
|
c.num_banks))
|
||||||
|
s = factory.create(module_type="sram", sram_config=c)
|
||||||
|
corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0])
|
||||||
|
f = functional(s.s, corner=corner, cycles=100)
|
||||||
|
(fail, error) = f.run()
|
||||||
|
self.assertTrue(fail, error)
|
||||||
|
|
||||||
|
globals.end_openram()
|
||||||
|
|
||||||
|
# instantiate a copy 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(testRunner=debugTestRunner())
|
||||||
|
|
@ -3,17 +3,17 @@
|
||||||
import sys
|
import sys
|
||||||
from gdsMill import gdsMill
|
from gdsMill import gdsMill
|
||||||
|
|
||||||
if len(sys.argv) < 3:
|
if len(sys.argv) < 4:
|
||||||
print("Script to prefix every instance and structure with the root cell name to provide unique namespace.")
|
print("Script to prefix every instance and structure with the root cell name to provide unique namespace, but skip cells that begin with the library prefix.")
|
||||||
print("Usage: {0} in.gds out.gds".format(sys.argv[0]))
|
print("Usage: {0} <library prefix> in.gds out.gds".format(sys.argv[0]))
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
gds_file = sys.argv[1]
|
gds_file = sys.argv[2]
|
||||||
gds = gdsMill.VlsiLayout()
|
gds = gdsMill.VlsiLayout()
|
||||||
reader = gdsMill.Gds2reader(gds)
|
reader = gdsMill.Gds2reader(gds)
|
||||||
reader.loadFromFile(gds_file)
|
reader.loadFromFile(gds_file)
|
||||||
|
|
||||||
gds.uniquify()
|
gds.uniquify(prefix_name=sys.argv[1])
|
||||||
|
|
||||||
writer = gdsMill.Gds2writer(gds)
|
writer = gdsMill.Gds2writer(gds)
|
||||||
writer.writeToFile(sys.argv[2])
|
writer.writeToFile(sys.argv[3])
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue