From 7077de8cc52b8c8ba37eb54ed402f14d16ce1729 Mon Sep 17 00:00:00 2001 From: Alessandro Thea Date: Sun, 13 Sep 2020 23:08:50 +0200 Subject: [PATCH] Tweak to `vivadohls` regex format See #99 --- sandbox/report_timing.tcl | 4 + sandbox/reports.tcl | 39 +++++++ src/ipbb/tools/xilinx/vivadohls_console.py | 4 +- tests/scripts/alien_config.py | 121 +++++++++++++++++++++ 4 files changed, 166 insertions(+), 2 deletions(-) create mode 100644 sandbox/report_timing.tcl create mode 100644 sandbox/reports.tcl create mode 100755 tests/scripts/alien_config.py diff --git a/sandbox/report_timing.tcl b/sandbox/report_timing.tcl new file mode 100644 index 00000000..559bac80 --- /dev/null +++ b/sandbox/report_timing.tcl @@ -0,0 +1,4 @@ +report_timing -delay_type min_max -max_paths 10 -slack_less_than 0 -sort_by group -input_pins -name timing_3 + +set failing_paths [get_timing_paths -delay_type min_max -max_paths 10 -slack_less_than 0 -sort_by group] +report_property [lindex $failing_paths 0] \ No newline at end of file diff --git a/sandbox/reports.tcl b/sandbox/reports.tcl new file mode 100644 index 00000000..d0d6b9f2 --- /dev/null +++ b/sandbox/reports.tcl @@ -0,0 +1,39 @@ +# reportCriticalPaths.tcl + +#------------------------------------------------------------------------ +# This function generates a CSV file that provides a summary of the first +# 50 violations for both Setup and Hold analysis. So a maximum number of +# 100 paths are reported. +# +# #------------------------------------------------------------------------ +proc reportCriticalPaths { fileName } { +# Open the specified output file in write mode + set FH [open $fileName w] + # Write the current date and CSV format to a file header + puts $FH "#\n# File created on [clock format [clock seconds]]\n#\n" + puts $FH "Startpoint,Endpoint,DelayType,Slack,#Levels,#LUTs" + # Iterate through both Min and Max delay types + foreach delayType {max min} { + # Collect details from the 50 worst timing paths for the current analysis + # (max = setup/recovery, min = hold/removal) + # The $path variable contains a Timing Path object. + foreach path [get_timing_paths -delay_type $delayType -max_paths 50 -nworst 1] { + # Get the LUT cells of the timing paths + set luts [get_cells -filter {REF_NAME =~ LUT*} -of_object $path] + # Get the startpoint of the Timing Path object + set startpoint [get_property STARTPOINT_PIN $path] + # Get the endpoint of the Timing Path object + set endpoint [get_property ENDPOINT_PIN $path] + # Get the slack on the Timing Path object + set slack [get_property SLACK $path] + # Get the number of logic levels between startpoint and endpoint + set levels [get_property LOGIC_LEVELS $path] + # Save the collected path details to the CSV file + puts $FH "$startpoint,$endpoint,$delayType,$slack,$levels,[llength $luts]" + } + } + # Close the output file + close $FH + puts "CSV file $fileName has been created.\n" + return 0 +}; # End PROC diff --git a/src/ipbb/tools/xilinx/vivadohls_console.py b/src/ipbb/tools/xilinx/vivadohls_console.py index c35304ef..d9f14e59 100644 --- a/src/ipbb/tools/xilinx/vivadohls_console.py +++ b/src/ipbb/tools/xilinx/vivadohls_console.py @@ -190,8 +190,8 @@ class VivadoHLSConsole(object): __promptMap = { 'vivado_hls': re.compile(r'\x1b\[2K\r\rvivado_hls>\s'), } - __newlines = [u'\r\n'] - __cmdSentAck = '\r\x1b[12C\r' + __newlines = [r'\r\n'] + __cmdSentAck = r'\r\x1b[12C\r' # -------------------------------------------------------------- @classmethod diff --git a/tests/scripts/alien_config.py b/tests/scripts/alien_config.py new file mode 100755 index 00000000..ed09d4fd --- /dev/null +++ b/tests/scripts/alien_config.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python +from __future__ import print_function, absolute_import +from future.utils import iterkeys, itervalues, iteritems + + +class AlienNode2g(object): + """ + Utility class to easily build trees of key-values, useful for configuration + tress + """ + def __init__(self): + super(AlienNode2g, self).__init__() + self.__dict__['_locked'] = False + + def __repr__(self): + return str({ k:v for k, v in self.__dict__.iteritems() if not k.startswith('_')}) + + def __getattr__(self, name): + try: + return self.__dict__[name] + except KeyError: + if self._locked or name.startswith('__'): + raise + else: + value = self.__dict__[name] = type(self)() + return value + + def __setattr__(self, name, value): + if name not in self.__dict__ and name.startswith('_'): + raise AttributeError("Attributes starting with '_' are reserved ") + super(AlienNode2g, self).__setattr__(name, value) + + def __getitem__(self, name): + # print('get',name) + tokens = name.split('.',1) + child = getattr(self,tokens[0]) + if len(tokens) == 1: + return child + else: + return child[tokens[1]] + + def __setitem__(self, name, value): + + tokens = name.rsplit('.',1) + if len(tokens) == 1: + setattr(self, name, value) + else: + setattr(self[tokens[0]],tokens[1], value) + + def __iter__(self): + for n,o in self.__dict__.iteritems(): + if n.startswith('_'): + continue + elif isinstance(o, type(self)): + for cn in o: + yield n+'.'+cn + yield n + else: + yield n + + def _iternodes(self): + for n,o in self.__dict__.iteritems(): + if n.startswith('_'): + continue + elif isinstance(o, type(self)): + for cn, co in o._iternodes(): + yield n+'.'+cn, co + else: + yield n,o +#----------------------------------------------------------------------- + +def iternodes(node): + """ + Helper function to iterate over a node tree + + :param node: The node + :type node: { type_description } + + :returns: { description_of_the_return_value } + :rtype: { return_type_description } + """ + return node._iternodes() + +node = AlienNode2g() +print(node) +print(vars(node)) +print(dir(node)) +print(vars(node)) +print(node.a) +print(node) + +node.b.c = 5 +print(node) +print(node['b.c']) +print(node['b.d']) +print(node['b']['c']) +print(node) +node['l1.l2.l3.l4'] =7 +node.l1.l2.l3.l4=8 +print (node) +for k in node: + print ('-', k) + + +print('locked:', node._locked) +node._locked = True +try: + node.noway.val = 7 +except Exception as e: + print (type(e), e) + +for n in node: + print (n) + +print('b' in node) + +for n in node._iternodes(): + print (n) + +for n in iternodes(node): + print (n) \ No newline at end of file