Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update MLopt #346

Merged
merged 4 commits into from
Oct 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions openfasoc/MLoptimization/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ klayout
safetensors
requests
tensorboard
numpy<2
ray==2.7.1
gym==0.26.2
gymnasium==0.28.1
Expand Down
109 changes: 90 additions & 19 deletions openfasoc/MLoptimization/test.py
Original file line number Diff line number Diff line change
@@ -1,31 +1,103 @@
import numpy as np
import glayout_import
import sys

from sky130_nist_tapeout import safe_single_build_and_simulation
from sky130_nist_tapeout import opamp_parameters_serializer
from sky130_nist_tapeout import opamp_parameters_serializer, opamp_parameters_de_serializer

import yaml
from pathlib import Path
import numpy as np
from typing import Union

params = {
"diffpair_params0" : [1, 8, 1],
"diffpair_params1" : [0.5, 2.1, 0.1],
"diffpair_params2" : [1, 13, 1],
"Diffpair_bias0" : [1, 8, 1],
"Diffpair_bias1" : [1, 4.5, 0.5],
"Diffpair_bias2" : [3, 13, 1],
"pamp_hparams0" : [1, 9, 1],
"pamp_hparams1" : [0.5, 2.1, 0.1],
"pamp_hparams2" : [2, 14, 1],
"bias0" : [1, 8, 1],
"bias1" : [0.5, 2.1, 0.1],
"bias2" : [3, 18, 1],
"bias3" : [2, 4, 1],
"half_pload1": [3, 10, 1],
"half_pload3": [4, 9, 1],
"mim_cap_rows" : [1, 4, 1],
}
"diffpair_params0" : [1, 8, 1],
"diffpair_params1" : [0.5, 2.1, 0.1],
"diffpair_params2" : [1, 13, 1],
"Diffpair_bias0" : [1, 8, 1],
"Diffpair_bias1" : [1, 4.5, 0.5],
"Diffpair_bias2" : [3, 13, 1],
"pamp_hparams0" : [1, 9, 1],
"pamp_hparams1" : [0.5, 2.1, 0.1],
"pamp_hparams2" : [2, 14, 1],
"bias0" : [1, 8, 1],
"bias1" : [0.5, 2.1, 0.1],
"bias2" : [3, 18, 1],
"bias3" : [2, 4, 1],
"half_pload1": [3, 10, 1],
"half_pload3": [4, 9, 1],
"mim_cap_rows" : [1, 4, 1],
}

