diff --git a/compiler/characterizer/lib.py b/compiler/characterizer/lib.py index 156481ce..3b4f465b 100644 --- a/compiler/characterizer/lib.py +++ b/compiler/characterizer/lib.py @@ -507,9 +507,11 @@ class lib: def parse_info(self,corner,lib_name): """ Copies important characterization data to datasheet.info to be added to datasheet """ if OPTS.is_unit_test: - git_id = 'AAAAAAAAAAAAAAAAAAAA' + git_id = 'FFFFFFFFFFFFFFFFFFFF' + else: with open(os.devnull, 'wb') as devnull: + # parses the mose recent git commit id - requres git is installed proc = subprocess.Popen(['git','rev-parse','HEAD'], cwd=os.path.abspath(os.environ.get("OPENRAM_HOME")) + '/', stdout=subprocess.PIPE) git_id = str(proc.stdout.read()) @@ -518,16 +520,17 @@ class lib: git_id = git_id[2:-3] except: pass - + # check if git id is valid if len(git_id) != 40: debug.warning("Failed to retrieve git id") git_id = 'Failed to retruieve' datasheet = open(OPTS.openram_temp +'/datasheet.info', 'a+') - - current_time = datetime.datetime.now() - datasheet.write("{0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10},{11},{12},{13},{14},{15},".format( - "sram_{0}_{1}_{2}".format(OPTS.word_size, OPTS.num_words, OPTS.tech_name), + + current_time = datetime.date.today() + # write static information to be parser later + datasheet.write("{0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10},{11},{12},{13},{14},{15},{16},".format( + OPTS.output_name, OPTS.num_words, OPTS.num_banks, OPTS.num_rw_ports, @@ -542,7 +545,8 @@ class lib: lib_name, OPTS.word_size, git_id, - current_time + current_time, + OPTS.analytical_delay )) # information of checks @@ -555,7 +559,9 @@ class lib: LVS = str(total_lvs_errors) datasheet.write("{0},{1},".format(DRC, LVS)) + # write area datasheet.write(str(self.sram.width * self.sram.height)+',') + # write timing information for all ports for port in self.all_ports: #DIN timings if port in self.write_ports: @@ -652,9 +658,45 @@ class lib: )) + # write power information + for port in self.all_ports: + name = '' + read_write = '' + # write dynamic power usage + if port in self.read_ports: + web_name = " & !WEb{0}".format(port) + name = "!CSb{0} & clk{0}{1}".format(port, web_name) + read_write = 'Read' + datasheet.write("{0},{1},{2},{3},".format( + "power", + name, + read_write, + + np.mean(self.char_port_results[port]["read1_power"] + self.char_port_results[port]["read0_power"])/2 + )) + + if port in self.write_ports: + web_name = " & WEb{0}".format(port) + name = "!CSb{0} & !clk{0}{1}".format(port, web_name) + read_write = 'Write' + + datasheet.write("{0},{1},{2},{3},".format( + 'power', + name, + read_write, + np.mean(self.char_port_results[port]["write1_power"] + self.char_port_results[port]["write0_power"])/2 + + )) + + # write leakage power + control_str = 'CSb0' + for i in range(1, self.total_port_num): + control_str += ' & CSb{0}'.format(i) + + datasheet.write("{0},{1},{2},".format('leak', control_str, self.char_sram_results["leakage_power"])) + datasheet.write("END\n") datasheet.close() - diff --git a/compiler/datasheet/datasheet.py b/compiler/datasheet/datasheet.py index d15733d5..4b5cb741 100644 --- a/compiler/datasheet/datasheet.py +++ b/compiler/datasheet/datasheet.py @@ -28,11 +28,12 @@ class datasheet(): # for item in self.description: # self.html += item + ',' self.html += '-->' - + # Add vlsida logo vlsi_logo = 0 with open(os.path.abspath(os.environ.get("OPENRAM_HOME")) + '/datasheet/assets/vlsi_logo.png', "rb") as image_file: vlsi_logo = base64.b64encode(image_file.read()) + # Add openram logo openram_logo = 0 with open(os.path.abspath(os.environ.get("OPENRAM_HOME")) + '/datasheet/assets/openram_logo_placeholder.png', "rb") as image_file: openram_logo = base64.b64encode(image_file.read()) @@ -49,23 +50,30 @@ class datasheet(): 'LVS errors: ' + str(self.LVS) + '

' self.html += '

' + \ 'Git commit id: ' + str(self.git_id) + '

' - + # print port table self.html += '

Ports and Configuration

' -# self.html += in_out(self.io,table_id='data').__html__().replace('<','<').replace('"','"').replace('>',">") self.html += self.io_table.to_html() - + + # print operating condidition information self.html += '

Operating Conditions

' -# self.html += operating_conditions(self.operating,table_id='data').__html__() self.html += self.operating_table.to_html() - self.html += '

Timing and Current Data

' -# self.html += timing_and_current_data(self.timing,table_id='data').__html__() + # check if analytical model is being used + self.html += '

Timing Data

' + model = '' + if self.ANALYTICAL_MODEL: + model = "analytical model: results may not be percise" + else: + model = "spice characterizer" + # display timing data + self.html += '

Using '+model+'

' self.html += self.timing_table.to_html() - + # display power data + self.html += '

Power Data

' + self.html += self.power_table.to_html() + # display corner information self.html += '

Characterization Corners

' -# self.html += characterization_corners(self.corners,table_id='data').__html__() self.html += self.corners_table.to_html() - + # display deliverables table self.html += '

Deliverables

