Modified og_gui_manager.py to make it accessible on devices not on the efabless platform. Changed the create project script to make the proper config directories so that the editors can be used. Modified profile.py to make the settings properly reflect the user preferences.
diff --git a/common/make_icon_from_soft.py b/common/make_icon_from_soft.py
new file mode 100644
index 0000000..b866463
--- /dev/null
+++ b/common/make_icon_from_soft.py
@@ -0,0 +1,617 @@
+#!/ef/efabless/opengalaxy/venv/bin/python3 -B
+#--------------------------------------------------------
+# make_icon_from_soft.py --
+#
+# Create an electric icon (manually) from information taken from
+# a verilog module.
+#-----------------------------------------------------------------
+
+import os
+import re
+import sys
+import json
+import datetime
+import subprocess
+
+def create_symbol(projectpath, verilogfile, project, destfile=None, debug=False, dolist=False):
+ if not os.path.exists(projectpath):
+ print('No path to project ' + projectpath)
+ return 1
+
+ if not os.path.isfile(verilogfile):
+ print('No path to verilog file ' + verilogfile)
+ return 1
+
+ if not os.path.exists(projectpath + '/elec'):
+ print('No electric subdirectory /elec/ in project.')
+ return 1
+
+ if not destfile:
+
+ delibdir = projectpath + '/elec/' + project + '.delib'
+ if not os.path.isdir(delibdir):
+ print('No electric library ' + project + '.delib in project.')
+ return 1
+
+ if os.path.isfile(delibdir + '/' + project + '.ic'):
+ print('Symbol file ' + project + '.ic exists already.')
+ print('Please remove it if you want to overwrite it.')
+ return 1
+
+ # By default, put the icon file in the project's electric library
+ destfile = projectpath + '/elec/' + project + '.delib/' + project + '.ic'
+ desthdr = projectpath + '/elec/' + project + '.delib/header'
+
+ else:
+ if os.path.isfile(destfile):
+ print('Symbol file ' + project + '.ic exists already.')
+ print('Please remove it if you want to overwrite it.')
+ return 1
+
+ destdir = os.path.split(destfile)[0]
+ desthdr = destdir + '/header'
+ if not os.path.isdir(destdir):
+ os.makedirs(destdir)
+
+ # Original verilog source can be very complicated to parse. Run through
+ # qflow's vlog2Verilog tool to get a much simplified header, which also
+ # preprocesses the verilog, handles parameters, etc.
+
+ vdir = os.path.split(verilogfile)[0]
+ vtempfile = vdir + '/vtemp.out'
+ p = subprocess.run(['/ef/apps/ocd/qflow/current/share/qflow/bin/vlog2Verilog',
+ '-p', '-o', vtempfile, verilogfile], stdout = subprocess.PIPE)
+
+ if not os.path.exists(vtempfile):
+ print('Error: Failed to create preprocessed verilog from ' + verilogfile)
+ return 1
+
+ # Okay, ready to go. Now read the verilog source file and get the list
+ # of pins.
+
+ commstr1 = '/\*.*\*/'
+ commstr2 = '//[^\n]*\n'
+ c1rex = re.compile(commstr1)
+ c2rex = re.compile(commstr2)
+
+ # Find and isolate the module and its pin list.
+ modstr = 'module[ \t]+' + project + '[ \t]*\(([^\)]+)\)[ \t\n]*;'
+ modrex = re.compile(modstr)
+
+ # End parsing on any of these tokens
+ endrex = re.compile('[ \t]*(initial|function|task|always)')
+
+ inpins = []
+ outpins = []
+ iopins = []
+ invecs = []
+ outvecs = []
+ iovecs = []
+
+ with open(vtempfile, 'r') as ifile:
+ vlines = ifile.read()
+
+ # Remove comments
+ vlines2 = c2rex.sub('\n', c1rex.sub('', vlines))
+
+ # Find and isolate the module pin list
+ modpinslines = modrex.findall(vlines2)
+
+ modpinsstart = modrex.search(vlines2)
+ if modpinsstart:
+ startc = modpinsstart.span()[0]
+ else:
+ startc = 0
+ modpinsend = endrex.search(vlines2[startc:])
+ if modpinsend:
+ endc = modpinsend.span()[0]
+ else:
+ endc = len(vlines2)
+
+ vlines2 = vlines2[startc:endc]
+
+ # Find the module (there should be only one) and get pins if in the
+ # format with input / output declarations in the module heading.
+
+ pinlist = []
+ if len(modpinslines) > 0:
+ modpins = modpinslines[0]
+ pinlist = re.sub('[\t\n]', '', modpins).split(',')
+
+ # If each pinlist entry is only one word, then look for following
+ # lines "input", "output", etc., and compile them into a similar
+ # list. Then parse each list entry.
+
+ knownreal = {}
+ knownpower = {}
+ knownground = {}
+
+ if len(pinlist) > 0 and len(pinlist[0].split()) == 1:
+
+ invecrex = re.compile('\n[ \t]*input[ \t]*\[[ \t]*([0-9]+)[ \t]*:[ \t]*([0-9]+)[ \t]*\][ \t]*([^;]+);')
+ insigrex = re.compile('\n[ \t]*input[ \t]+([^\[;]+);')
+ outvecrex = re.compile('\n[ \t]*output[ \t]*\[[ \t]*([0-9]+)[ \t]*:[ \t]*([0-9]+)[ \t]*\][ \t]*([^;]+);')
+ outsigrex = re.compile('\n[ \t]*output[ \t]+([^;\[]+);')
+ iovecrex = re.compile('\n[ \t]*inout[ \t]*\[[ \t]*([0-9]+)[ \t]*:[ \t]*([0-9]+)[ \t]*\][ \t]*([^;]+);')
+ iosigrex = re.compile('\n[ \t]*inout [ \t]+([^;\[]+);')
+
+ # Find input, output, and inout lines
+ for test in insigrex.findall(vlines2):
+ pinname = list(item.strip() for item in test.split(','))
+ inpins.extend(pinname)
+ for test in outsigrex.findall(vlines2):
+ pinname = list(item.strip() for item in test.split(','))
+ outpins.extend(pinname)
+ for test in iosigrex.findall(vlines2):
+ pinname = list(item.strip() for item in test.split(','))
+ iopins.extend(pinname)
+ for test in invecrex.finditer(vlines2):
+ tpin = test.group(3).split(',')
+ for pin in tpin:
+ pinname = pin.strip() + '[' + test.group(1) + ':' + test.group(2) + ']'
+ invecs.append(pinname)
+ for test in outvecrex.finditer(vlines2):
+ tpin = test.group(3).split(',')
+ for pin in tpin:
+ pinname = pin.strip() + '[' + test.group(1) + ':' + test.group(2) + ']'
+ outvecs.append(pinname)
+ for test in iovecrex.finditer(vlines2):
+ tpin = test.group(3).split(',')
+ for pin in tpin:
+ pinname = pin.strip() + '[' + test.group(1) + ':' + test.group(2) + ']'
+ iovecs.append(pinname)
+
+ # Apply syntax checks (to do: check for "real" above)
+ powerrec = re.compile('VDD|VCC', re.IGNORECASE)
+ groundrec = re.compile('VSS|GND|GROUND', re.IGNORECASE)
+ for pinname in inpins + outpins + iopins + invecs + outvecs + iovecs:
+ pmatch = powerrec.match(pinname)
+ gmatch = groundrec.match(pinname)
+ if pmatch:
+ knownpower[pinname] = True
+ if gmatch:
+ knownground[pinname] = True
+ else:
+
+ # Get pin lists from module pin list. These are simpler to
+ # parse, since they have to be enumerated one by one.
+
+ invecrex = re.compile('[ \t]*input[ \t]*\[[ \t]*([0-9]+)[ \t]*:[ \t]*([0-9]+)[ \t]*\][ \t]*(.+)')
+ insigrex = re.compile('[ \t]*input[ \t]+([a-zA-Z_][^ \t]+)')
+ outvecrex = re.compile('[ \t]*output[ \t]*\[[ \t]*([0-9]+)[ \t]*:[ \t]*([0-9]+)[ \t]*\][ \t]*(.+)')
+ outsigrex = re.compile('[ \t]*output[ \t]+([a-zA-Z_][^ \t]+)')
+ iovecrex = re.compile('[ \t]*inout[ \t]*\[[ \t]*([0-9]+)[ \t]*:[ \t]*([0-9]+)[ \t]*\][ \t]*(.+)')
+ iosigrex = re.compile('[ \t]*inout[ \t]+([a-zA-Z_][^ \t]+)')
+ realrec = re.compile('[ \t]+real[ \t]+')
+ logicrec = re.compile('[ \t]+logic[ \t]+')
+ wirerec = re.compile('[ \t]+wire[ \t]+')
+ powerrec = re.compile('VDD|VCC', re.IGNORECASE)
+ groundrec = re.compile('VSS|GND|GROUND', re.IGNORECASE)
+
+ for pin in pinlist:
+ # Pull out any reference to "real", "logic", or "wire" to get pin name
+ ppin = realrec.sub(' ', logicrec.sub(' ', wirerec.sub(' ', pin.strip())))
+ pinname = None
+
+ # Make syntax checks
+ rmatch = realrec.match(pin)
+ pmatch = powerrec.match(pin)
+ gmatch = groundrec.match(pin)
+
+ imatch = insigrex.match(ppin)
+ if imatch:
+ pinname = imatch.group(1)
+ inpins.append(pinname)
+ omatch = outsigrex.match(ppin)
+ if omatch:
+ pinname = omatch.group(1)
+ outpins.append(pinname)
+ bmatch = iosigrex.match(ppin)
+ if bmatch:
+ pinname = bmatch.group(1)
+ iopins.append(pinname)
+ ivmatch = invecrex.match(ppin)
+ if ivmatch:
+ pinname = ivmatch.group(3) + '[' + ivmatch.group(1) + ':' + ivmatch.group(2) + ']'
+ invecs.append(pinname)
+ ovmatch = outvecrex.match(ppin)
+ if ovmatch:
+ pinname = ovmatch.group(3) + '[' + ovmatch.group(1) + ':' + ovmatch.group(2) + ']'
+ outvecs.append(pinname)
+ bvmatch = iovecrex.match(ppin)
+ if bvmatch:
+ pinname = bvmatch.group(3) + '[' + bvmatch.group(1) + ':' + bvmatch.group(2) + ']'
+ iovecs.append(pinname)
+
+ # Apply syntax checks
+ if pinname:
+ if rmatch:
+ knownreal[pinname] = True
+ if pmatch and rmatch:
+ knownpower[pinname] = True
+ if gmatch and rmatch:
+ knownground[pinname] = True
+
+ if (os.path.exists(vtempfile)):
+ os.remove(vtempfile)
+
+ if len(inpins) + len(outpins) + len(iopins) + len(invecs) + len(outvecs) + len(iovecs) == 0:
+ print('Failure to parse pin list for module ' + project + ' out of verilog source.')
+ return 1
+
+ if debug:
+ print("Input pins of module " + project + ":")
+ for pin in inpins:
+ print(pin)
+ print("Output pins of module " + project + ":")
+ for pin in outpins:
+ print(pin)
+ print("Bidirectional pins of module " + project + ":")
+ for pin in iopins:
+ print(pin)
+
+ # If "dolist" is True, then create a list of pin records in the style used by
+ # project.json, and return the list.
+
+ if dolist == True:
+ pinlist = []
+ for pin in inpins:
+ pinrec = {}
+ pinrec["name"] = pin
+ pinrec["description"] = "(add description here)"
+ if pin in knownreal:
+ pinrec["type"] = 'signal'
+ else:
+ pinrec["type"] = 'digital'
+ pinrec["Vmin"] = "-0.5"
+ pinrec["Vmax"] = "VDD + 0.3"
+ pinrec["dir"] = "input"
+ pinlist.append(pinrec)
+ for pin in outpins:
+ pinrec = {}
+ pinrec["name"] = pin
+ pinrec["description"] = "(add description here)"
+ if pin in knownreal:
+ pinrec["type"] = 'signal'
+ else:
+ pinrec["type"] = 'digital'
+ pinrec["Vmin"] = "-0.5"
+ pinrec["Vmax"] = "VDD + 0.3"
+ pinrec["dir"] = "output"
+ pinlist.append(pinrec)
+ for pin in iopins:
+ pinrec = {}
+ pinrec["name"] = pin
+ pinrec["description"] = "(add description here)"
+ if pin in knownpower:
+ pinrec["type"] = 'power'
+ pinrec["Vmin"] = "3.6"
+ pinrec["Vmax"] = "3.0"
+ elif pin in knownground:
+ pinrec["type"] = 'ground'
+ pinrec["Vmin"] = "0"
+ pinrec["Vmax"] = "0"
+ elif pin in knownreal:
+ pinrec["type"] = 'signal'
+ pinrec["Vmin"] = "-0.5"
+ pinrec["Vmax"] = "VDD + 0.3"
+ else:
+ pinrec["type"] = 'digital'
+ pinrec["Vmin"] = "-0.5"
+ pinrec["Vmax"] = "VDD + 0.3"
+ pinrec["dir"] = "inout"
+ pinlist.append(pinrec)
+ for pin in invecs:
+ pinrec = {}
+ pinrec["name"] = pin
+ pinrec["description"] = "(add description here)"
+ if pin in knownreal:
+ pinrec["type"] = 'signal'
+ else:
+ pinrec["type"] = 'digital'
+ pinrec["dir"] = "input"
+ pinrec["Vmin"] = "-0.5"
+ pinrec["Vmax"] = "VDD + 0.3"
+ pinlist.append(pinrec)
+ for pin in outvecs:
+ pinrec = {}
+ pinrec["name"] = pin
+ pinrec["description"] = "(add description here)"
+ if pin in knownreal:
+ pinrec["type"] = 'signal'
+ else:
+ pinrec["type"] = 'digital'
+ pinrec["dir"] = "output"
+ pinrec["Vmin"] = "-0.5"
+ pinrec["Vmax"] = "VDD + 0.3"
+ pinlist.append(pinrec)
+ for pin in iovecs:
+ pinrec = {}
+ pinrec["name"] = pin
+ pinrec["description"] = "(add description here)"
+ if pin in knownpower:
+ pinrec["type"] = 'power'
+ pinrec["Vmin"] = "3.6"
+ pinrec["Vmax"] = "3.0"
+ elif pin in knownground:
+ pinrec["type"] = 'ground'
+ pinrec["Vmin"] = "0"
+ pinrec["Vmax"] = "0"
+ elif pin in knownreal:
+ pinrec["type"] = 'signal'
+ pinrec["Vmin"] = "-0.5"
+ pinrec["Vmax"] = "VDD + 0.3"
+ else:
+ pinrec["type"] = 'digital'
+ pinrec["Vmin"] = "-0.5"
+ pinrec["Vmax"] = "VDD + 0.3"
+ pinrec["dir"] = "inout"
+ pinlist.append(pinrec)
+
+ return pinlist
+
+ # Okay, we've got all the pins, now build the symbol.
+
+ leftpins = len(inpins) + len(invecs)
+ rightpins = len(outpins) + len(outvecs)
+ # Arbitrarily, bidirectional pins are put on bottom and vectors on top.
+ toppins = len(iovecs)
+ botpins = len(iopins)
+
+ height = 2 + max(leftpins, rightpins) * 10
+ width = 82 + max(toppins, botpins) * 10
+
+ # Enforce minimum height (minimum width enforced above)
+ if height < 40:
+ height = 40
+
+ # Run electric -v to get version string
+ p = subprocess.run(['/ef/apps/bin/electric', '-v'], stdout = subprocess.PIPE)
+ vstring = p.stdout.decode('utf-8').rstrip()
+
+ # Get timestamp
+ timestamp = str(int(datetime.datetime.now().strftime("%s")) * 1000)
+
+ with open(destfile, 'w') as ofile:
+ print('H' + project + '|' + vstring, file=ofile)
+ print('', file=ofile)
+ print('# Cell ' + project + ';1{ic}', file=ofile)
+ print('C' + project + ';1{ic}||artwork|' + timestamp + '|' + timestamp + '|E', file=ofile)
+ print('Ngeneric:Facet-Center|art@0||0|0||||AV', file=ofile)
+ print('NBox|art@1||0|0|' + str(width) + '|' + str(height) + '||', file=ofile)
+ pnum = 0
+
+ # Title
+ print('Ngeneric:Invisible-Pin|pin@' + str(pnum) + '||0|5|||||ART_message(BD5G5;)S' + project, file=ofile)
+
+ pnum += 1
+ # Fill in left side pins
+ px = -(width / 2)
+ py = -(height / 2) + 5
+ for pin in inpins:
+ print('Nschematic:Wire_Pin|pin@' + str(pnum) + '||' + str(px - 10) + '|' + str(py) + '|1|1||', file=ofile)
+ pnum += 1
+ print('NPin|pin@' + str(pnum) + '||' + str(px - 10) + '|' + str(py) + '|1|1||', file=ofile)
+ pnum += 1
+ print('NPin|pin@' + str(pnum) + '||' + str(px) + '|' + str(py) + '|1|1||', file=ofile)
+ pnum += 1
+ py += 10
+ for pin in invecs:
+ print('Nschematic:Bus_Pin|pin@' + str(pnum) + '||' + str(px - 10) + '|' + str(py) + '|1|1||', file=ofile)
+ pnum += 1
+ print('NPin|pin@' + str(pnum) + '||' + str(px - 10) + '|' + str(py) + '|1|1||', file=ofile)
+ pnum += 1
+ print('NPin|pin@' + str(pnum) + '||' + str(px) + '|' + str(py) + '|1|1||', file=ofile)
+ pnum += 1
+ py += 10
+
+ # Fill in right side pins
+ px = (width / 2)
+ py = -(height / 2) + 5
+ for pin in outpins:
+ print('Nschematic:Wire_Pin|pin@' + str(pnum) + '||' + str(px + 10) + '|' + str(py) + '|1|1||', file=ofile)
+ pnum += 1
+ print('NPin|pin@' + str(pnum) + '||' + str(px + 10) + '|' + str(py) + '|1|1||', file=ofile)
+ pnum += 1
+ print('NPin|pin@' + str(pnum) + '||' + str(px) + '|' + str(py) + '|1|1||', file=ofile)
+ pnum += 1
+ py += 10
+ for pin in outvecs:
+ print('Nschematic:Bus_Pin|pin@' + str(pnum) + '||' + str(px + 10) + '|' + str(py) + '|1|1||', file=ofile)
+ pnum += 1
+ print('NPin|pin@' + str(pnum) + '||' + str(px + 10) + '|' + str(py) + '|1|1||', file=ofile)
+ pnum += 1
+ print('NPin|pin@' + str(pnum) + '||' + str(px) + '|' + str(py) + '|1|1||', file=ofile)
+ pnum += 1
+ py += 10
+
+ # Fill in bottom side pins
+ py = -(height / 2)
+ px = -(width / 2) + 45
+ for pin in iopins:
+ print('Nschematic:Wire_Pin|pin@' + str(pnum) + '||' + str(px) + '|' + str(py - 10) + '|1|1||', file=ofile)
+ pnum += 1
+ print('NPin|pin@' + str(pnum) + '||' + str(px) + '|' + str(py) + '|1|1||', file=ofile)
+ pnum += 1
+ print('NPin|pin@' + str(pnum) + '||' + str(px) + '|' + str(py - 10) + '|1|1||', file=ofile)
+ pnum += 1
+ px += 10
+
+ # Fill in top side pins
+ py = (height / 2)
+ px = -(width / 2) + 45
+ for pin in iovecs:
+ print('Nschematic:Bus_Pin|pin@' + str(pnum) + '||' + str(px) + '|' + str(py + 10) + '|1|1||', file=ofile)
+ pnum += 1
+ print('NPin|pin@' + str(pnum) + '||' + str(px) + '|' + str(py) + '|1|1||', file=ofile)
+ pnum += 1
+ print('NPin|pin@' + str(pnum) + '||' + str(px) + '|' + str(py + 10) + '|1|1||', file=ofile)
+ pnum += 1
+ px += 10
+
+ # Start back at pin 1 and retain the same order when drawing wires
+ pnum = 1
+ nnum = 0
+
+ px = -(width / 2)
+ py = -(height / 2) + 5
+ for pin in inpins:
+ pnum += 1
+ print('ASolid|net@' + str(nnum) + '|||FS0|pin@' + str(pnum) + '||' + str(px - 10) + '|' + str(py) + '|pin@' + str(pnum + 1) + '||' + str(px) + '|' + str(py), file=ofile)
+ pnum += 2
+ nnum += 1
+ py += 10
+
+ for pin in invecs:
+ pnum += 1
+ print('ASolid|net@' + str(nnum) + '|||FS0|pin@' + str(pnum) + '||' + str(px - 10) + '|' + str(py) + '|pin@' + str(pnum + 1) + '||' + str(px) + '|' + str(py), file=ofile)
+ pnum += 2
+ nnum += 1
+ py += 10
+
+ px = (width / 2)
+ py = -(height / 2) + 5
+ for pin in outpins:
+ pnum += 1
+ print('ASolid|net@' + str(nnum) + '|||FS0|pin@' + str(pnum) + '||' + str(px + 10) + '|' + str(py) + '|pin@' + str(pnum + 1) + '||' + str(px) + '|' + str(py), file=ofile)
+ pnum += 2
+ nnum += 1
+ py += 10
+
+ for pin in outvecs:
+ pnum += 1
+ print('ASolid|net@' + str(nnum) + '|||FS0|pin@' + str(pnum) + '||' + str(px + 10) + '|' + str(py) + '|pin@' + str(pnum + 1) + '||' + str(px) + '|' + str(py), file=ofile)
+ pnum += 2
+ nnum += 1
+ py += 10
+
+ py = -(height / 2)
+ px = -(width / 2) + 45
+ for pin in iopins:
+ pnum += 1
+ print('ASolid|net@' + str(nnum) + '|||FS0|pin@' + str(pnum) + '||' + str(px) + '|' + str(py) + '|pin@' + str(pnum + 1) + '||' + str(px) + '|' + str(py - 10), file=ofile)
+ pnum += 2
+ nnum += 1
+ px += 10
+
+ py = (height / 2)
+ px = -(width / 2) + 45
+ for pin in iovecs:
+ pnum += 1
+ print('ASolid|net@' + str(nnum) + '|||FS0|pin@' + str(pnum) + '||' + str(px) + '|' + str(py) + '|pin@' + str(pnum + 1) + '||' + str(px) + '|' + str(py + 10), file=ofile)
+ pnum += 2
+ nnum += 1
+ px += 10
+
+ # Add the exports (which are the only nontrivial elements)
+ pnum = 1
+ for pin in inpins:
+ print('E' + pin + '||D6G4;X12.0;Y0.0;|pin@' + str(pnum) + '||I', file=ofile)
+ pnum += 3
+ for pin in invecs:
+ print('E' + pin + '||D6G4;X12.0;Y0.0;|pin@' + str(pnum) + '||I', file=ofile)
+ pnum += 3
+ for pin in outpins:
+ print('E' + pin + '||D4G4;X-12.0;Y0.0;|pin@' + str(pnum) + '||O', file=ofile)
+ pnum += 3
+ for pin in outvecs:
+ print('E' + pin + '||D4G4;X-12.0;Y0.0;|pin@' + str(pnum) + '||O', file=ofile)
+ pnum += 3
+ for pin in iopins:
+ print('E' + pin + '||D6G4;RX0.0;Y12.0;|pin@' + str(pnum) + '||B', file=ofile)
+ pnum += 3
+ for pin in iovecs:
+ print('E' + pin + '||D6G4;RRRX0.0;Y-12.0;|pin@' + str(pnum) + '||B', file=ofile)
+ pnum += 3
+
+ # X marks the spot, or at least the end.
+ print('X', file=ofile)
+
+ if not os.path.isfile(desthdr):
+ with open(desthdr, 'w') as ofile:
+ print('# header information:', file=ofile)
+ print('H' + project + '|' + vstring, file=ofile)
+ print('', file=ofile)
+ print('# Views:', file=ofile)
+ print('Vicon|ic', file=ofile)
+ print('', file=ofile)
+ print('# Tools:', file=ofile)
+ print('Ouser|DefaultTechnology()Sschematic', file=ofile)
+ print('Osimulation|VerilogUseAssign()BT', file=ofile)
+ print('C____SEARCH_FOR_CELL_FILES____', file=ofile)
+
+ return 0
+
+def usage():
+ print("make_icon_from_soft.py <project_path> [<verilog_source>] [<output_file>]")
+ print("")
+ print(" where <project_path> is the path to a standard efabless project, and")
+ print(" <verilog_source> is the path to a verilog source file.")
+ print("")
+ print(" The module name must be the same as the project's ip-name.")
+ print("")
+ print(" <verilog_source> is assumed to be in verilog/source/<ip-name>.v by")
+ print(" default if not otherwise specified.")
+ print("")
+ print(" If <output_file> is not specified, output goes in the project's")
+ print(" electric library.")
+ print("")
+
+if __name__ == '__main__':
+ arguments = []
+ options = []
+
+ for item in sys.argv[1:]:
+ if item[0] == '-':
+ options.append(item.strip('-'))
+ else:
+ arguments.append(item)
+
+ debug = True if 'debug' in options else False
+
+ numarg = len(arguments)
+ if numarg > 3 or numarg == 0:
+ usage()
+ sys.exit(0)
+
+ projectpath = arguments[0]
+
+ projdirname = os.path.split(projectpath)[1]
+ jsonfile = projectpath + '/project.json'
+ if not os.path.isfile(jsonfile):
+ # Legacy behavior is to have the JSON file name the same as the directory name.
+ jsonfile = projectpath + '/' + projdirname + '.json'
+ if not os.path.isfile(jsonfile):
+ print('Error: No project JSON file found for project ' + projdirname)
+ sys.exit(1)
+
+ project = None
+ with open(jsonfile, 'r') as ifile:
+ datatop = json.load(ifile)
+ dsheet = datatop['data-sheet']
+ project = dsheet['ip-name']
+
+ if not project:
+ print('Error: No project IP name in project JSON file.')
+ sys.exit(1)
+
+ if numarg > 1:
+ verilogfile = arguments[1]
+ else:
+ verilogfile = projectpath + '/verilog/source/' + project + '.v'
+ if not os.path.exists(verilogfile):
+ print('Error: No verilog file ' + verilogfile + ' found.')
+ print('Please specify full path as 2nd argument.')
+ sys.exit(1)
+
+ if numarg > 2:
+ destfile = arguments[2]
+ else:
+ destfile = projectpath + '/elec/' + project + '.delib/' + project + '.ic'
+ if os.path.exists(destfile):
+ print('Error: Icon file ' + destfile + ' already exists.')
+ print('Please delete any unwanted original before running this script.')
+ sys.exit(1)
+
+ result = create_symbol(projectpath, verilogfile, project, destfile, debug)
+ sys.exit(result)