def get_indices_from_ranges(opamp_parameters: Union[dict, np.array]) -> np.array:
"""The RL framework works by doing design searches within a user defined range for each parameter
For example, the RL framework may be told to search diffpair widths between 1um and 8um in steps of 1um
In this case, the RL framework will only ever try to make opamps with diff pair width one of [1,2,3,4,5,6,7,8]
this is done to limit the search space
The RL result will then show an index of the result. For example, if the best opamp in a design iteration had a with of 3um,
the corresponding index for 3um is 2 (3um is at the 2nd index in the array [1,2,3,4,5,6,7,8])

The purpose of this function to convert a list of opamp parameter into a list of indices into these range arrays
returns a list of indicies

input can either be given in dictionary or np.array format
here is an example dictionary input:
{'half_diffpair_params': (-987.654321, -987.654321, -987.654321), 'diffpair_bias': (-987.654321, -987.654321, -987.654321), 'half_common_source_params': (-987.654321, -987.654321, -987.654321, -987.654321), 'half_common_source_bias': (-987.654321, -987.654321, -987.654321, -987.654321), 'output_stage_params': (-987.654321, -987.654321, -987), 'output_stage_bias': (-987, -987.654321, -987.654321), 'half_pload': (-987.654321, -987.654321, -987.654321), 'mim_cap_size': (-987.654321, -987.654321), 'mim_cap_rows': -987, 'rmult': -987}

here is an example np.array indices output:
np.array([6, 2, 7, 6, 0, 5, 7, 0, 10, 6, 5, 13, 0, 6, 4, 2])
"""
# convert to dictionary format first
if isinstance(opamp_parameters, dict):
opamp_parameter_dict = opamp_parameters
else:
opamp_parameter_dict = opamp_parameters_de_serializer(opamp_parameters)
# Function to find the closest index in the range
def closest_index(range_params, number):
start, end, step = range_params
values = np.arange(start, end, step)
idx = (np.abs(values - number)).argmin()
return idx
# loop through params and find closest indices
opamp_parameter_arr = list()
for key, val in params.items():
if key == "diffpair_params0":
opamp_parameter_arr.append(closest_index(val, opamp_parameter_dict["half_diffpair_params"][0]))
elif key == "diffpair_params1":
opamp_parameter_arr.append(closest_index(val, opamp_parameter_dict["half_diffpair_params"][1]))
elif key == "diffpair_params2":
opamp_parameter_arr.append(closest_index(val, opamp_parameter_dict["half_diffpair_params"][2]))
elif key == "Diffpair_bias0":
opamp_parameter_arr.append(closest_index(val, opamp_parameter_dict["diffpair_bias"][0]))
elif key == "Diffpair_bias1":
opamp_parameter_arr.append(closest_index(val, opamp_parameter_dict["diffpair_bias"][1]))
elif key == "Diffpair_bias2":
opamp_parameter_arr.append(closest_index(val, opamp_parameter_dict["diffpair_bias"][2]))
elif key == "pamp_hparams0":
opamp_parameter_arr.append(closest_index(val, opamp_parameter_dict["half_common_source_params"][0]))
elif key == "pamp_hparams1":
opamp_parameter_arr.append(closest_index(val, opamp_parameter_dict["half_common_source_params"][1]))
elif key == "pamp_hparams2":
opamp_parameter_arr.append(closest_index(val, opamp_parameter_dict["half_common_source_params"][2]))
elif key == "bias0":
opamp_parameter_arr.append(closest_index(val, opamp_parameter_dict["half_common_source_bias"][0]))
elif key == "bias1":
opamp_parameter_arr.append(closest_index(val, opamp_parameter_dict["half_common_source_bias"][1]))
elif key == "bias2":
opamp_parameter_arr.append(closest_index(val, opamp_parameter_dict["half_common_source_bias"][2]))
elif key == "bias3":
opamp_parameter_arr.append(closest_index(val, opamp_parameter_dict["half_common_source_bias"][3]))
elif key == "half_pload1":
opamp_parameter_arr.append(closest_index(val, opamp_parameter_dict["half_pload"][0]))
elif key == "half_pload3":
opamp_parameter_arr.append(closest_index(val, opamp_parameter_dict["half_pload"][2]))
elif key == "mim_cap_rows":
opamp_parameter_arr.append(closest_index(val, opamp_parameter_dict["mim_cap_rows"]))
else:
raise ValueError("invalid key")
# this relies on the fact that the params dict should be in order
return np.array(opamp_parameter_arr)

paramss = []
params_id = list(params.keys())

Expand All @@ -46,7 +118,6 @@
inputparam[22] = paramsss[14]
inputparam[25] = paramsss[15]


result = safe_single_build_and_simulation(inputparam, hardfail=True)

print(result)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
import sys
from os import path, rename, environ
environ['OPENBLAS_NUM_THREADS'] = '1'
from pathlib import Path
# path to glayout
sys.path.append(path.join(path.dirname(__file__), '../../'))

sys.path.append(path.join(str(Path(__file__).resolve().parents[2])))
from gdsfactory.read.import_gds import import_gds
from gdsfactory.components import text_freetype, rectangle
from glayout.flow.pdk.util.comp_utils import prec_array, movey, align_comp_to_port, prec_ref_center
from glayout.flow.pdk.util.port_utils import add_ports_perimeter, print_ports
from gdsfactory.component import Component
from glayout.flow.pdk.mappedpdk import MappedPDK
from glayout.flow.blocks.composite.opamp import opamp
try:
chetanyagoyal marked this conversation as resolved.
Show resolved Hide resolved
from glayout.flow.blocks.composite.opamp import opamp
except:
print('Regular opamp import failed! Using Fallback...')
from glayout.flow.blocks.opamp import opamp
from glayout.flow.routing.L_route import L_route
from glayout.flow.routing.straight_route import straight_route
from glayout.flow.routing.c_route import c_route
Expand Down