diff --git a/compiler/characterizer/lib.py b/compiler/characterizer/lib.py
index 156481ce..60452d76 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
@@ -556,6 +560,7 @@ class lib:
datasheet.write("{0},{1},".format(DRC, LVS))
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 +657,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..44db3f9b 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):
@@ -100,6 +114,10 @@ def parse_characterizer_csv(f, pages):
AREA = row[col]
col += 1
+
+ ANALYTICAL_MODEL = 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 += '' + root[0] + '>\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 += '' + root[0] + '>\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..f25ff4b5 100644
--- a/compiler/debug.py
+++ b/compiler/debug.py
@@ -16,7 +16,7 @@ def check(check, str):
index) = inspect.getouterframes(inspect.currentframe())[1]
sys.stderr.write("ERROR: file {0}: line {1}: {2}\n".format(
os.path.basename(filename), line_number, str))
- log("ERROR: file {0}: line {1}: {2}\n".format(
+ logger.log("ERROR: file {0}: line {1}: {2}\n".format(
os.path.basename(filename), line_number, str))
assert 0
@@ -27,7 +27,7 @@ def error(str, return_value=0):
index) = inspect.getouterframes(inspect.currentframe())[1]
sys.stderr.write("ERROR: file {0}: line {1}: {2}\n".format(
os.path.basename(filename), line_number, str))
- log("ERROR: file {0}: line {1}: {2}\n".format(
+ logger.log("ERROR: file {0}: line {1}: {2}\n".format(
os.path.basename(filename), line_number, str))
assert return_value == 0
@@ -38,7 +38,7 @@ def warning(str):
index) = inspect.getouterframes(inspect.currentframe())[1]
sys.stderr.write("WARNING: file {0}: line {1}: {2}\n".format(
os.path.basename(filename), line_number, str))
- log("WARNING: file {0}: line {1}: {2}\n".format(
+ logger.log("WARNING: file {0}: line {1}: {2}\n".format(
os.path.basename(filename), line_number, str))
@@ -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))