Commit 9973916e authored by Mikhail Karpenko's avatar Mikhail Karpenko

Add Quartus parser script

parent 080053fa
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright (C) 2015, Elphel, Inc.
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Additional permission under GNU GPL version 3 section 7:
# If you modify this Program, or any covered work, by linking or combining it
# with Eclipse or Eclipse plugins (or a modified version of those libraries),
# containing parts covered by the terms of EPL/CPL, the licensors of this
# Program grant you additional permission to convey the resulting work.
# {Corresponding Source for a non-source form of such a combination shall
# include the source code for the parts of Eclipse or Eclipse plugins used
# as well as that of the covered work.}
import sys
import argparse
import re
# Global variables
g_topModule = ""
g_toolName = ""
g_mode = ""
g_includeMsgId = True
# Lines starting with these markers are of lines of interest
g_msgTypeMarkers = ("Info", "Warning", "Error", "Critical Warning", "Extra Info")
# Command line paramerters, these names should be in sync with those that are passed to the script in XML files (quartus_proto.xml probably)
g_optNames = ["top_module", "tool_name", "parser_mode", "include_msg_id"]
# Search patterns
patternMsgType = re.compile(".*?:")
patternMsgId = re.compile("[0-9]+")
patternFileLine = re.compile("([^ ]+)[ ]?\(([0-9]+)")
patternFileNameFull = re.compile("File:(.*)Line:")
class MessageContainer:
"""Helper container for parsed message line"""
msgType = ""
msgId = 0
msgText = ""
fileName = ""
fileNameFull = ""
lineNumber = 0
#Private parameters
__discardId = True
def discardId(self, value = None):
if value == None:
return self.__discardId
else:
self.__discardId = value
def getParameters():
"""Extract parameters from command line arguments"""
global g_topModule
global g_toolName
global g_mode
global g_includeMsgId
parser = argparse.ArgumentParser()
for opt in g_optNames:
parser.add_argument("--{}".format(opt))
args = parser.parse_args()
if args.top_module:
g_topModule = args.top_module
if args.tool_name:
g_toolName = args.tool_name
if args.parser_mode:
g_mode = args.parser_mode
if args.include_msg_id:
if args.include_msg_id == "true":
g_includeMsgId = True
else:
g_includeMsgId = False
def isProblem(line):
"""Check if the line contains meaningful information"""
global g_msgTypeMarkers
retVal = False
strippedLine = line.strip()
for msgType in g_msgTypeMarkers:
if strippedLine.startswith(msgType):
retVal = True
break
return retVal
def getMsgId(line, msg):
"""Extract message ID from log line an set coresponding msg field
line - text string to be parsed
msg - instance of MessageContainer class
return: instance of MessageContainer class
"""
matchedText = patternMsgId.search(line)
if matchedText:
msgId = line[matchedText.start() : matchedText.end()]
msg.msgId = int(msgId)
return msg
def getMsgType(line, msg):
"""Extract message type from log line an set coresponding msg field
line - text string to be parsed
msg - instance of MessageContainer class
return: log line without message type and instance of MessageContainer class
"""
strippedLine = line.strip()
matchedText = patternMsgType.search(strippedLine)
if matchedText:
msgType = strippedLine[matchedText.start() : matchedText.end() - 1]
msg = getMsgId(msgType, msg)
if msg.msgId != 0:
#remove message ID
msg.msgType = msgType.split('(')[0].strip()
msg.discardId(False)
else:
msg.msgType = msgType
return (strippedLine[matchedText.end() + 1:], msg)
def getFileLine(line, msg):
"""Extract file name and line number from log line an set coresponding msg fields
line - text string to be parsed
msg - instance of MessageContainer class
return: log line without extracted information
"""
matchedLine = patternFileLine.search(line)
if matchedLine and len(matchedLine.groups()) == 2:
msg.lineNumber = int(matchedLine.group(2))
msg.fileName = matchedLine.group(1)
#remove part of the string preceding file name as well as trailing braket and colon
#line = line[matchedLine.end(2) + 2:]
return (line, msg)
def getFilePath(line, msg):
"""Extract full file name and line number from log line an set coresponding msg fields
line - text string to be parsed
msg - instance of MessageContainer class
return: log line without extracted information
"""
matchedLine = patternFileNameFull.search(line)
if matchedLine:
msg.fileNameFull = matchedLine.group(1).strip()
line = line[:matchedLine.start() - 1]
return (line, msg)
def getMsgText(line, msg):
msg.msgText = line.strip()
return ("", msg)
def filterMessage(msg):
"""Decide whether this message should be redirected to output or filtered out"""
#just a stub
return True
def assembleLine(msg):
"""Assemble and return output line"""
if not g_includeMsgId or msg.discardId():
formatStr = "{0}: {2} [{3}:{4:04d}]\n"
else:
formatStr = "{0}: [{1}] {2} [{3}:{4:04d}]\n"
if msg.fileName =="":
problemMarker = g_toolName
else:
problemMarker = msg.fileName
line = formatStr.format(msg.msgType,
msg.msgId,
msg.msgText,
problemMarker,
msg.lineNumber
)
return line
if __name__ == "__main__":
getParameters()
for line in iter(sys.stdin.readline, ''):
if isProblem(line):
msg = MessageContainer()
processedLine, msg = getMsgType(line, msg)
processedLine, msg = getFilePath(processedLine, msg)
processedLine, msg = getFileLine(processedLine, msg)
processedLine, msg = getMsgText(processedLine, msg)
if filterMessage(msg):
logLine = assembleLine(msg)
sys.stdout.write(logLine)
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
<interface name="QuartusInterface" extends="FPGAPprojectInterface"> <interface name="QuartusInterface" extends="FPGAPprojectInterface">
<syntax name="GrepFilterProblemSyntax" format='| grep --line-buffered -v "\[%%ParamName"' /> <syntax name="GrepFilterProblemSyntax" format='| grep --line-buffered -v "\[%%ParamName"' />
<syntax name="GrepFilterProblemOtherSyntax" format='%(| grep --line-buffered -v "\[%%ParamValue"%|\n%)' /> <syntax name="GrepFilterProblemOtherSyntax" format='%(| grep --line-buffered -v "\[%%ParamValue"%|\n%)' />
<syntax name="CmdLineParameterSyntax" format="--%%ParamName %%ParamValue"/>
<typedef name="ParserModeType"> <typedef name="ParserModeType">
<paramtype kind= "enum" base="String"> <paramtype kind= "enum" base="String">
<item value="0" label="Tool output is parsed immediately"/> <item value="0" label="Tool output is parsed immediately"/>
......
...@@ -35,5 +35,89 @@ ...@@ -35,5 +35,89 @@
description="Quartus tool prototype" description="Quartus tool prototype"
abstract="true" abstract="true"
> >
<!-- parser parameters -->
<parameter id="PatternErrors" label="Errors" tooltip="Regular expression for error messages"
default=".*(Error:)(.*)\[(.*):([0-9]+)\]"
visible="true" type="String" format="CopyValue"/>
<parameter id="PatternWarnings" label="Warnings" tooltip="Regular expression for warnings messages"
default=".*(Warning:|Critical Warning:)(.*)\[(.*):([0-9]+)\]"
visible="true" type="String" format="CopyValue"/>
<parameter id="PatternInfo" label="Info" tooltip="Regular expression for info messages"
default=".*(Info:)(.*)\[(.*):([0-9]+)\]"
visible="true" type="String" format="CopyValue"/>
<parameter id="InstanceCapture" label="Instance capture"
tooltip="Regular expression to extract hierarchical instance name (outer '()' enclose the hierarchical name itself)"
default="((([#a-zA-Z_$]([a-zA-Z_$0-9]|\[[0-9:]+\])*)(\.|:))+([a-zA-Z_$]([a-zA-Z_$0-9]|\[[0-9:]+\])*))"
visible="true" type="String" format="CopyValue"/>
<parameter id="InstanceSeparator" label="Instance separator"
tooltip="Regular expression to extract hierarchical name separator, for literal '.' it is '\.'"
default="\."
visible="true" type="String" format="CopyValue"/>
<parameter id="InstanceSuffix" label="Instance suffix"
tooltip="Regular expression to match/remove name suffixes automatically added by the tools"
default="_reg|__parameterized[0-9]*"
visible="true" type="String" format="CopyValue"/>
<parameter id="ShowWarnings" label="Show Warnings" tooltip="Parse warning messages"
default="true" type="Boolean" format="None"/>
<parameter id="ShowInfo" label="Show info" tooltip="Parse info messages"
default="true" type="Boolean" format="None"/>
<parameter id="PreGrepW" visible="false"
type="String" format="None" default="?%ShowWarnings=true: |Warning, "/>
<parameter id="PreGrepI" visible="false"
type="String" format="None" default="?%ShowInfo=true: |Info, "/>
<parameter id="GrepEWI" label="Grep filter" tooltip="Calculated grep filter"
default="grep --line-buffered -E 'Error|CRITICAL WARNING%PreGrepW%PreGrepI'"
type="String" format="CopyValue" visible="true" readonly="true"/>
<parameter id="MaxMsg" outid="set_param messaging.defaultLimit" label="Maximal messages" tooltip="Maximum number of messages to output (per type)"
default="1000" visible="true" omit="100" type="Cardinal" format="NameValue"/>
<parameter id="parser_mode" label="Parser mode" tooltip="Parser mode (consolidation of bits of the same instance)"
default="1" visible="true" omit="" type="ParserModeType" format="CmdLineParameterSyntax"/>
<parameter id="parsers_path" label="Parsers Path" tooltip="parsers directory in plugins"
default="%%ParsersPath" visible="true" omit="" type="String" format="CopyValue"/>
<parameter id="parser_name" label="Quartus parser name" tooltip="Quartus output parser script path"
default="parser_quartus.py" visible="true" omit="" type="String" format="CopyValue"/>
<parameter id="include_msg_id" label="Inlcude message ID" tooltip="Include message ID to output"
type="Boolean" default="true" visible="true" readonly="false" format="CmdLineParameterSyntax"/>
<!-- Invisible parameters-->
<parameter id="tool_name" type="String" default="%%ToolName" visible="false" format="CmdLineParameterSyntax"/>
<parameter id="top_module" type="String" default="%%TopModule" visible="false" format="CmdLineParameterSyntax"/>
<input>
<group name="Parser" weight="10">
"parsers_path"
"parser_name"
"---"
"ShowWarnings"
"ShowInfo"
"MaxMsg"
"GrepEWI"
"---"
"include_msg_id"
"---"
"PatternErrors"
"PatternWarnings"
"PatternInfo"
"InstanceCapture"
"InstanceSeparator"
"InstanceSuffix"
"parser_mode"
</group>
</input>
<output>
<line name="parser_Quartus"
errors="PatternErrors"
warnings="PatternWarnings"
info="PatternInfo"
instance-capture="InstanceCapture"
instance-separator="InstanceSeparator"
instance-suffix="InstanceSuffix">
"-c"
"python -u %parsers_path%parser_name %tool_name %top_module %parser_mode %include_msg_id | "
"%GrepEWI"
</line>
</output>
</tool> </tool>
</vdt-project> </vdt-project>
...@@ -212,7 +212,7 @@ semantec errors, and perform a netlist exraction." ...@@ -212,7 +212,7 @@ semantec errors, and perform a netlist exraction."
<if QuartusSynthActionIndex="1"> <if QuartusSynthActionIndex="1">
"%analysis_and_elaboration" "%analysis_and_elaboration"
</if> </if>
"\"\n" "\""
</line> </line>
<line name="quartus_run_synth" <line name="quartus_run_synth"
dest="QuartusConsole" dest="QuartusConsole"
...@@ -235,6 +235,8 @@ semantec errors, and perform a netlist exraction." ...@@ -235,6 +235,8 @@ semantec errors, and perform a netlist exraction."
"project_open $projectName" "project_open $projectName"
"} else {" "} else {"
"project_new $projectName }" "project_new $projectName }"
"set_global_assignment -name VERILOG_FILE %ImplementationTopFile"
"set_global_assignment -name TOP_LEVEL_ENTITY %ImplementationTopModule"
"foreach file [list %FilteredSourceListPar] {" "foreach file [list %FilteredSourceListPar] {"
"puts \"Adding $file to project\"" "puts \"Adding $file to project\""
"set_global_assignment -name VERILOG_FILE $file }" "set_global_assignment -name VERILOG_FILE $file }"
......
...@@ -245,6 +245,8 @@ ...@@ -245,6 +245,8 @@
type="String" default="" format="CopyValue" readonly="false" /> type="String" default="" format="CopyValue" readonly="false" />
<parameter id="ImplementationTopFile" label="Implementation top file" tooltip="Project file with top implementation module" <parameter id="ImplementationTopFile" label="Implementation top file" tooltip="Project file with top implementation module"
type="Filename" default="" format="CopyValue" readonly="false" /> type="Filename" default="" format="CopyValue" readonly="false" />
<parameter id="ImplementationTopModule" label="Implementation top module" tooltip="Project top implementation module"
type="String" default="" format="CopyValue" readonly="false" />
<parameter id="SimulDir" label="Simulation directory" tooltip="Project simulation directory" <parameter id="SimulDir" label="Simulation directory" tooltip="Project simulation directory"
type="Pathname" default="simulation" format="CopyValue" readonly="false" /> type="Pathname" default="simulation" format="CopyValue" readonly="false" />
<!-- Vivado parameters --> <!-- Vivado parameters -->
...@@ -385,7 +387,6 @@ ...@@ -385,7 +387,6 @@
label="Disable Vivado bitstream" tooltip="Disable tool Vivado bitstream generator" label="Disable Vivado bitstream" tooltip="Disable tool Vivado bitstream generator"
default="false" default="false"
type="Boolean" format="None" /> type="Boolean" format="None" />
"" <!-- same as in project -->
<!-- Invisible (calculated) project-wide parameters --> <!-- Invisible (calculated) project-wide parameters -->
<parameter id="SimulDirSlash" type="Pathname" visible="false" <parameter id="SimulDirSlash" type="Pathname" visible="false"
...@@ -475,6 +476,7 @@ ...@@ -475,6 +476,7 @@
<group name="General" label="General parameters"> <group name="General" label="General parameters">
"part" "part"
"ImplementationTopFile" "ImplementationTopFile"
"ImplementationTopModule"
</group> </group>
<group name="Simulation" label="Simulation properties"> <group name="Simulation" label="Simulation properties">
"SimulationTopFile" "SimulationTopFile"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment