blob: 8d62db33f502331666d13f5fff1ac08501b11f02 [file] [log] [blame]
#!/bin/env python3
# text2mag.py
#
# Read a text file from standard input and write out the text as an
# array of magic cells using the sky130_ml_xx_hd library.
#
# Adapted from the script by Paul Schulz <paul@mawsonlakes.org> in
# the sky130_ml_xx_hd repository. Modified for open_pdks standard
# paths, and to take the text string as an argument in addition to
# stdin.
import getopt
import sys
import os
import subprocess
# Options
options, remainder = getopt.getopt(sys.argv[1:],
'c:p:m:kh',
['cellname',
'pdk',
'message',
'keep',
'help',
])
def usage(ofile):
print('text2mag.py <options>', file=ofile)
print('', file=ofile)
print(' Options:', file=ofile)
print(' [-c|--cellname] - Required. Cell name to use.', file=ofile)
print(' [-m|--message] - Text to convert (default: use stdin).', file=ofile)
print(' [-k|--keep] - Keep generator script', file=ofile)
print(' [-h|--help] - Display these details', file=ofile)
keep = False
message = None
cellname = None
for opt, arg in options:
if opt in ('-c', '--cellname'):
cellname = arg
elif opt in ('-m', '--message'):
message = arg
elif opt in ('-k', '--keep'):
keep = True
elif opt in ('-h', '--help'):
usage(sys.stdout)
sys.exit(0)
else:
usage(sys.stderr)
sys.exit(1)
if not cellname:
usage(sys.stderr)
print('', file=sys.stderr)
print('*** cellname required', file=sys.stderr)
sys.exit(1)
# Convert character ID to cellname
# Accepts character UTF-8 encodings
def get_cellname (ch):
"""Return name of cell used to store character data"""
prefix = 'font_'
if (ord(ch) < 0x100):
cellname = '{:02X}'.format(ord(ch))
elif (ord(ch) < 0x10000):
cellname = '{:04X}'.format(ord(ch))
elif (ord(ch) < 0x1000000):
cellname = '{:06X}'.format(ord(ch))
else:
cellname = '{:X}'.format(ord(ch))
return prefix + cellname
def write_text_generator(message, ofile):
x = 0
y = 0
baselineskip = 400
print('drc off', file=ofile)
print('snap int', file=ofile)
print('select top cell', file=ofile)
print('box position 0 0', file=ofile)
print('', file=ofile)
# NOTE: When a character is not found, substitute "?"
for char in message:
if char != '\n':
filename = get_cellname(char)
print('if {[catch {getcell ' + filename + ' child 0 0}]} {', file=ofile)
print(' getcell font_3F child 0 0', file=ofile)
print('}', file=ofile)
print('pushstack', file=ofile)
print('set bbox [property FIXED_BBOX]', file=ofile)
print('set width [expr {[lindex $bbox 2] - [lindex $bbox 0]}]', file=ofile)
print('popstack', file=ofile)
print('box move e $width', file=ofile)
else:
x = 0
y = y - baselineskip
print('box position {} {}'.format(x,y), file=ofile)
print('save ' + cellname, file=ofile)
print('quit -noprompt', file=ofile)
##############################################################################
# Take message from stdin if not specified on the command line.
if not message:
for line in sys.stdin:
message = message + line
with open('gen_message.tcl', 'w') as ofile:
write_text_generator(message, ofile)
# Run magic with the text generator script as input.
# NOTE: Assumes that a .magicrc file exists at the target and that
# it already includes the library in the search path.
mproc = subprocess.run(['magic', '-dnull', '-noconsole', 'gen_message.tcl'],
stdin = subprocess.DEVNULL, stdout = subprocess.PIPE,
stderr = subprocess.PIPE, universal_newlines = True)
if mproc.stdout:
for line in mproc.stdout.splitlines():
print(line)
if mproc.stderr:
print('Error message output from magic:')
for line in mproc.stderr.splitlines():
print(line)
if mproc.returncode != 0:
print('ERROR: Magic exited with status ' + str(mproc.returncode))
# Delete the text generator script
if not keep:
os.remove('gen_message.tcl')
sys.exit(mproc.returncode)