Skip to content

Commit

Permalink
Merge pull request #323 from srpathen/main
Browse files Browse the repository at this point in the history
Adding code that trains on different LLM models and added the introduction to GLayout notebook
  • Loading branch information
msaligane authored Jul 5, 2024
2 parents 76a53c5 + 72efa96 commit f0677e8
Show file tree
Hide file tree
Showing 33 changed files with 2,825 additions and 298 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/glayout_opamp_sim.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ jobs:
pip3 install -r requirements.txt &&\
cd ./openfasoc/generators/glayout/tapeout/tapeout_and_RL/ &&\
pip3 install prettyprint prettyprinttree gdstk &&\
python3 -m pip uninstall numpy -y &&\
python3 -m pip install numpy==1.23.5 &&\
python3 test_glayout_ci.py --component opamp_parametric
" && exit_code=$? | tee -a glayout.log
if [ $? -ne 0 ]; then exit 1; fi
Expand Down
10 changes: 10 additions & 0 deletions .github/workflows/glayout_sky130.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ jobs:
cp ./.github/scripts/test_glayout_ci.py ./openfasoc/generators/glayout/. &&\
cd ./openfasoc/generators/glayout &&\
pip3 install gdsfactory==7.7.0 prettyprint prettyprinttree gdstk &&\
python3 -m pip uninstall numpy -y &&\
python3 -m pip install numpy==1.23.5 &&\
python3 test_glayout_ci.py --component opamp
" && exit_code=$? | tee -a glayout.log
if [ $? -ne 0 ]; then exit 1; fi
Expand All @@ -62,6 +64,8 @@ jobs:
cp ./.github/scripts/test_glayout_ci.py ./openfasoc/generators/glayout/. &&\
cd ./openfasoc/generators/glayout &&\
pip3 install gdsfactory==7.7.0 prettyprint prettyprinttree gdstk &&\
python3 -m pip uninstall numpy -y &&\
python3 -m pip install numpy==1.23.5 &&\
python3 test_glayout_ci.py --component pmos
" && exit_code=$? | tee -a glayout.log
if [ $? -ne 0 ]; then exit 1; fi
Expand All @@ -82,6 +86,8 @@ jobs:
cp ./.github/scripts/test_glayout_ci.py ./openfasoc/generators/glayout/. &&\
cd ./openfasoc/generators/glayout &&\
pip3 install gdsfactory==7.7.0 prettyprint prettyprinttree gdstk &&\
python3 -m pip uninstall numpy -y &&\
python3 -m pip install numpy==1.23.5 &&\
python3 test_glayout_ci.py --component nmos
" && exit_code=$? | tee -a glayout.log
if [ $? -ne 0 ]; then exit 1; fi
Expand All @@ -102,6 +108,8 @@ jobs:
cp ./.github/scripts/test_glayout_ci.py ./openfasoc/generators/glayout/. &&\
cd ./openfasoc/generators/glayout &&\
pip3 install gdsfactory==7.7.0 prettyprint prettyprinttree gdstk &&\
python3 -m pip uninstall numpy -y &&\
python3 -m pip install numpy==1.23.5 &&\
python3 test_glayout_ci.py --component diff_pair
" && exit_code=$? | tee -a glayout.log
if [ $? -ne 0 ]; then exit 1; fi
Expand All @@ -122,6 +130,8 @@ jobs:
cp ./.github/scripts/test_glayout_ci.py ./openfasoc/generators/glayout/. &&\
cd ./openfasoc/generators/glayout &&\
pip3 install gdsfactory==7.7.0 prettyprint prettyprinttree gdstk &&\
python3 -m pip uninstall numpy -y &&\
python3 -m pip install numpy==1.23.5 &&\
python3 test_glayout_ci.py --component current_mirror
" && exit_code=$? | tee -a glayout.log
if [ $? -ne 0 ]; then exit 1; fi
Expand Down
2,239 changes: 2,239 additions & 0 deletions docs/source/notebooks/glayout/GLayout_Introduction.ipynb

