mirror of https://github.com/VLSIDA/OpenRAM.git
Merge branch 'dev' into tech_migration
This commit is contained in:
commit
9e8b03d6c2
|
|
@ -1012,7 +1012,7 @@ class layout():
|
|||
|
||||
|
||||
|
||||
def add_power_pin(self, name, loc, vertical=False, start_layer="m1"):
|
||||
def add_power_pin(self, name, loc, size=[1,1], vertical=False, start_layer="m1"):
|
||||
"""
|
||||
Add a single power pin from M3 down to M1 at the given center location.
|
||||
The starting layer is specified to determine which vias are needed.
|
||||
|
|
@ -1024,12 +1024,14 @@ class layout():
|
|||
|
||||
if start_layer=="m1":
|
||||
self.add_via_center(layers=self.m1_stack,
|
||||
size=size,
|
||||
offset=loc,
|
||||
directions=direction)
|
||||
|
||||
|
||||
if start_layer=="m1" or start_layer=="m2":
|
||||
via=self.add_via_center(layers=self.m2_stack,
|
||||
size=size,
|
||||
offset=loc,
|
||||
directions=direction)
|
||||
|
||||
|
|
|
|||
|
|
@ -304,6 +304,7 @@ def read_config(config_file, is_unit_test=True):
|
|||
except:
|
||||
debug.error("Unable to read configuration file: {0}".format(config_file),2)
|
||||
|
||||
OPTS.overridden = {}
|
||||
for k, v in config.__dict__.items():
|
||||
# The command line will over-ride the config file
|
||||
# except in the case of the tech name! This is because the tech name
|
||||
|
|
@ -311,6 +312,7 @@ def read_config(config_file, is_unit_test=True):
|
|||
# Note that if we re-read a config file, nothing will get read again!
|
||||
if k not in OPTS.__dict__ or k == "tech_name":
|
||||
OPTS.__dict__[k] = v
|
||||
OPTS.overridden[k] = True
|
||||
|
||||
# Massage the output path to be an absolute one
|
||||
if not OPTS.output_path.endswith('/'):
|
||||
|
|
|
|||
|
|
@ -12,63 +12,15 @@ class ModuleType():
|
|||
"""
|
||||
def __init__(self):
|
||||
self.names = {}
|
||||
self.names['contact'] = 'contact'
|
||||
self.names['precharge'] = 'precharge'
|
||||
self.names['pinv'] = 'pinv'
|
||||
self.names['dff_buf'] = 'dff_buf'
|
||||
self.names['sense_amp'] = 'sense_amp'
|
||||
self.names['bitcell'] = 'bitcell'
|
||||
self.names['port_data'] = 'port_data'
|
||||
self.names['port_address'] = 'port_address'
|
||||
self.names['replica_bitcell_array'] = 'replica_bitcell_array'
|
||||
self.names['bank_select'] = 'bank_select'
|
||||
self.names['dff'] = 'dff'
|
||||
self.names['pinvbuf'] = 'pinvbuf'
|
||||
self.names['hierarchical_predecode2x4'] = 'hierarchical_predecode2x4'
|
||||
self.names['hierarchical_predecode3x8'] = 'hierarchical_predecode3x8'
|
||||
self.names['replica_bitcell'] = 'replica_bitcell'
|
||||
self.names['dummy_bitcell'] = 'dummy_bitcell'
|
||||
self.names['bitcell'] = 'bitcell'
|
||||
self.names['pnor2'] = 'pnor2'
|
||||
self.names['pnand2'] = 'pnand2'
|
||||
self.names['precharge_array'] = 'precharge_array'
|
||||
self.names['sense_amp_array'] = 'sense_amp_array'
|
||||
self.names['column_mux_array'] = 'column_mux_array'
|
||||
self.names['write_driver_array'] = 'write_driver_array'
|
||||
self.names['write_mask_and_array'] = 'write_mask_and_array'
|
||||
self.names['pand2'] = 'pand2'
|
||||
self.names['write_driver'] = 'write_driver'
|
||||
self.names['dff_buf_array'] = 'dff_buf_array'
|
||||
self.names['pdriver'] = 'pdriver'
|
||||
self.names['pand3'] = 'pand3'
|
||||
self.names['delay_chain'] = 'delay_chain'
|
||||
self.names['decoder'] = 'decoder'
|
||||
self.names['wordline_driver'] = 'wordline_driver'
|
||||
self.names['tri_gate'] = 'tri_gate'
|
||||
self.names['tri_gate_array'] = 'tri_gate_array'
|
||||
self.names['bitcell_array'] = 'bitcell_array'
|
||||
self.names['replica_column'] = 'replica_column'
|
||||
self.names['dummy_array'] = 'dummy_array'
|
||||
self.names['single_level_column_mux_array'] = 'single_level_column_mux_array'
|
||||
self.names['single_level_column_mux'] = 'single_level_column_mux'
|
||||
self.names['sram'] = 'sram'
|
||||
self.names['ptx'] = 'ptx'
|
||||
self.names['hierarchical_decoder'] = 'hierarchical_decoder'
|
||||
self.names['pbuf'] = 'pbuf'
|
||||
self.names['control_logic'] = 'control_logic'
|
||||
self.names['bank'] = 'bank'
|
||||
self.names['pbitcell'] = 'pbitcell'
|
||||
self.names['pnand3'] = 'pnand3'
|
||||
self.names['pwrite_driver'] = 'pwrite_driver'
|
||||
self.names['ptristate_inv'] = 'ptristate_inv'
|
||||
self.names['ptristate_buf'] = 'ptristate_buf'
|
||||
|
||||
def __setitem__(self, b, c):
|
||||
self.names[b] = c
|
||||
|
||||
def is_overridden(self, b):
|
||||
return (b in self.names.keys())
|
||||
|
||||
def __getitem__(self, b):
|
||||
if b not in self.names.keys():
|
||||
raise KeyError
|
||||
|
||||
|
||||
return self.names[b]
|
||||
|
||||
|
|
|
|||
|
|
@ -271,28 +271,25 @@ class sram_base(design, verilog, lef):
|
|||
self.dff = factory.create(module_type="dff")
|
||||
|
||||
# Create the address and control flops (but not the clk)
|
||||
from dff_array import dff_array
|
||||
self.row_addr_dff = dff_array(name="row_addr_dff", rows=self.row_addr_size, columns=1)
|
||||
self.row_addr_dff = factory.create("dff_array", module_name="row_addr_dff", rows=self.row_addr_size, columns=1)
|
||||
self.add_mod(self.row_addr_dff)
|
||||
|
||||
if self.col_addr_size > 0:
|
||||
self.col_addr_dff = dff_array(name="col_addr_dff", rows=1, columns=self.col_addr_size)
|
||||
self.col_addr_dff = factory.create("dff_array", module_name="col_addr_dff", rows=1, columns=self.col_addr_size)
|
||||
self.add_mod(self.col_addr_dff)
|
||||
else:
|
||||
self.col_addr_dff = None
|
||||
|
||||
self.data_dff = dff_array(name="data_dff", rows=1, columns=self.word_size)
|
||||
self.data_dff = factory.create("dff_array", module_name="data_dff", rows=1, columns=self.word_size)
|
||||
self.add_mod(self.data_dff)
|
||||
|
||||
if self.write_size:
|
||||
self.wmask_dff = dff_array(name="wmask_dff", rows=1, columns=self.num_wmasks)
|
||||
self.wmask_dff = factory.create("dff_array", module_name="wmask_dff", rows=1, columns=self.num_wmasks)
|
||||
self.add_mod(self.wmask_dff)
|
||||
|
||||
|
||||
# Create the bank module (up to four are instantiated)
|
||||
from bank import bank
|
||||
self.bank = bank(self.sram_config,
|
||||
name="bank")
|
||||
self.bank = factory.create("bank", sram_config=self.sram_config, module_name="bank")
|
||||
self.add_mod(self.bank)
|
||||
|
||||
# Create bank decoder
|
||||
|
|
|
|||
|
|
@ -30,15 +30,16 @@ class sram_factory:
|
|||
Clear the factory instances for testing.
|
||||
"""
|
||||
self.__init__()
|
||||
|
||||
def create(self, module_type, **kwargs):
|
||||
|
||||
def get_techmodule_type(self, module_type):
|
||||
"""
|
||||
A generic function to create a module with a given module_type.
|
||||
The args are passed directly to the module constructor.
|
||||
Try to load the custom tech module type.
|
||||
"""
|
||||
overridden = False
|
||||
try:
|
||||
from tech import tech_modules
|
||||
real_module_type = tech_modules[module_type]
|
||||
overridden = tech_modules.is_overridden(module_type)
|
||||
except ImportError:
|
||||
# If they didn't define these, then don't use the option types.
|
||||
# Primarily for backward compatibility and simplicity of tech files.
|
||||
|
|
@ -46,12 +47,47 @@ class sram_factory:
|
|||
except KeyError:
|
||||
# If it wasn't a tech module type, we can ignore that too.
|
||||
real_module_type = module_type
|
||||
|
||||
return (real_module_type, overridden)
|
||||
|
||||
def get_usermodule_type(self, module_type):
|
||||
"""
|
||||
Try to load the custom user module type. If the user hasn't specified
|
||||
anything, we use the default from 'options.py'. If we cannot find anything, we
|
||||
fall back to the original 'module_type'.
|
||||
"""
|
||||
overridden = False
|
||||
if hasattr(OPTS, module_type):
|
||||
# Retrieve the name from OPTS if it exists,
|
||||
# otherwise just use the name
|
||||
real_module_type = getattr(OPTS, module_type)
|
||||
|
||||
module_type = getattr(OPTS, module_type)
|
||||
overridden = module_type in OPTS.overridden.keys()
|
||||
return (module_type, overridden)
|
||||
|
||||
def is_duplicate_name(self, name):
|
||||
for mods in self.objects.values():
|
||||
for insts in mods:
|
||||
if insts[1].name == name:
|
||||
return True
|
||||
return False
|
||||
|
||||
def create(self, module_type, module_name=None, **kwargs):
|
||||
"""
|
||||
A generic function to create a module with a given module_type.
|
||||
The args are passed directly to the module constructor.
|
||||
"""
|
||||
tech_module_type, tm_overridden = self.get_techmodule_type(module_type)
|
||||
user_module_type, um_overridden = self.get_usermodule_type(module_type)
|
||||
|
||||
# overridden user modules have priority
|
||||
if um_overridden:
|
||||
real_module_type = user_module_type
|
||||
# then overridden tech modules
|
||||
elif tm_overridden:
|
||||
real_module_type = tech_module_type
|
||||
# if nothing else works use the name generated by get_usermodule_type()
|
||||
else:
|
||||
real_module_type = user_module_type
|
||||
|
||||
# Either retrieve the already loaded module or load it
|
||||
try:
|
||||
# Load a cached version from previous usage
|
||||
|
|
@ -72,16 +108,22 @@ class sram_factory:
|
|||
if obj_kwargs == kwargs:
|
||||
return obj_item
|
||||
|
||||
# Use the default name if there are default arguments
|
||||
# This is especially for library cells so that the
|
||||
# spice and gds files can be found.
|
||||
if len(kwargs) > 0:
|
||||
# Create a unique name and increment the index
|
||||
module_name = "{0}_{1}".format(real_module_type,
|
||||
self.module_indices[real_module_type])
|
||||
self.module_indices[real_module_type] += 1
|
||||
# If no prefered module name is provided, we generate one.
|
||||
if module_name is None:
|
||||
# Use the default name if there are default arguments
|
||||
# This is especially for library cells so that the
|
||||
# spice and gds files can be found.
|
||||
if len(kwargs) > 0:
|
||||
# Create a unique name and increment the index
|
||||
module_name = "{0}_{1}".format(real_module_type,
|
||||
self.module_indices[real_module_type])
|
||||
self.module_indices[real_module_type] += 1
|
||||
else:
|
||||
module_name = real_module_type
|
||||
else:
|
||||
module_name = real_module_type
|
||||
if self.is_duplicate_name(module_name):
|
||||
raise ValueError("Modules with duplicate name are not allowed." \
|
||||
" '{}'".format(module_name))
|
||||
|
||||
# type_str = "type={}".format(real_module_type)
|
||||
# name_str = "name={}".format(module_name)
|
||||
|
|
|
|||
Loading…
Reference in New Issue