OpenRAM/compiler/sram_factory.py

108 lines
4.1 KiB
Python
Raw Normal View History

# See LICENSE for licensing information.
#
2019-06-14 17:43:41 +02:00
# Copyright (c) 2016-2019 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.
#
2019-01-17 02:04:28 +01:00
from globals import OPTS
2019-10-03 01:26:02 +02:00
2019-01-17 02:04:28 +01:00
class sram_factory:
"""
This is a factory pattern to create modules for usage in an SRAM.
Since GDSII has a flat namespace, it requires modules to have unique
names if their layout differs. This module ensures that any module
with different layouts will have different names. It also ensures that
identical layouts will share the same name to reduce file size and promote
hierarchical sharing.
"""
def __init__(self):
2019-10-03 01:26:02 +02:00
# A dictionary of modules indexed by module type
2019-01-17 02:04:28 +01:00
self.modules = {}
# These are the indices to append to name to make unique object names
self.module_indices = {}
# A dictionary of instance lists indexed by module type
self.objects = {}
def reset(self):
"""
Clear the factory instances for testing.
"""
self.__init__()
def create(self, module_type, **kwargs):
"""
2019-10-03 01:26:02 +02:00
A generic function to create a module with a given module_type.
The args are passed directly to the module constructor.
2019-01-17 02:04:28 +01:00
"""
try:
from tech import tech_modules
real_module_type = tech_modules[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.
pass
2019-01-17 02:04:28 +01:00
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)
2019-01-17 02:04:28 +01:00
# Either retrieve the already loaded module or load it
try:
# Load a cached version from previous usage
mod = self.modules[real_module_type]
2019-01-17 02:04:28 +01:00
except KeyError:
# Dynamically load the module
2019-05-31 17:43:37 +02:00
import importlib
c = importlib.reload(__import__(real_module_type))
mod = getattr(c, real_module_type)
self.modules[real_module_type] = mod
self.module_indices[real_module_type] = 0
self.objects[real_module_type] = []
2019-01-17 02:04:28 +01:00
# Either retreive a previous object or create a new one
for obj in self.objects[real_module_type]:
2019-01-17 02:04:28 +01:00
(obj_kwargs, obj_item) = obj
# Must have the same dictionary exactly (conservative)
if obj_kwargs == kwargs:
return obj_item
# Use the default name if there are default arguments
2019-10-03 01:26:02 +02:00
# This is especially for library cells so that the
# spice and gds files can be found.
if len(kwargs) > 0:
2019-01-17 02:04:28 +01:00
# 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
2019-10-03 01:26:02 +02:00
# type_str = "type={}".format(real_module_type)
2019-10-03 01:26:02 +02:00
# name_str = "name={}".format(module_name)
# kwargs_str = "kwargs={}".format(str(kwargs))
# import debug
# debug.info(0, "New module:" + type_str + name_str + kwargs_str)
obj = mod(name=module_name, **kwargs)
self.objects[real_module_type].append((kwargs, obj))
2019-01-17 02:04:28 +01:00
return obj
def get_mods(self, module_type):
"""Returns list of all objects of module name's type."""
if hasattr(OPTS, module_type):
# Retrieve the name from OPTS if it exists,
# otherwise just use the input
module_type = getattr(OPTS, module_type)
try:
mod_tuples = self.objects[module_type]
2019-10-03 01:26:02 +02:00
mods = [mod for kwargs, mod in mod_tuples]
except KeyError:
mods = []
return mods
2019-10-03 01:26:02 +02:00
2019-01-17 02:04:28 +01:00
# Make a factory
factory = sram_factory()