Large diffs are not rendered by default.

50 changes: 28 additions & 22 deletions openfasoc/generators/glayout/glayout/flow/routing/smart_route.py
Original file line number Diff line number Diff line change
Expand Up @@ -264,48 +264,54 @@ def generic_route_ab_ba_common_centroid(
# TODO: implement
name1, name2 = parse_port_name(edge1.name), parse_port_name(edge2.name)
width1 = edge1.width
# grab basename for reading ports
basename = edge1.name.rstrip("NESW").rstrip("_")
basename = basename.removesuffix("source").removesuffix("drain").removesuffix("gate").rstrip("_")
basename = basename.removesuffix("A").removesuffix("B")
def get_top_port(prtname):
return top_comp.ports[basename + prtname]
# order names so that A is first (if only one A)
if "A" in name2 and not("A" in name1):
name1, name2 = name2, name1
# same device routes (A->A or B->B) (6/15)
if check_route(name1,name2,"A_source","A_gate"):
return straight_route(pdk, top_comp.ports["A_source_E_private"],top_comp.ports["A_gate_route_con_N"],via2_alignment=("right","bottom"))
return straight_route(pdk, get_top_port("A_source_E_private"),get_top_port("A_gate_route_con_N"),via2_alignment=("right","bottom"))
if check_route(name1,name2,"A_drain","A_gate"):
return straight_route(pdk, top_comp.ports["A_drain_E_private"],top_comp.ports["A_gate_route_con_N"],via2_alignment=("right","top"))
return straight_route(pdk, get_top_port("A_drain_E_private"),get_top_port("A_gate_route_con_N"),via2_alignment=("right","top"))
if check_route(name1,name2,"A_source","A_drain"):
straight_route(pdk, top_comp.ports["br_multiplier_0_source_N"],top_comp.ports["br_multiplier_0_drain_S"],width=min(width1,1))
return straight_route(pdk, top_comp.ports["tl_multiplier_0_source_S"],top_comp.ports["tl_multiplier_0_drain_N"],width=min(width1,1))
straight_route(pdk, get_top_port("br_multiplier_0_source_N"),get_top_port("br_multiplier_0_drain_S"),width=min(width1,1))
return straight_route(pdk, get_top_port("tl_multiplier_0_source_S"),get_top_port("tl_multiplier_0_drain_N"),width=min(width1,1))
if check_route(name1,name2,"B_source","B_gate"):
return straight_route(pdk, top_comp.ports["B_source_W_private"],top_comp.ports["B_gate_route_con_N"],via2_alignment=("left","bottom"))
return straight_route(pdk, get_top_port("B_source_W_private"),get_top_port("B_gate_route_con_N"),via2_alignment=("left","bottom"))
if check_route(name1,name2,"B_drain","B_gate"):
return straight_route(pdk, top_comp.ports["B_drain_W_private"],top_comp.ports["B_gate_route_con_N"],via2_alignment=("left","top"))
return straight_route(pdk, get_top_port("B_drain_W_private"),get_top_port("B_gate_route_con_N"),via2_alignment=("left","top"))
if check_route(name1,name2,"B_source","B_drain"):
top_comp << straight_route(pdk, top_comp.ports["tr_multiplier_0_source_S"],top_comp.ports["tr_multiplier_0_drain_N"],width=min(width1,1))
return straight_route(pdk, top_comp.ports["bl_multiplier_0_source_N"],top_comp.ports["bl_multiplier_0_drain_S"],width=min(width1,1))
top_comp << straight_route(pdk, get_top_port("tr_multiplier_0_source_S"),get_top_port("tr_multiplier_0_drain_N"),width=min(width1,1))
return straight_route(pdk, get_top_port("bl_multiplier_0_source_N"),get_top_port("bl_multiplier_0_drain_S"),width=min(width1,1))
# A_src/drain->B_gate or B_src/drain->A_gate (4/15)
if check_route(name1,name2,"A_source","B_gate"):
return straight_route(pdk, top_comp.ports["A_source_W_private"],top_comp.ports["B_gate_route_con_N"],via2_alignment=("left","top"))
return straight_route(pdk, get_top_port("A_source_W_private"),get_top_port("B_gate_route_con_N"),via2_alignment=("left","top"))
if check_route(name1,name2,"A_drain","B_gate"):
return straight_route(pdk, top_comp.ports["A_drain_W_private"],top_comp.ports["B_gate_route_con_N"],via2_alignment=("left","bottom"))
return straight_route(pdk, get_top_port("A_drain_W_private"),get_top_port("B_gate_route_con_N"),via2_alignment=("left","bottom"))
if check_route(name1,name2,"B_source","A_gate"):
return straight_route(pdk, top_comp.ports["B_source_E_private"],top_comp.ports["A_gate_route_con_N"],via2_alignment=("right","top"))
return straight_route(pdk, get_top_port("B_source_E_private"),get_top_port("A_gate_route_con_N"),via2_alignment=("right","top"))
if check_route(name1,name2,"B_drain","A_gate"):
return straight_route(pdk, top_comp.ports["B_drain_E_private"],top_comp.ports["A_gate_route_con_N"],via2_alignment=("right","bottom"))
return straight_route(pdk, get_top_port("B_drain_E_private"),get_top_port("A_gate_route_con_N"),via2_alignment=("right","bottom"))
# A_src/drain->B_src or A_src/drain->B_drain (4/15)
if check_route(name1,name2,"A_source","B_source"):
return straight_route(pdk, top_comp.ports["tl_multiplier_0_source_E"],top_comp.ports["tr_multiplier_0_source_W"])
return straight_route(pdk, get_top_port("tl_multiplier_0_source_E"),get_top_port("tr_multiplier_0_source_W"))
if check_route(name1,name2,"A_drain","B_source"):
portmv1 = top_comp.ports["tl_multiplier_0_drain_E"].copy()
return straight_route(pdk, top_comp.ports["tl_multiplier_0_drain_E"],movex(portmv1,2*pdk.get_grule(pdk.layer_to_glayer(portmv1.layer))["min_separation"]))
portmv1 = get_top_port("tl_multiplier_0_drain_E").copy()
return straight_route(pdk, get_top_port("tl_multiplier_0_drain_E"),movex(portmv1,2*pdk.get_grule(pdk.layer_to_glayer(portmv1.layer))["min_separation"]))
if check_route(name1,name2,"A_source","B_drain"):
portmv1 = top_comp.ports["tr_multiplier_0_drain_W"].copy()
return straight_route(pdk, top_comp.ports["tr_multiplier_0_drain_W"],movex(portmv1,-2*pdk.get_grule(pdk.layer_to_glayer(portmv1.layer))["min_separation"]))
portmv1 = get_top_port("tr_multiplier_0_drain_W").copy()
return straight_route(pdk, get_top_port("tr_multiplier_0_drain_W"),movex(portmv1,-2*pdk.get_grule(pdk.layer_to_glayer(portmv1.layer))["min_separation"]))
if check_route(name1,name2,"A_drain","B_drain"):
portmv1 = top_comp.ports["bl_mutliplier_0_drain_N"].copy()
portmv2 = top_comp.ports["br_multiplier_0_drain_N"].copy()
top_comp << straight_route(pdk, movex(portmv1,-portmv1.width/2), top_comp.ports["tl_multiplier_0_drain_S"],width=width1)
return straight_route(pdk, movex(portmv2,portmv2.width/2),top_comp.ports["tr_multiplier_0_drain_S"])
portmv1 = get_top_port("bl_mutliplier_0_drain_N").copy()
portmv2 = get_top_port("br_multiplier_0_drain_N").copy()
top_comp << straight_route(pdk, movex(portmv1,-portmv1.width/2), get_top_port("tl_multiplier_0_drain_S"),width=width1)
return straight_route(pdk, movex(portmv2,portmv2.width/2),get_top_port("tr_multiplier_0_drain_S"))
# A_gate -> B_gate (1/15)
if check_route(name1,name2,"A_gate","B_gate"):
return straight_route(pdk,top_comp.ports["br_multiplier_0_gate_W"],top_comp.ports["bl_multiplier_0_gate_E"])
return straight_route(pdk,get_top_port("br_multiplier_0_gate_W"),get_top_port("bl_multiplier_0_gate_E"))
raise ValueError("You picked a port that smart_route with ab_ba_common_centroid does not support")
153 changes: 153 additions & 0 deletions openfasoc/generators/glayout/glayout/llm/convo_parser/Command.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
from parse_utils import parseKeyValues, parseKwarg, parseTuple, regenKeyValues, regenKwargs, regenTuple

class Command:
def __init__(self, type: str):
self.type = type
def type(self):
return self.type
def changeParamDependency(self, param, newparam):
return
def changeCompDependency(self, comp, newcomp):
return

class Import:
def __init__(self, line):
self.line = line
self.type = "import"
self.parseLine()
def parseLine(self):
words = self.line.split(" ")
self.importFile = words[1]
def regenCommand(self):
return f"import {self.importFile}"

class Param(Command):
def __init__(self, line):
self.line = line
self.type = "create"
self.parseLine()
def parseLine(self):
words = self.line.split(" ")
self.paramType = words[2]
self.name = words[5]
def regenCommand(self):
return f"create a {self.paramType} parameter called {self.name}"
def changeParamDependency(self, param, newparam):
if self.name == param:
self.name = newparam

# has parameter dependencies
class Place(Command):
def __init__(self, line):
self.line = line
self.type = "place"
self.parseLine()
def parseLine(self):
words = self.line.split(" ")
self.compType = words[2]
if self.compType == "interdigitated":
self.compType += " "+words[3]
self.compName = words[5]
else:
self.compName = words[4]
withIndex = self.line.find(" with ")
if withIndex > -1:
keyValues = self.line[self.line.find(" with ")+len(" with "):]
self.keyValues = parseKeyValues(keyValues)
else:
self.keyValues = None
def changeParamDependency(self, param, newparam):
if self.keyValues == None:
return
for key in self.keyValues:
if self.keyValues[key] == param:
self.keyValues[key] = newparam
if "kwargs" in self.keyValues:
for key in self.keyValues["kwargs"]:
if self.keyValues["kwargs"][key] == param:
self.keyValues["kwargs"][key] = newparam
def changeCompDependency(self, comp, newcomp):
if self.compName == comp:
self.compName = newcomp
def regenCommand(self):
string = f"place a {self.compType} called {self.compName}"
if self.keyValues != None:
string += " with " + regenKeyValues(self.keyValues)
return string

# Has component dependencies
class Move(Command):
def __init__(self, line):
self.line = line
self.type = "move"
self.parseLine()
def parseLine(self):
words = self.line.split(" ")
self.comp1 = words[1]
self.comp2 = words[-1]
self.moveType = " ".join(words[2:-1])
def changeCompDependency(self, comp, newcomp):
if self.comp1 == comp:
self.comp1 = newcomp
if self.comp2 == comp:
self.comp2 = newcomp
def regenCommand(self):
return f"move {self.comp1} {self.moveType} {self.comp2}"

# Has component dependencies, and might have parameter dependencies
class Route(Command):
def __init__(self, line):
self.line = line
self.type = "route"
self.parseLine()
def parseLine(self):
words = self.line.split(" ")
self.port1 = words[2]
self.port2 = words[4]
self.routeType = words[6]
withIndex = self.line.find(" with ")
if withIndex > -1:
keyValues = self.line[self.line.find(" with ")+len(" with "):]
self.keyValues = parseKeyValues(keyValues)
else:
self.keyValues = None
def changeParamDependency(self, param, newparam):
if self.keyValues == None:
return
for key in self.keyValues:
if self.keyValues[key] == param:
self.keyValues[key] = newparam
if "kwargs" in self.keyValues:
for key in self.keyValues["kwargs"]:
if self.keyValues["kwargs"][key] == param:
self.keyValues["kwargs"][key] = newparam
def changeCompDependency(self, comp, newcomp):
comp1 = ""
comp2 = ""
if self.port1.find("_") != -1:
comp1 = self.port1[:self.port1.find("_")]
if self.port2.find("_") != -1:
comp2 = self.port2[:self.port2.find("_")]
if comp1 == comp:
self.port1 = newcomp+self.port1[self.port1.find("_"):]
if comp2 == comp:
self.port2 = newcomp+self.port2[self.port2.find("_"):]
def regenCommand(self):
string = f"route between {self.port1} and {self.port2}"
if self.keyValues != None:
string += " with " + regenKeyValues(self.keyValues)
return string

class Comment(Command):
def __init__(self, line):
self.line = line
self.type = "comment"
def regenCommand(self):
return self.line

class Newline(Command):
def __init__(self):
self.type = "newline"
def regenCommand(self):
return ""

Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
from Command import Import, Param, Place, Move, Route, Comment, Newline
from validate_synthetic_data import run_all_tests, instantiate_convo
from glayout.flow.pdk.mappedpdk import MappedPDK
import tempfile

class Convo:
def __init__(self, compName):
self.compName = compName
self.commands = []
self.parameters = dict()
self.components = dict()

def addParam(self, param, type, line):
self.parameters[param]= (type, line)

def addComp(self, comp, type, line):
self.components[comp] = (type, line)

def addCommand(self, command):
self.commands.append(command)

def changeParam(self, param, newparam):
for command in self.commands:
command.changeParamDependency(param, newparam)
old = self.parameters[param]
del self.parameters[param]
self.parameters[newparam] = old

def changeComp(self, comp, newcomp):
for command in self.commands:
command.changeCompDependency(comp, newcomp)
old = self.components[comp]
del self.components[comp]
self.parameters[newcomp] = old

def unparametrize(self, param, value):
del self.commands[self.parameters[param][1]]
self.changeParam(param, value)
del self.parameters[param]

def regen(self):
str = self.compName + "\n"
for command in self.commands:
str += command.regenCommand() + "\n"
str = str[:-2]
return str

def runDRC(self, pdk: MappedPDK):
temp = tempfile.NamedTemporaryFile()
temp.write(self.regen())
component = instantiate_convo(pdk, temp.name, return_component=True)
pdk.drc_magic(component, component.name)

def run_LVSandPEX(self, pdk, netlist):
temp = tempfile.NamedTemporaryFile()
temp.write(self.regen())
component = instantiate_convo(pdk, temp.name, return_component=True)
pdk.lvs_netgen(component, component.name, copy_intermediate_files=True, netlist=netlist)

class ConvoParser:
def __init__(self, filename: str):
self.fileContents = open(filename).read()
self.readContents()

def readContents(self):
commClassMap = {"import":Import, "create":Param, "place":Place, "move": Move, "route":Route}
lines = self.fileContents.split('\n')
self.convo = Convo(lines[0])

lineIndex = 0
for line in lines[1:]:
commandType = line.split(" ")[0]

if commandType in commClassMap:
command = commClassMap[commandType](line)
self.convo.addCommand(command)
if commandType == "create":
self.convo.addParam(command.name, command.paramType, lineIndex)
elif commandType == "place":
self.convo.addComp(command.compName, command.compType, lineIndex)

elif len(line) > 0 and line[0] == "#":
self.convo.addCommand(Comment(line))

elif line == "":
self.convo.addCommand(Newline())

lineIndex += 1
Loading

0 comments on commit f0677e8

Please sign in to comment.