mirror of https://github.com/VLSIDA/OpenRAM.git
sram_factory: Give proper priority to overrides
modules overridden by the user are the highest priority, then modules overridden by the technology. If nothing is overriden, use the defaults from OPTS (if they exist) or use the requested module_type. This fixes that custom tech_modules could not be used, if they had a default in OPTS even if the latter was not overridden by the user. We don't need extra defaults in the tech_modules, as we now only use them, if they have been overridden by the tech_module. Signed-off-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
This commit is contained in:
parent
fab963701b
commit
1df16eceb6
|
|
@ -304,6 +304,7 @@ def read_config(config_file, is_unit_test=True):
|
||||||
except:
|
except:
|
||||||
debug.error("Unable to read configuration file: {0}".format(config_file),2)
|
debug.error("Unable to read configuration file: {0}".format(config_file),2)
|
||||||
|
|
||||||
|
OPTS.overridden = {}
|
||||||
for k, v in config.__dict__.items():
|
for k, v in config.__dict__.items():
|
||||||
# The command line will over-ride the config file
|
# The command line will over-ride the config file
|
||||||
# except in the case of the tech name! This is because the tech name
|
# 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!
|
# Note that if we re-read a config file, nothing will get read again!
|
||||||
if k not in OPTS.__dict__ or k == "tech_name":
|
if k not in OPTS.__dict__ or k == "tech_name":
|
||||||
OPTS.__dict__[k] = v
|
OPTS.__dict__[k] = v
|
||||||
|
OPTS.overridden[k] = True
|
||||||
|
|
||||||
# Massage the output path to be an absolute one
|
# Massage the output path to be an absolute one
|
||||||
if not OPTS.output_path.endswith('/'):
|
if not OPTS.output_path.endswith('/'):
|
||||||
|
|
|
||||||
|
|
@ -12,64 +12,15 @@ class ModuleType():
|
||||||
"""
|
"""
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.names = {}
|
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'
|
|
||||||
self.names['dff_array'] = 'dff_array'
|
|
||||||
|
|
||||||
def __setitem__(self, b, c):
|
def __setitem__(self, b, c):
|
||||||
self.names[b] = c
|
self.names[b] = c
|
||||||
|
|
||||||
|
def is_overridden(self, b):
|
||||||
|
return (b in self.names.keys())
|
||||||
|
|
||||||
def __getitem__(self, b):
|
def __getitem__(self, b):
|
||||||
if b not in self.names.keys():
|
if b not in self.names.keys():
|
||||||
raise KeyError
|
raise KeyError
|
||||||
|
|
||||||
return self.names[b]
|
return self.names[b]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,14 +31,15 @@ class sram_factory:
|
||||||
"""
|
"""
|
||||||
self.__init__()
|
self.__init__()
|
||||||
|
|
||||||
def create(self, module_type, module_name=None, **kwargs):
|
def get_techmodule_type(self, module_type):
|
||||||
"""
|
"""
|
||||||
A generic function to create a module with a given module_type.
|
Try to load the custom tech module type.
|
||||||
The args are passed directly to the module constructor.
|
|
||||||
"""
|
"""
|
||||||
|
overridden = False
|
||||||
try:
|
try:
|
||||||
from tech import tech_modules
|
from tech import tech_modules
|
||||||
real_module_type = tech_modules[module_type]
|
real_module_type = tech_modules[module_type]
|
||||||
|
overridden = tech_modules.is_overridden(module_type)
|
||||||
except ImportError:
|
except ImportError:
|
||||||
# If they didn't define these, then don't use the option types.
|
# If they didn't define these, then don't use the option types.
|
||||||
# Primarily for backward compatibility and simplicity of tech files.
|
# Primarily for backward compatibility and simplicity of tech files.
|
||||||
|
|
@ -46,11 +47,39 @@ class sram_factory:
|
||||||
except KeyError:
|
except KeyError:
|
||||||
# If it wasn't a tech module type, we can ignore that too.
|
# If it wasn't a tech module type, we can ignore that too.
|
||||||
real_module_type = module_type
|
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):
|
if hasattr(OPTS, module_type):
|
||||||
# Retrieve the name from OPTS if it exists,
|
# Retrieve the name from OPTS if it exists,
|
||||||
# otherwise just use the name
|
# 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 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
|
# Either retrieve the already loaded module or load it
|
||||||
try:
|
try:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue