From 15ca3db9cbfdb95930a03d6e410397809bdfaf16 Mon Sep 17 00:00:00 2001 From: Jeremiah Leary Date: Sat, 21 Oct 2023 08:53:56 -0500 Subject: [PATCH] Issue#26: Adding parsing of Vivado Methodology report file. --- .../vendors/xilinx/vivado_methodology.rst | 43 ++++++ docs/source/vendors/xilinx/xilinx.rst | 1 + elfws/vendor/xilinx/vivado_methodology.py | 68 +++++++++ .../xilinx/vivado_methodology/__init__.py | 0 .../vivado_methodology/test_functions.py | 134 ++++++++++++++++++ .../vivado_methodology/warning_messages.rpt | 82 +++++++++++ 6 files changed, 328 insertions(+) create mode 100644 docs/source/vendors/xilinx/vivado_methodology.rst create mode 100644 elfws/vendor/xilinx/vivado_methodology.py create mode 100644 tests/vendor/xilinx/vivado_methodology/__init__.py create mode 100644 tests/vendor/xilinx/vivado_methodology/test_functions.py create mode 100755 tests/vendor/xilinx/vivado_methodology/warning_messages.rpt diff --git a/docs/source/vendors/xilinx/vivado_methodology.rst b/docs/source/vendors/xilinx/vivado_methodology.rst new file mode 100644 index 0000000..5a6bd05 --- /dev/null +++ b/docs/source/vendors/xilinx/vivado_methodology.rst @@ -0,0 +1,43 @@ +Vivado Methodology +~~~~~~~~~~~~~~~~~~ + +The Vivado methologoy report has a single warning format, but two different type of warnings: critical warnings and non critical warnings. +Some warning messages can also span multiple lines. + +Methodology Format +^^^^^^^^^^^^^^^^^^ + +Each methodology violation is reported over multiple lines. + +# + +
+Related violations: + +where: + ++-------------------------------+-------------------------------------------------+ +| Item | Regular Expression Match | ++===============================+=================================================+ +| ID | \W+ | ++-------------------------------+-------------------------------------------------+ +| count | [0-9]+ | ++-------------------------------+-------------------------------------------------+ +| classification | \W+ | ++-------------------------------+-------------------------------------------------+ +| details | \\W+\s\W+ | ++-------------------------------+-------------------------------------------------+ +| related | \\W+\s\W+ | ++-------------------------------+-------------------------------------------------+ + +Extracting Warnings +^^^^^^^^^^^^^^^^^^^ + +Extraction of warnings from the logfile will follow this process: + +1. Search for second line starting with 2. REPORT DETAILS +2. Extract ID and drop count and classification +3. drop description +4. Extract details +5. drop related + diff --git a/docs/source/vendors/xilinx/xilinx.rst b/docs/source/vendors/xilinx/xilinx.rst index 4d464f9..f1415d2 100644 --- a/docs/source/vendors/xilinx/xilinx.rst +++ b/docs/source/vendors/xilinx/xilinx.rst @@ -2,5 +2,6 @@ Xilinx ------ .. include:: vivado.rst +.. include:: vivado_methodology.rst diff --git a/elfws/vendor/xilinx/vivado_methodology.py b/elfws/vendor/xilinx/vivado_methodology.py new file mode 100644 index 0000000..5d97f2d --- /dev/null +++ b/elfws/vendor/xilinx/vivado_methodology.py @@ -0,0 +1,68 @@ +from elfws import warning +from elfws import warning_list + + +def get_vendor(): + return ['Xilinx'] + + +def get_tool_name(): + return 'vivado' + + +def is_logfile(lFile): + bSearch = False + for iLineNumber, sLine in enumerate(lFile): + if 'Tool Version' in sLine and 'Vivado' in sLine: + bSearch = True + if bSearch and sLine.startswith('Report Methodology'): + return True + if iLineNumber == 200: + return False + return False + + +def extract_warnings(lFile): + oReturn = warning_list.create() + + lRules = extract_rule_ids_from_summary(lFile) + iNumSection = 0 + iWarningLine = 0 + for iLineNumber, sLine in enumerate(lFile): + + if iWarningLine == 0: + for sRule in lRules: + if sLine.startswith(sRule): + iWarningLine = 1 + sID = sRule + + if iWarningLine == 1: + iWarningLine += 1 + elif iWarningLine == 2: + iWarningLine += 1 + elif iWarningLine == 3: + sMessage = sLine + iWarningLine += 1 + elif iWarningLine == 4: + iWarningLine = 0 + oWarning = warning.create(sID, sMessage, None, iLineNumber - 2) + oReturn.add_warning(oWarning) + + return oReturn + + +def extract_rule_ids_from_summary(lFile): + iNumSection = 0 + iTableDivider = 0 + lReturn = [] + for sLine in lFile: + if iTableDivider == 3: + break + if iTableDivider == 2 and not sLine.startswith('+---'): + lLine = sLine.split() + lReturn.append(lLine[1]) + if iNumSection == 2 and sLine.startswith('+---'): + iTableDivider += 1 + if sLine.startswith('1. REPORT SUMMARY'): + iNumSection += 1 + return lReturn diff --git a/tests/vendor/xilinx/vivado_methodology/__init__.py b/tests/vendor/xilinx/vivado_methodology/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/vendor/xilinx/vivado_methodology/test_functions.py b/tests/vendor/xilinx/vivado_methodology/test_functions.py new file mode 100644 index 0000000..d4e957f --- /dev/null +++ b/tests/vendor/xilinx/vivado_methodology/test_functions.py @@ -0,0 +1,134 @@ +import os +import unittest + +from elfws.vendor.xilinx import vivado_methodology +from tests import test_utils + +lLogFile = test_utils.read_file(os.path.join(os.path.dirname(__file__), 'warning_messages.rpt')) + +class testFunctions(unittest.TestCase): + + def test_extract_warnings(self): + oWarningList = vivado_methodology.extract_warnings(lLogFile) + + oWarning = oWarningList.warnings[0] + self.assertEqual('TIMING-18', oWarning.get_id()) + self.assertEqual('An input delay is missing on I_CS_F relative to clock(s) I_CLK', oWarning.get_message()) + self.assertEqual(None, oWarning.get_filename()) + self.assertEqual(37, oWarning.get_linenumber()) + + oWarning = oWarningList.warnings[1] + self.assertEqual('TIMING-18', oWarning.get_id()) + self.assertEqual('An input delay is missing on I_DATA relative to clock(s) I_CLK', oWarning.get_message()) + self.assertEqual(None, oWarning.get_filename()) + self.assertEqual(42, oWarning.get_linenumber()) + + oWarning = oWarningList.warnings[2] + self.assertEqual('TIMING-18', oWarning.get_id()) + self.assertEqual('An input delay is missing on I_MISO_DATA relative to clock(s) I_CLK', oWarning.get_message()) + self.assertEqual(None, oWarning.get_filename()) + self.assertEqual(47, oWarning.get_linenumber()) + + oWarning = oWarningList.warnings[3] + self.assertEqual('TIMING-18', oWarning.get_id()) + self.assertEqual('An input delay is missing on I_RST relative to clock(s) I_CLK', oWarning.get_message()) + self.assertEqual(None, oWarning.get_filename()) + self.assertEqual(52, oWarning.get_linenumber()) + + oWarning = oWarningList.warnings[4] + self.assertEqual('TIMING-18', oWarning.get_id()) + self.assertEqual('An input delay is missing on I_SCK relative to clock(s) I_CLK', oWarning.get_message()) + self.assertEqual(None, oWarning.get_filename()) + self.assertEqual(57, oWarning.get_linenumber()) + + oWarning = oWarningList.warnings[5] + self.assertEqual('TIMING-18', oWarning.get_id()) + self.assertEqual('An output delay is missing on O_DATA relative to clock(s) I_CLK', oWarning.get_message()) + self.assertEqual(None, oWarning.get_filename()) + self.assertEqual(62, oWarning.get_linenumber()) + + oWarning = oWarningList.warnings[6] + self.assertEqual('TIMING-18', oWarning.get_id()) + self.assertEqual('An output delay is missing on O_MOSI_CLK relative to clock(s) I_CLK', oWarning.get_message()) + self.assertEqual(None, oWarning.get_filename()) + self.assertEqual(67, oWarning.get_linenumber()) + + oWarning = oWarningList.warnings[7] + self.assertEqual('TIMING-19', oWarning.get_id()) + self.assertEqual('An output delay is missing on O_MOSI_CS_F relative to clock(s) I_CLK', oWarning.get_message()) + self.assertEqual(None, oWarning.get_filename()) + self.assertEqual(72, oWarning.get_linenumber()) + + oWarning = oWarningList.warnings[8] + self.assertEqual('TIMING-20', oWarning.get_id()) + self.assertEqual('An output delay is missing on O_MOSI_DATA relative to clock(s) I_CLK', oWarning.get_message()) + self.assertEqual(None, oWarning.get_filename()) + self.assertEqual(77, oWarning.get_linenumber()) + + self.assertEqual(9, oWarningList.get_number_of_warnings()) + + def test_is_logfile(self): + lLogFile = [] + lLogFile.append('Copyright 1986-2020 Xilinx, Inc. All Rights Reserved.') + lLogFile.append('-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------') + lLogFile.append('| Tool Version : Vivado v.2020.2 (win64) Build 3064766 Wed Nov 18 09:12:45 MST 2020') + lLogFile.append('| Date : Sun Aug 13 10:00:30 2023') + lLogFile.append('| Host : DESKTOP-HV9NHA3 running 64-bit major release (build 9200)') + lLogFile.append('| Command : report_methodology -file four_wire_spi_methodology_drc_routed.rpt -pb four_wire_spi_methodology_drc_routed.pb -rpx four_wire_spi_methodology_drc_routed.rpx') + lLogFile.append('| Design : four_wire_spi') + lLogFile.append('| Device : xa7a12tcpg238-2I') + lLogFile.append('| Speed File : -2I') + lLogFile.append('| Design State : Fully Routed') + lLogFile.append('-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------') + lLogFile.append(' ') + lLogFile.append('Report Methodology') + + self.assertTrue(vivado_methodology.is_logfile(lLogFile)) + + lLogFile = [] + lLogFile.append('***** Vivado v2018.3 (64-bit)') + lLogFile.append(' **** SW Build 2405991 on ') + lLogFile.append(' **** IP Build 2404404 on ') + lLogFile.append(' ** Copyright ') + + self.assertFalse(vivado_methodology.is_logfile(lLogFile)) + + lLogFile = [] + lLogFile.append(' ') + lLogFile.append(' ') + lLogFile.append('***** Vivado v2018.3 (64-bit)') + lLogFile.append(' **** SW Build 2405991 on ') + lLogFile.append(' **** IP Build 2404404 on ') + lLogFile.append(' ** Copyright ') + lLogFile.append(' ') + lLogFile.append(' ') + lLogFile.append(' ') + lLogFile.append(' ') + lLogFile.append(' ') + lLogFile.append(' ') + lLogFile.append(' ') + lLogFile.append(' ') + + self.assertFalse(vivado_methodology.is_logfile(lLogFile)) + + lLogFile = [] + for i in range(0, 100): + lLogFile.append(' ') + lLogFile.append('# Vivado ') + lLogFile.append('# SW Build ') + lLogFile.append('# IP Build ') + lLogFile.append('# Process ID: ') + + self.assertFalse(vivado_methodology.is_logfile(lLogFile)) + + lLogFile = [] + for i in range(0, 300): + lLogFile.append('') + + self.assertFalse(vivado_methodology.is_logfile(lLogFile)) + + def test_vendor(self): + self.assertEqual(['Xilinx'], vivado_methodology.get_vendor()) + + def test_tool_name(self): + self.assertEqual('vivado', vivado_methodology.get_tool_name()) diff --git a/tests/vendor/xilinx/vivado_methodology/warning_messages.rpt b/tests/vendor/xilinx/vivado_methodology/warning_messages.rpt new file mode 100755 index 0000000..e5ac83f --- /dev/null +++ b/tests/vendor/xilinx/vivado_methodology/warning_messages.rpt @@ -0,0 +1,82 @@ +Copyright 1986-2020 Xilinx, Inc. All Rights Reserved. +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +| Tool Version : Vivado v.2020.2 (win64) Build 3064766 Wed Nov 18 09:12:45 MST 2020 +| Date : Sun Aug 13 10:00:30 2023 +| Host : DESKTOP-HV9NHA3 running 64-bit major release (build 9200) +| Command : report_methodology -file four_wire_spi_methodology_drc_routed.rpt -pb four_wire_spi_methodology_drc_routed.pb -rpx four_wire_spi_methodology_drc_routed.rpx +| Design : four_wire_spi +| Device : xa7a12tcpg238-2I +| Speed File : -2I +| Design State : Fully Routed +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + +Report Methodology + +Table of Contents +----------------- +1. REPORT SUMMARY +2. REPORT DETAILS + +1. REPORT SUMMARY +----------------- + Netlist: netlist + Floorplan: design_1 + Design limits: + Max violations: + Violations found: 9 ++-----------+----------+-------------------------------+------------+ +| Rule | Severity | Description | Violations | ++-----------+----------+-------------------------------+------------+ +| TIMING-18 | Warning | Missing input or output delay | 7 | +| TIMING-19 | Warning | Missing input or output delay | 1 | +| TIMING-20 | Warning | Missing input or output delay | 1 | ++-----------+----------+-------------------------------+------------+ + +2. REPORT DETAILS +----------------- +TIMING-18#1 Warning +Missing input or output delay +An input delay is missing on I_CS_F relative to clock(s) I_CLK +Related violations: + +TIMING-18#2 Warning +Missing input or output delay +An input delay is missing on I_DATA relative to clock(s) I_CLK +Related violations: + +TIMING-18#3 Warning +Missing input or output delay +An input delay is missing on I_MISO_DATA relative to clock(s) I_CLK +Related violations: + +TIMING-18#4 Warning +Missing input or output delay +An input delay is missing on I_RST relative to clock(s) I_CLK +Related violations: + +TIMING-18#5 Warning +Missing input or output delay +An input delay is missing on I_SCK relative to clock(s) I_CLK +Related violations: + +TIMING-18#6 Warning +Missing input or output delay +An output delay is missing on O_DATA relative to clock(s) I_CLK +Related violations: + +TIMING-18#7 Warning +Missing input or output delay +An output delay is missing on O_MOSI_CLK relative to clock(s) I_CLK +Related violations: + +TIMING-19#1 Warning +Missing input or output delay +An output delay is missing on O_MOSI_CS_F relative to clock(s) I_CLK +Related violations: + +TIMING-20#1 Warning +Missing input or output delay +An output delay is missing on O_MOSI_DATA relative to clock(s) I_CLK +Related violations: + +