' -# self.html += deliverables(self.dlv,table_id='data').__html__().replace('<','<').replace('"','"').replace('>',">") self.html += self.dlv_table.to_html() diff --git a/compiler/datasheet/datasheet_gen.py b/compiler/datasheet/datasheet_gen.py index 6786c7bf..1644df5f 100644 --- a/compiler/datasheet/datasheet_gen.py +++ b/compiler/datasheet/datasheet_gen.py @@ -4,7 +4,6 @@ This is a script to load data from the characterization and layout processes int a web friendly html datasheet. """ # TODO: -# include power # Diagram generation # Improve css @@ -16,19 +15,34 @@ import csv import datasheet import table_gen - -def process_name(corner): - """ - Expands the names of the characterization corner types into something human friendly - """ - if corner == "TT": - return "Typical - Typical" - if corner == "SS": - return "Slow - Slow" - if corner == "FF": - return "Fast - Fast" - else: - return "custom" +# def process_name(corner): +# """ +# Expands the names of the characterization corner types into something human friendly +# """ +# if corner == "TS": +# return "Typical - Slow" +# if corner == "TT": +# return "Typical - Typical" +# if corner == "TF": +# return "Typical - Fast" +# +# if corner == "SS": +# return "Slow - Slow" +# if corner == "ST": +# return "Slow - Typical" +# if corner == "SF": +# return "Slow - Fast" +# +# if corner == "FS": +# return "Fast - Slow" +# if corner == "FT": +# return "Fast - Typical" +# if corner == "FF": +# return "Fast - Fast" +# +# else: +# return "custom" +# def parse_characterizer_csv(f, pages): @@ -98,8 +112,12 @@ def parse_characterizer_csv(f, pages): LVS = row[col] col += 1 + ANALYTICAL_MODEL = row[col] + col += 1 + AREA = row[col] col += 1 + for sheet in pages: if sheet.name == NAME: @@ -133,7 +151,7 @@ def parse_characterizer_csv(f, pages): 1000/float(MIN_PERIOD))) except Exception: pass - + # check current .lib file produces the slowest timing results while(True): col_start = col if(row[col].startswith('DIN')): @@ -147,31 +165,31 @@ def parse_characterizer_csv(f, pages): if float(row[col+2]) > float(item[2]): item[2] = row[col+2] - col += 2 + col += 2 - elif item[0].endswith('setup falling'): + if item[0].endswith('setup falling'): if float(row[col+1]) < float(item[1]): item[1] = row[col+1] if float(row[col+2]) > float(item[2]): item[2] = row[col+2] - col += 2 + col += 2 - elif item[0].endswith('hold rising'): + if item[0].endswith('hold rising'): if float(row[col+1]) < float(item[1]): item[1] = row[col+1] if float(row[col+2]) > float(item[2]): item[2] = row[col+2] - col += 2 + col += 2 - elif item[0].endswith('hold falling'): + if item[0].endswith('hold falling'): if float(row[col+1]) < float(item[1]): item[1] = row[col+1] if float(row[col+2]) > float(item[2]): item[2] = row[col+2] - col += 2 + col += 2 col += 1 @@ -186,31 +204,31 @@ def parse_characterizer_csv(f, pages): if float(row[col+2]) > float(item[2]): item[2] = row[col+2] - col += 2 + col += 2 - elif item[0].endswith('cell fall'): + if item[0].endswith('cell fall'): if float(row[col+1]) < float(item[1]): item[1] = row[col+1] if float(row[col+2]) > float(item[2]): item[2] = row[col+2] - col += 2 + col += 2 - elif item[0].endswith('rise transition'): + if item[0].endswith('rise transition'): if float(row[col+1]) < float(item[1]): item[1] = row[col+1] if float(row[col+2]) > float(item[2]): item[2] = row[col+2] - col += 2 + col += 2 - elif item[0].endswith('fall transition'): + if item[0].endswith('fall transition'): if float(row[col+1]) < float(item[1]): item[1] = row[col+1] if float(row[col+2]) > float(item[2]): item[2] = row[col+2] - col += 2 + col += 2 col += 1 @@ -225,31 +243,31 @@ def parse_characterizer_csv(f, pages): if float(row[col+2]) > float(item[2]): item[2] = row[col+2] - col += 2 + col += 2 - elif item[0].endswith('setup falling'): + if item[0].endswith('setup falling'): if float(row[col+1]) < float(item[1]): item[1] = row[col+1] if float(row[col+2]) > float(item[2]): item[2] = row[col+2] - col += 2 + col += 2 - elif item[0].endswith('hold rising'): + if item[0].endswith('hold rising'): if float(row[col+1]) < float(item[1]): item[1] = row[col+1] if float(row[col+2]) > float(item[2]): item[2] = row[col+2] - col += 2 + col += 2 - elif item[0].endswith('hold falling'): + if item[0].endswith('hold falling'): if float(row[col+1]) < float(item[1]): item[1] = row[col+1] if float(row[col+2]) > float(item[2]): item[2] = row[col+2] - col += 2 + col += 2 col += 1 @@ -264,31 +282,31 @@ def parse_characterizer_csv(f, pages): if float(row[col+2]) > float(item[2]): item[2] = row[col+2] - col += 2 + col += 2 - elif item[0].endswith('setup falling'): + if item[0].endswith('setup falling'): if float(row[col+1]) < float(item[1]): item[1] = row[col+1] if float(row[col+2]) > float(item[2]): item[2] = row[col+2] - col += 2 + col += 2 - elif item[0].endswith('hold rising'): + if item[0].endswith('hold rising'): if float(row[col+1]) < float(item[1]): item[1] = row[col+1] if float(row[col+2]) > float(item[2]): item[2] = row[col+2] - col += 2 + col += 2 - elif item[0].endswith('hold falling'): + if item[0].endswith('hold falling'): if float(row[col+1]) < float(item[1]): item[1] = row[col+1] if float(row[col+2]) > float(item[2]): item[2] = row[col+2] - col += 2 + col += 2 col += 1 @@ -303,31 +321,31 @@ def parse_characterizer_csv(f, pages): if float(row[col+2]) > float(item[2]): item[2] = row[col+2] - col += 2 + col += 2 - elif item[0].endswith('setup falling'): + if item[0].endswith('setup falling'): if float(row[col+1]) < float(item[1]): item[1] = row[col+1] if float(row[col+2]) > float(item[2]): item[2] = row[col+2] - col += 2 + col += 2 - elif item[0].endswith('hold rising'): + if item[0].endswith('hold rising'): if float(row[col+1]) < float(item[1]): item[1] = row[col+1] if float(row[col+2]) > float(item[2]): item[2] = row[col+2] - col += 2 + col += 2 - elif item[0].endswith('hold falling'): + if item[0].endswith('hold falling'): if float(row[col+1]) < float(item[1]): item[1] = row[col+1] if float(row[col+2]) > float(item[2]): item[2] = row[col+2] - col += 2 + col += 2 col += 1 @@ -336,8 +354,36 @@ def parse_characterizer_csv(f, pages): sheet.description.append(str(element)) break - new_sheet.corners_table.add_row([PROC, process_name( - PROC), VOLT, TEMP, LIB_NAME.replace(OUT_DIR, '').replace(NAME, '')]) + #check if new power is worse the previous + while(True): + col_start = col + if row[col] == 'power': + for item in sheet.power_table.rows: + if item[0].startswith(row[col+1]): + if item[2].startswith('{0} Rising'.format(row[col+2])): + if float(item[2]) < float(row[col+3]): + item[2] = row[col+3] + if item[2].startswith('{0} Falling'.format(row[col+2])): + if float(item[2]) < float(row[col+3]): + item[2] = row[col+3] + col += 4 + else: + break + # check if new leakge is worse the previous + while(True): + col_start = col + if row[col] == 'leak': + for item in sheet.power_table.rows: + if item[0].startswith(row[col+1]): + if float(item[2]) < float(row[col+2]): + item[2] = row[col+2] + col += 3 + + else: + break + # add new corner information + new_sheet.corners_table.add_row( + [PROC, VOLT, TEMP, LIB_NAME.replace(OUT_DIR, '').replace(NAME, '')]) new_sheet.dlv_table.add_row( ['.lib', 'Synthesis models', '{1}'.format(LIB_NAME, LIB_NAME.replace(OUT_DIR, ''))]) @@ -351,14 +397,15 @@ def parse_characterizer_csv(f, pages): new_sheet.time = DATETIME new_sheet.DRC = DRC new_sheet.LVS = LVS + new_sheet.ANALYTICAL_MODEL = ANALYTICAL_MODEL new_sheet.description = [NAME, NUM_WORDS, NUM_BANKS, NUM_RW_PORTS, NUM_W_PORTS, NUM_R_PORTS, TECH_NAME, MIN_PERIOD, WORD_SIZE, ORIGIN_ID, DATETIME] new_sheet.corners_table = table_gen.table_gen("corners") new_sheet.corners_table.add_row( - ['Corner Name', 'Process', 'Power Supply', 'Temperature', 'Library Name Suffix']) - new_sheet.corners_table.add_row([PROC, process_name( - PROC), VOLT, TEMP, LIB_NAME.replace(OUT_DIR, '').replace(NAME, '')]) + ['Transistor Type', 'Power Supply', 'Temperature', 'Corner Name']) + new_sheet.corners_table.add_row( + [PROC, VOLT, TEMP, LIB_NAME.replace(OUT_DIR, '').replace(NAME, '')]) new_sheet.operating_table = table_gen.table_gen( "operating_table") new_sheet.operating_table.add_row( @@ -375,9 +422,13 @@ def parse_characterizer_csv(f, pages): # failed to provide non-zero MIN_PERIOD new_sheet.operating_table.add_row( ['Operating Frequency (F)', '', '', "not available in netlist only", 'MHz']) + new_sheet.power_table = table_gen.table_gen("power") + new_sheet.power_table.add_row( + ['Pins', 'Mode', 'Power', 'Units']) new_sheet.timing_table = table_gen.table_gen("timing") new_sheet.timing_table.add_row( ['Parameter', 'Min', 'Max', 'Units']) + # parse initial timing information while(True): col_start = col if(row[col].startswith('DIN')): @@ -504,6 +555,32 @@ def parse_characterizer_csv(f, pages): for element in row[col_start:col-1]: sheet.description.append(str(element)) break + # parse initial power and leakage information + while(True): + start = col + if(row[col].startswith('power')): + new_sheet.power_table.add_row([row[col+1], + '{0} Rising'.format( + row[col+2]), + row[col+3][0:6], + 'mW'] + ) + new_sheet.power_table.add_row([row[col+1], + '{0} Falling'.format( + row[col+2]), + row[col+3][0:6], + 'mW'] + ) + + col += 4 + + elif(row[col].startswith('leak')): + new_sheet.power_table.add_row( + [row[col+1], 'leakage', row[col+2], 'mW']) + col += 3 + + else: + break new_sheet.dlv_table = table_gen.table_gen("dlv") new_sheet.dlv_table.add_row(['Type', 'Description', 'Link']) @@ -537,12 +614,13 @@ def parse_characterizer_csv(f, pages): new_sheet.io_table.add_row(['NUM_RW_PORTS', NUM_RW_PORTS]) new_sheet.io_table.add_row(['NUM_R_PORTS', NUM_R_PORTS]) new_sheet.io_table.add_row(['NUM_W_PORTS', NUM_W_PORTS]) - new_sheet.io_table.add_row(['Area', AREA]) + new_sheet.io_table.add_row( + ['Area (µm2)', AREA]) class datasheet_gen(): def datasheet_write(name): - + """writes the datasheet to a file""" in_dir = OPTS.openram_temp if not (os.path.isdir(in_dir)): diff --git a/compiler/datasheet/table_gen.py b/compiler/datasheet/table_gen.py index 18590739..8f94e896 100644 --- a/compiler/datasheet/table_gen.py +++ b/compiler/datasheet/table_gen.py @@ -1,24 +1,29 @@ class table_gen: - def __init__(self,name): + """small library of functions to generate the html tables""" + + def __init__(self, name): self.name = name self.rows = [] self.table_id = 'data' - def add_row(self,row): + def add_row(self, row): + """add a row to table_gen object""" self.rows.append(row) def gen_table_head(self): + """generate html table header""" html = '' html += '' html += '' for col in self.rows[0]: - html += '' + str(col) + '' + html += '' + str(col) + '' html += '' html += '' return html def gen_table_body(self): + """generate html body (used after gen_table_head)""" html = '' html += '' @@ -31,13 +36,13 @@ class table_gen: html += '' html += '' return html - + def to_html(self): - + """writes table_gen object to inline html""" html = '' html += '' html += self.gen_table_head() html += self.gen_table_body() html += '
' - + return html diff --git a/compiler/datasheet/wavedrom.py b/compiler/datasheet/wavedrom.py deleted file mode 100644 index e8c68c56..00000000 --- a/compiler/datasheet/wavedrom.py +++ /dev/null @@ -1,827 +0,0 @@ -#!/usr/bin/python -# The MIT License (MIT) -# -# Copyright (c) 2011-2016 Aliaksei Chapyzhenka -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. -# -# Translated to Python from original file: -# https://github.com/drom/wavedrom/blob/master/src/WaveDrom.js -# - -import sys -import json -import math -import waveskin - -font_width = 7 - -lane = { - "xs" : 20, # tmpgraphlane0.width - "ys" : 20, # tmpgraphlane0.height - "xg" : 120, # tmpgraphlane0.x - "yg" : 0, # head gap - "yh0" : 0, # head gap title - "yh1" : 0, # head gap - "yf0" : 0, # foot gap - "yf1" : 0, # foot gap - "y0" : 5, # tmpgraphlane0.y - "yo" : 30, # tmpgraphlane1.y - y0 - "tgo" : -10, # tmptextlane0.x - xg - "ym" : 15, # tmptextlane0.y - y0 - "xlabel" : 6, # tmptextlabel.x - xg - "xmax" : 1, - "scale" : 1, - "head" : {}, - "foot" : {} -} - -def genBrick (texts, extra, times) : - - R = [] - if len( texts ) == 4 : - for j in range( times ): - - R.append(texts[0]) - - for i in range ( extra ): - R.append(texts[1]) - - R.append(texts[2]) - for i in range ( extra ): - R.append(texts[3]) - - return R - - if len( texts ) == 1 : - texts.append(texts[0]) - - R.append(texts[0]) - for i in range (times * (2 * (extra + 1)) - 1) : - R.append(texts[1]) - return R - -def genFirstWaveBrick (text, extra, times) : - - pattern = { - 'p': ['pclk', '111', 'nclk', '000'], - 'n': ['nclk', '000', 'pclk', '111'], - 'P': ['Pclk', '111', 'nclk', '000'], - 'N': ['Nclk', '000', 'pclk', '111'], - 'l': ['000'], - 'L': ['000'], - '0': ['000'], - 'h': ['111'], - 'H': ['111'], - '1': ['111'], - '=': ['vvv-2'], - '2': ['vvv-2'], - '3': ['vvv-3'], - '4': ['vvv-4'], - '5': ['vvv-5'], - 'd': ['ddd'], - 'u': ['uuu'], - 'z': ['zzz'] - } - - return genBrick( pattern.get( text, ['xxx'] ) , extra, times ); - -def genWaveBrick (text, extra, times) : - - x1 = {'p':'pclk', 'n':'nclk', 'P':'Pclk', 'N':'Nclk', 'h':'pclk', 'l':'nclk', 'H':'Pclk', 'L':'Nclk'} - x2 = {'0':'0', '1':'1', 'x':'x', 'd':'d', 'u':'u', 'z':'z', '=':'v', '2':'v', '3':'v', '4':'v', '5':'v' } - x3 = {'0': '', '1': '', 'x': '', 'd': '', 'u': '', 'z': '', '=':'-2', '2':'-2', '3':'-3', '4':'-4', '5':'-5'} - y1 = { - 'p':'0', 'n':'1', - 'P':'0', 'N':'1', - 'h':'1', 'l':'0', - 'H':'1', 'L':'0', - '0':'0', '1':'1', 'x':'x', 'd':'d', 'u':'u', 'z':'z', '=':'v', '2':'v', '3':'v', '4':'v', '5':'v'} - - y2 = { - 'p': '', 'n': '', - 'P': '', 'N': '', - 'h': '', 'l': '', - 'H': '', 'L': '', - '0': '', '1': '', 'x': '', 'd': '', 'u': '', 'z': '', '=':'-2', '2':'-2', '3':'-3', '4':'-4', '5':'-5'} - - x4 = { - 'p': '111', 'n': '000', - 'P': '111', 'N': '000', - 'h': '111', 'l': '000', - 'H': '111', 'L': '000', - '0': '000', '1': '111', 'x': 'xxx', 'd': 'ddd', 'u': 'uuu', 'z': 'zzz', - '=': 'vvv-2', '2': 'vvv-2', '3': 'vvv-3', '4': 'vvv-4', '5': 'vvv-5'} - - x5 = {'p':'nclk', 'n':'pclk', 'P':'nclk', 'N':'pclk'} - x6 = {'p': '000', 'n': '111', 'P': '000', 'N': '111'} - xclude = {'hp':'111', 'Hp':'111', 'ln': '000', 'Ln': '000', 'nh':'111', 'Nh':'111', 'pl': '000', 'Pl':'000'} - - #atext = text.split() - atext = text - - tmp0 = x4.get(atext[1]) - tmp1 = x1.get(atext[1]) - if tmp1 == None : - tmp2 = x2.get(atext[1]) - if tmp2 == None : - # unknown - return genBrick(['xxx'], extra, times) - else : - tmp3 = y1.get(atext[0]) - if tmp3 == None : - # unknown - return genBrick(['xxx'], extra, times) - - # soft curves - return genBrick([tmp3 + 'm' + tmp2 + y2[atext[0]] + x3[atext[1]], tmp0], extra, times) - - else : - tmp4 = xclude.get(text) - if tmp4 != None : - tmp1 = tmp4 - - # sharp curves - tmp2 = x5.get(atext[1]) - if tmp2 == None : - # hlHL - return genBrick([tmp1, tmp0], extra, times) - else : - # pnPN - return genBrick([tmp1, tmp0, tmp2, x6[atext[1]]], extra, times) - -def parseWaveLane (text, extra) : - - R = [] - Stack = text - Next = Stack[0] - Stack = Stack[1:] - - Repeats = 1 - while len(Stack) and ( Stack[0] == '.' or Stack[0] == '|' ): # repeaters parser - Stack=Stack[1:] - Repeats += 1 - - R.extend(genFirstWaveBrick(Next, extra, Repeats)) - - while len(Stack) : - Top = Next - Next = Stack[0] - Stack = Stack[1:] - Repeats = 1 - while len(Stack) and ( Stack[0] == '.' or Stack[0] == '|' ) : # repeaters parser - Stack=Stack[1:] - Repeats += 1 - R.extend(genWaveBrick((Top + Next), extra, Repeats)) - - for i in range( lane['phase'] ): - R = R[1:] - return R - -def parseWaveLanes (sig) : - - def data_extract (e) : - tmp = e.get('data') - if tmp == None : return None - if is_type_str (tmp) : tmp=tmp.split() - return tmp - - content = [] - for sigx in sig : - lane['period'] = sigx.get('period',1) - lane['phase'] = int( sigx.get('phase',0 ) * 2 ) - sub_content=[] - sub_content.append( [sigx.get('name',' '), sigx.get('phase',0 ) ] ) - sub_content.append( parseWaveLane( sigx['wave'], int(lane['period'] * lane['hscale'] - 1 ) ) if sigx.get('wave') else None ) - sub_content.append( data_extract(sigx) ) - content.append(sub_content) - - return content - -def findLaneMarkers (lanetext) : - - lcount = 0 - gcount = 0 - ret = [] - for i in range( len( lanetext ) ) : - if lanetext[i] == 'vvv-2' or lanetext[i] == 'vvv-3' or lanetext[i] == 'vvv-4' or lanetext[i] == 'vvv-5' : - lcount += 1 - else : - if lcount !=0 : - ret.append(gcount - ((lcount + 1) / 2)) - lcount = 0 - - gcount += 1 - - if lcount != 0 : - ret.append(gcount - ((lcount + 1) / 2)) - - return ret - -def renderWaveLane (root, content, index) : - - xmax = 0 - xgmax = 0 - glengths = [] - svgns = 'http://www.w3.org/2000/svg' - xlinkns = 'http://www.w3.org/1999/xlink' - xmlns = 'http://www.w3.org/XML/1998/namespace' - for j in range( len(content) ): - name = content[j][0][0] - if name : # check name - g = [ - 'g', - { - 'id': 'wavelane_' + str(j) + '_' + str(index), - 'transform': 'translate(0,' + str(lane['y0'] + j * lane['yo']) + ')' - } - ] - root.append(g) - title = [ - 'text', - { - 'x': lane['tgo'], - 'y': lane['ym'], - 'class': 'info', - 'text-anchor': 'end', - 'xml:space': 'preserve' - }, - ['tspan', name] - ] - g.append(title) - - glengths.append( len(name) * font_width + font_width ) - - xoffset = content[j][0][1] - xoffset = math.ceil(2 * xoffset) - 2 * xoffset if xoffset > 0 else -2 * xoffset - gg = [ - 'g', - { - 'id': 'wavelane_draw_' + str(j) + '_' + str(index), - 'transform': 'translate(' + str( xoffset * lane['xs'] ) + ', 0)' - } - ] - g.append(gg) - - if content[j][1] : - for i in range( len(content[j][1]) ) : - b = [ - 'use', - { - #'id': 'use_' + str(i) + '_' + str(j) + '_' + str(index), - 'xmlns:xlink':xlinkns, - 'xlink:href': '#' + str( content[j][1][i] ), - 'transform': 'translate(' + str(i * lane['xs']) + ')' - } - ] - gg.append(b) - - if content[j][2] and len(content[j][2]) : - labels = findLaneMarkers(content[j][1]) - if len(labels) != 0 : - for k in range( len(labels) ) : - if content[j][2] and k < len(content[j][2]) : - title = [ - 'text', - { - 'x': int(labels[k]) * lane['xs'] + lane['xlabel'], - 'y': lane['ym'], - 'text-anchor': 'middle', - 'xml:space': 'preserve' - }, - ['tspan',content[j][2][k]] - ] - gg.append(title) - - - if len(content[j][1]) > xmax : - xmax = len(content[j][1]) - - lane['xmax'] = xmax - lane['xg'] = xgmax + 20 - return glengths - -def renderMarks (root, content, index) : - - def captext ( g, cxt, anchor, y ) : - - if cxt.get(anchor) and cxt[anchor].get('text') : - tmark = [ - 'text', - { - 'x': float( cxt['xmax'] ) * float( cxt['xs'] ) / 2, - 'y': y, - 'text-anchor': 'middle', - 'fill': '#000', - 'xml:space': 'preserve' - }, cxt[anchor]['text'] - ] - g.append(tmark) - - def ticktock ( g, cxt, ref1, ref2, x, dx, y, length ) : - L = [] - - if cxt.get(ref1) == None or cxt[ref1].get(ref2) == None : - return - - val = cxt[ref1][ref2] - if is_type_str( val ) : - val = val.split() - elif type( val ) is int : - offset = val - val = [] - for i in range ( length ) : - val.append(i + offset) - - if type( val ) is list : - if len( val ) == 0 : - return - elif len( val ) == 1 : - offset = val[0] - if is_type_str(offset) : - L = val - else : - for i in range ( length ) : - L[i] = i + offset - - elif len( val ) == 2: - offset = int(val[0]) - step = int(val[1]) - tmp = val[1].split('.') - if len( tmp ) == 2 : - dp = len( tmp[1] ) - - if is_type_str(offset) or is_type_str(step) : - L = val - else : - offset = step * offset - for i in range( length ) : - L[i] = "{0:.",dp,"f}".format(step * i + offset) - - else : - L = val - - else : - return - - for i in range( length ) : - tmp = L[i] - tmark = [ - 'text', - { - 'x': i * dx + x, - 'y': y, - 'text-anchor': 'middle', - 'class': 'muted', - 'xml:space': 'preserve' - }, str(tmp) - ] - g.append(tmark) - - mstep = 2 * int(lane['hscale']) - mmstep = mstep * lane['xs'] - marks = int( lane['xmax'] / mstep ) - gy = len( content ) * int(lane['yo']) - - g = ['g', {'id': 'gmarks_' + str(index)}] - root.insert(0,g) - - for i in range( marks + 1): - gg = [ - 'path', - { - 'id': 'gmark_' + str(i) + '_' + str(index), - 'd': 'm ' + str(i * mmstep) + ',' + '0' + ' 0,' + str(gy), - 'style': 'stroke:#888;stroke-width:0.5;stroke-dasharray:1,3' - } - ] - g.append( gg ) - - captext(g, lane, 'head', -33 if lane['yh0'] else -13 ) - captext(g, lane, 'foot', gy + ( 45 if lane['yf0'] else 25 ) ) - - ticktock( g, lane, 'head', 'tick', 0, mmstep, -5, marks + 1) - ticktock( g, lane, 'head', 'tock', mmstep / 2, mmstep, -5, marks) - ticktock( g, lane, 'foot', 'tick', 0, mmstep, gy + 15, marks + 1) - ticktock( g, lane, 'foot', 'tock', mmstep / 2, mmstep, gy + 15, marks) - -def renderArcs (root, source, index, top) : - - Stack = [] - Edge = {'words': [], 'frm': 0, 'shape': '', 'to': 0, 'label': ''} - Events = {} - svgns = 'http://www.w3.org/2000/svg' - xmlns = 'http://www.w3.org/XML/1998/namespace' - - if source : - for i in range (len (source) ) : - lane['period'] = source[i].get('period',1) - lane['phase'] = int( source[i].get('phase',0 ) * 2 ) - text = source[i].get('node') - if text: - Stack = text - pos = 0 - while len( Stack ) : - eventname = Stack[0] - Stack=Stack[1:] - if eventname != '.' : - Events[eventname] = { - 'x' : str( int( float( lane['xs'] ) * (2 * pos * lane['period'] * lane['hscale'] - lane['phase'] ) + float( lane['xlabel'] ) ) ), - 'y' : str( int( i * lane['yo'] + lane['y0'] + float( lane['ys'] ) * 0.5 ) ) - } - pos += 1 - - gg = [ 'g', { 'id' : 'wavearcs_' + str( index ) } ] - root.append(gg) - - if top.get('edge') : - for i in range( len ( top['edge'] ) ) : - Edge['words'] = top['edge'][i].split() - Edge['label'] = top['edge'][i][len(Edge['words'][0]):] - Edge['label'] = Edge['label'][1:] - Edge['frm'] = Edge['words'][0][0] - Edge['to'] = Edge['words'][0][-1] - Edge['shape'] = Edge['words'][0][1:-1] - frm = Events[Edge['frm']] - to = Events[Edge['to']] - gmark = [ - 'path', - { - 'id': 'gmark_' + Edge['frm'] + '_' + Edge['to'], - 'd': 'M ' + frm['x'] + ',' + frm['y'] + ' ' + to['x'] + ',' + to['y'], - 'style': 'fill:none;stroke:#00F;stroke-width:1' - } - ] - gg.append(gmark) - dx = float( to['x'] ) - float( frm['x'] ) - dy = float( to['y'] ) - float( frm['y'] ) - lx = (float(frm['x']) + float(to['x'])) / 2 - ly = (float(frm['y']) + float(to['y'])) / 2 - pattern = { - '~' : {'d': 'M ' + frm['x'] + ',' + frm['y'] + ' c ' + str(0.7 * dx) + ', 0 ' + str(0.3 * dx) + ', ' + str(dy) + ' ' + str(dx) + ', ' + str(dy) }, - '-~' : {'d': 'M ' + frm['x'] + ',' + frm['y'] + ' c ' + str(0.7 * dx) + ', 0 ' + str(dx) + ', ' + str(dy) + ' ' + str(dx) + ', ' + str(dy) }, - '~-' : {'d': 'M ' + frm['x'] + ',' + frm['y'] + ' c ' + '0' + ', 0 ' + str(0.3 * dx) + ', ' + str(dy) + ' ' + str(dx) + ', ' + str(dy) }, - '-|' : {'d': 'm ' + frm['x'] + ',' + frm['y'] + ' ' + str(dx) + ',0 0,' + str(dy)}, - '|-' : {'d': 'm ' + frm['x'] + ',' + frm['y'] + ' 0,' + str(dy) + ' ' + str(dx) + ',0'}, - '-|-' : {'d': 'm ' + frm['x'] + ',' + frm['y'] + ' ' + str(dx / 2) + ',0 0,' + str(dy) + ' ' + str(dx / 2) + ',0'}, - '->' : {'style': 'marker-end:url(#arrowhead);stroke:#0041c4;stroke-width:1;fill:none'}, - '~>' : {'style': 'marker-end:url(#arrowhead);stroke:#0041c4;stroke-width:1;fill:none', 'd': 'M ' + frm['x'] + ',' + frm['y'] + ' ' + 'c ' + str(0.7 * dx) + ', 0 ' + str(0.3 * dx) + ', ' + str(dy) + ' ' + str(dx) + ', ' + str(dy)}, - '-~>' : {'style': 'marker-end:url(#arrowhead);stroke:#0041c4;stroke-width:1;fill:none', 'd': 'M ' + frm['x'] + ',' + frm['y'] + ' ' + 'c ' + str(0.7 * dx) + ', 0 ' + str(dx) + ', ' + str(dy) + ' ' + str(dx) + ', ' + str(dy)}, - '~->' : {'style': 'marker-end:url(#arrowhead);stroke:#0041c4;stroke-width:1;fill:none', 'd': 'M ' + frm['x'] + ',' + frm['y'] + ' ' + 'c ' + '0' + ', 0 ' + str(0.3 * dx) + ', ' + str(dy) + ' ' + str(dx) + ', ' + str(dy)}, - '-|>' : {'style': 'marker-end:url(#arrowhead);stroke:#0041c4;stroke-width:1;fill:none', 'd': 'm ' + frm['x'] + ',' + frm['y'] + ' ' + str(dx) + ',0 0,' + str(dy)}, - '|->' : {'style': 'marker-end:url(#arrowhead);stroke:#0041c4;stroke-width:1;fill:none', 'd': 'm ' + frm['x'] + ',' + frm['y'] + ' 0,' + str(dy) + ' ' + str(dx) + ',0'}, - '-|->' : {'style': 'marker-end:url(#arrowhead);stroke:#0041c4;stroke-width:1;fill:none', 'd': 'm ' + frm['x'] + ',' + frm['y'] + ' ' + str(dx / 2) + ',0 0,' + str(dy) + ' ' + str(dx / 2) + ',0'}, - '<->' : {'style': 'marker-end:url(#arrowhead);marker-start:url(#arrowtail);stroke:#0041c4;stroke-width:1;fill:none'}, - '<~>' : {'style': 'marker-end:url(#arrowhead);marker-start:url(#arrowtail);stroke:#0041c4;stroke-width:1;fill:none','d': 'M ' + frm['x'] + ',' + frm['y'] + ' ' + 'c ' + str(0.7 * dx) + ', 0 ' + str(0.3 * dx) + ', ' + str(dy) + ' ' + str(dx) + ', ' + str(dy)}, - '<-~>' : {'style': 'marker-end:url(#arrowhead);marker-start:url(#arrowtail);stroke:#0041c4;stroke-width:1;fill:none','d': 'M ' + frm['x'] + ',' + frm['y'] + ' ' + 'c ' + str(0.7 * dx) + ', 0 ' + str(dx) + ', ' + str(dy) + ' ' + str(dx) + ', ' + str(dy)}, - '<-|>' : {'style': 'marker-end:url(#arrowhead);marker-start:url(#arrowtail);stroke:#0041c4;stroke-width:1;fill:none','d': 'm ' + frm['x'] + ',' + frm['y'] + ' ' + str(dx) + ',0 0,' + str(dy)}, - '<-|->': {'style': 'marker-end:url(#arrowhead);marker-start:url(#arrowtail);stroke:#0041c4;stroke-width:1;fill:none','d': 'm ' + frm['x'] + ',' + frm['y'] + ' ' + str(dx / 2) + ',0 0,' + str(dy) + ' ' + str(dx / 2) + ',0'} - } - gmark[1].update( pattern.get( Edge['shape'], { 'style': 'fill:none;stroke:#00F;stroke-width:1' } ) ) - - if Edge['label']: - if Edge['shape'] == '-~' : - lx = float(frm['x']) + (float(to['x']) - float(frm['x'])) * 0.75 - if Edge['shape'] == '~-' : - lx = float(frm['x']) + (float(to['x']) - float(frm['x'])) * 0.25 - if Edge['shape'] == '-|' : - lx = float(to['x']) - if Edge['shape'] == '|-' : - lx = float(frm['x']) - if Edge['shape'] == '-~>': - lx = float(frm['x']) + (float(to['x']) - float(frm['x'])) * 0.75 - if Edge['shape'] == '~->': - lx = float(frm['x']) + (float(to['x']) - float(frm['x'])) * 0.25 - if Edge['shape'] == '-|>' : - lx = float(to['x']) - if Edge['shape'] == '|->' : - lx = float(frm['x']) - if Edge['shape'] == '<-~>': - lx = float(frm['x']) + (float(to['x']) - float(frm['x'])) * 0.75 - if Edge['shape'] =='<-|>' : - lx = float(to['x']) - - lwidth = len( Edge['label'] ) * font_width - label = [ - 'text', - { - 'style': 'font-size:10px;', - 'text-anchor': 'middle', - 'xml:space': 'preserve', - 'x': int( lx ), - 'y': int( ly + 3 ) - }, - [ 'tspan', Edge['label'] ] - ] - underlabel = [ - 'rect', - { - 'height': 9, - 'style': 'fill:#FFF;', - 'width': lwidth, - 'x': int( lx - lwidth / 2 ), - 'y': int( ly - 5 ) - } - ] - gg.append(underlabel) - gg.append(label) - - for k in Events: - if k.islower() : - if int( Events[k]['x'] ) > 0 : - lwidth = len( k ) * font_width - underlabel = [ - 'rect', - { - 'x': float( Events[k]['x'] ) - float(lwidth) / 2, - 'y': int( Events[k]['y'] ) - 4, - 'height': 8, - 'width': lwidth, - 'style': 'fill:#FFF;' - } - ] - gg.append(underlabel) - label = [ - 'text', - { - 'style': 'font-size:8px;', - 'x': int( Events[k]['x'] ), - 'y': int( Events[k]['y'] ) + 2, - 'width': lwidth, - 'text-anchor': 'middle' - }, - k - ] - gg.append(label) - -def parseConfig (source) : - - lane['hscale'] = 1 - if lane.get('hscale0') : - lane['hscale'] = lane['hscale0'] - - if source and source.get('config') and source.get('config').get('hscale'): - hscale = round(source.get('config').get('hscale')) - if hscale > 0 : - if hscale > 100 : hscale = 100 - lane['hscale'] = hscale - - lane['yh0'] = 0 - lane['yh1'] = 0 - if source and source.get('head') : - lane['head'] = source['head'] - if source.get('head').get('tick',0) == 0 : lane['yh0'] = 20 - if source.get('head').get('tock',0) == 0 : lane['yh0'] = 20 - if source.get('head').get('text') : lane['yh1'] = 46; lane['head']['text'] = source['head']['text'] - - lane['yf0'] = 0 - lane['yf1'] = 0 - if source and source.get('foot') : - lane['foot'] = source['foot'] - if source.get('foot').get('tick',0) == 0 : lane['yf0'] = 20 - if source.get('foot').get('tock',0) == 0 : lane['yf0'] = 20 - if source.get('foot').get('text') : lane['yf1'] = 46; lane['foot']['text'] = source['foot']['text'] - -def rec (tmp, state) : - - name = str( tmp[0] ) - delta_x = 25 - - state['x'] += delta_x - for i in range( len( tmp ) ) : - if type( tmp[i] ) is list : - old_y = state['y'] - rec( tmp[i], state ) - state['groups'].append( {'x':state['xx'], 'y':old_y, 'height':state['y'] - old_y, 'name': state['name'] } ) - elif type( tmp[i] ) is dict : - state['lanes'].append(tmp[i]) - state['width'].append(state['x']) - state['y'] += 1 - - state['xx'] = state['x'] - state['x'] -= delta_x - state['name'] = name - -def insertSVGTemplate (index, parent, source) : - - e = waveskin.WaveSkin['default'] - - if source.get('config') and source.get('config').get('skin') : - if waveskin.WaveSkin.get( source.get('config').get('skin') ) : - e = waveskin.WaveSkin[ source.get('config').get('skin') ] - - if index == 0 : - lane['xs'] = int( e[3][1][2][1]['width'] ) - lane['ys'] = int( e[3][1][2][1]['height'] ) - lane['xlabel'] = int( e[3][1][2][1]['x'] ) - lane['ym'] = int( e[3][1][2][1]['y'] ) - - else : - e = ['svg', {'id': 'svg', 'xmlns': 'http://www.w3.org/2000/svg', 'xmlns:xlink': 'http://www.w3.org/1999/xlink', 'height': '0'}, - ['g', {'id': 'waves'}, - ['g', {'id': 'lanes'}], - ['g', {'id': 'groups'}] - ] - ] - - e[-1][1]['id'] = 'waves_' + str(index) - e[-1][2][1]['id'] = 'lanes_' + str(index) - e[-1][3][1]['id'] = 'groups_' + str(index) - e[1]['id'] = 'svgcontent_' + str(index) - e[1]['height'] = 0 - - parent.extend(e) - -def renderWaveForm (index, source, output) : - - xmax = 0 - root = [] - groups = [] - - if source.get('signal'): - insertSVGTemplate(index, output, source) - parseConfig( source ) - ret = {'x':0, 'y':0, 'xmax':0, 'width':[], 'lanes':[], 'groups':[] } - rec( source['signal'], ret ) - content = parseWaveLanes(ret['lanes']) - glengths = renderWaveLane(root, content, index) - for i in range( len( glengths ) ): - xmax = max( xmax, ( glengths[i] + ret['width'][i] ) ) - renderMarks(root, content, index) - renderArcs(root, ret['lanes'], index, source) - renderGaps(root, ret['lanes'], index) - renderGroups(groups, ret['groups'], index) - lane['xg'] = int( math.ceil( float( xmax - lane['tgo'] ) / float(lane['xs'] ) ) ) * lane['xs'] - width = (lane['xg'] + lane['xs'] * (lane['xmax'] + 1) ) - height = len(content) * lane['yo'] + lane['yh0'] + lane['yh1'] + lane['yf0'] + lane['yf1'] - output[1]={ - 'id' :'svgcontent_' + str(index), - 'xmlns' :"http://www.w3.org/2000/svg", - 'xmlns:xlink':"http://www.w3.org/1999/xlink", - 'width' :str(width), - 'height' :str(height), - 'viewBox' :'0 0 ' + str(width) + ' ' + str(height), - 'overflow' :"hidden" - } - output[-1][2][1]['transform']='translate(' + str(lane['xg'] + 0.5) + ', ' + str((float(lane['yh0']) + float(lane['yh1'])) + 0.5) + ')' - - output[-1][2].extend(root) - output[-1][3].extend(groups) - -def renderGroups (root, groups, index) : - - svgns = 'http://www.w3.org/2000/svg', - xmlns = 'http://www.w3.org/XML/1998/namespace' - - for i in range( len( groups ) ) : - group = [ - 'path', - { - 'id': 'group_' + str(i) + '_' + str(index), - 'd': 'm ' + str( groups[i]['x'] + 0.5 ) + ',' + str( groups[i]['y']* lane['yo'] + 3.5 + lane['yh0'] + lane['yh1'] ) + ' c -3,0 -5,2 -5,5 l 0,' + str( int( groups[i]['height'] * lane['yo'] - 16 ) ) + ' c 0,3 2,5 5,5', - 'style': 'stroke:#0041c4;stroke-width:1;fill:none' - } - ] - root.append(group) - - name = groups[i]['name'] - x = str( int( groups[i]['x'] - 10 ) ) - y = str( int( lane['yo'] * (groups[i]['y'] + (float(groups[i]['height']) / 2)) + lane['yh0'] + lane['yh1'] ) ) - label = [ - ['g', - {'transform': 'translate(' + x + ',' + y + ')'}, - ['g', {'transform': 'rotate(270)'}, - 'text', - { - 'text-anchor': 'middle', - 'class': 'info', - 'xml:space' : 'preserve' - }, - ['tspan',name] - ] - ] - ] - root.append(label) - -def renderGaps (root, source, index) : - - Stack = [] - svgns = 'http://www.w3.org/2000/svg', - xlinkns = 'http://www.w3.org/1999/xlink' - - if source: - - gg = [ - 'g', - { 'id': 'wavegaps_' + str(index) } - ] - - for i in range( len( source )): - lane['period'] = source[i].get('period',1) - lane['phase'] = int( source[i].get('phase',0 ) * 2 ) - - g = [ - 'g', - { - 'id': 'wavegap_' + str(i) + '_' + str(index), - 'transform': 'translate(0,' + str(lane['y0'] + i * lane['yo']) + ')' - } - ] - gg.append(g) - - if source[i].get('wave'): - text = source[i]['wave'] - Stack = text - pos = 0 - while len( Stack ) : - c = Stack [0] - Stack = Stack[1:] - if c == '|' : - b = [ - 'use', - { - 'xmlns:xlink':xlinkns, - 'xlink:href':'#gap', - 'transform': 'translate(' + str(int(float(lane['xs']) * ((2 * pos + 1) * float(lane['period']) * float(lane['hscale']) - float(lane['phase'])))) + ')' - } - ] - g.append(b) - pos += 1 - - root.append( gg ) - -def is_type_str( var ) : - if sys.version_info[0] < 3: - return type( var ) is str or type( var ) is unicode - else: - return type( var ) is str - -def convert_to_svg( root ) : - - svg_output = '' - - if type( root ) is list: - if len(root) >= 2 and type( root[1] ) is dict: - if len( root ) == 2 : - svg_output += '<' + root[0] + convert_to_svg( root[1] ) + '/>\n' - elif len( root ) >= 3 : - svg_output += '<' + root[0] + convert_to_svg( root[1] ) + '>\n' - if len( root ) == 3: - svg_output += convert_to_svg( root[2] ) - else: - svg_output += convert_to_svg( root[2:] ) - svg_output += '\n' - elif type( root[0] ) is list: - for eleml in root: - svg_output += convert_to_svg( eleml ) - else: - svg_output += '<' + root[0] + '>\n' - for eleml in root[1:]: - svg_output += convert_to_svg( eleml ) - svg_output += '\n' - elif type( root ) is dict: - for elemd in root : - svg_output += ' ' + elemd + '="' + str(root[elemd]) + '"' - else: - svg_output += root - - return svg_output - -if __name__ == '__main__': - - if len( sys.argv ) != 5: - print ( 'Usage : ' + sys.argv[0] + ' source svg ' ) - exit(1) - - if sys.argv[3] != 'svg' : - print ( 'Error: only SVG format supported.' ) - exit(1) - - output=[] - inputfile = sys.argv[2] - outputfile = sys.argv[4] - - with open(inputfile,'r') as f: - jinput = json.load(f) - - renderWaveForm(0,jinput,output) - svg_output = convert_to_svg(output) - - with open(outputfile,'w') as f: - f.write( svg_output ) diff --git a/compiler/debug.py b/compiler/debug.py index e6c6a1bd..b7819bcc 100644 --- a/compiler/debug.py +++ b/compiler/debug.py @@ -48,17 +48,27 @@ def print_raw(str): def log(str): - if log.create_file: - compile_log = open(globals.OPTS.output_path + - globals.OPTS.output_name + '.log', "w") - log.create_file = 0 + if globals.OPTS.output_name != '': + if log.create_file: + compile_log = open(globals.OPTS.output_path + + globals.OPTS.output_name + '.log', "w+") + log.create_file = 0 + else: + compile_log = open(globals.OPTS.output_path + + globals.OPTS.output_name + '.log', "a") + + if len(log.setup_output) != 0: + for line in log.setup_output: + compile_log.write(line) + log.setup_output = [] + compile_log.write(str + '\n') else: - compile_log = open(globals.OPTS.output_path + - globals.OPTS.output_name + '.log', "a") - compile_log.write(str + '\n') -log.create_file = 1 + log.setup_output.append(str + "\n") +# use a static list of strings to store messages until the global paths are set up +log.setup_output = [] +log.create_file = 1 def info(lev, str): @@ -71,5 +81,5 @@ def info(lev, str): class_name = "" else: class_name = mod.__name__ - print_raw("[{0}/{1}]: {2}".format(class_name, frm[0].f_code.co_name, str)) - + print_raw("[{0}/{1}]: {2}".format(class_name, + frm[0].f_code.co_name, str))