From bc79e30fe5d338a6888b87c7ec922db96d2cbf36 Mon Sep 17 00:00:00 2001 From: Ethan Sifferman Date: Mon, 2 Sep 2024 20:41:29 -0700 Subject: [PATCH] convert severity and elaboration system tasks (#276) --- CHANGELOG.md | 3 ++ README.md | 2 +- src/Convert.hs | 2 + src/Convert/Scoper.hs | 25 ++++++++++-- src/Convert/SeverityTask.hs | 64 +++++++++++++++++++++++++++++++ src/Job.hs | 3 +- sv2v.cabal | 1 + test/{nosim => core}/elab_task.sv | 3 +- test/core/elab_task.sv.pat | 5 +++ test/core/elab_task.v | 20 ++++++++++ test/core/severity_task.sv | 13 +++++++ test/core/severity_task.sv.pat | 5 +++ test/core/severity_task.v | 16 ++++++++ test/lib/functions.sh | 12 ++++++ 14 files changed, 167 insertions(+), 7 deletions(-) create mode 100644 src/Convert/SeverityTask.hs rename test/{nosim => core}/elab_task.sv (77%) create mode 100644 test/core/elab_task.sv.pat create mode 100644 test/core/elab_task.v create mode 100644 test/core/severity_task.sv create mode 100644 test/core/severity_task.sv.pat create mode 100644 test/core/severity_task.v diff --git a/CHANGELOG.md b/CHANGELOG.md index 2bc88496..d9df33bd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ ### New Features +* Added conversion of severity system tasks and elaboration system tasks (e.g., + `$info`) into `$display` tasks that include source file and scope information; + pass `-E SeverityTask` to disable this new conversion * Added parsing support for `not`, `strong`, `weak`, `nexttime`, and `s_nexttime` in assertion property expressions * Added `--bugpoint` utility for minimizing test cases for issue submission diff --git a/README.md b/README.md index 0099996d..af9c21e9 100644 --- a/README.md +++ b/README.md @@ -102,7 +102,7 @@ Preprocessing: Conversion: --pass-through Dump input without converting -E --exclude=CONV Exclude a particular conversion (Always, Assert, - Interface, Logic, or UnbasedUnsized) + Interface, Logic, SeverityTask, or UnbasedUnsized) -v --verbose Retain certain conversion artifacts -w --write=MODE/FILE/DIR How to write output; default is 'stdout'; use 'adjacent' to create a .v file next to each input; diff --git a/src/Convert.hs b/src/Convert.hs index 7a6e1f89..31008879 100644 --- a/src/Convert.hs +++ b/src/Convert.hs @@ -45,6 +45,7 @@ import qualified Convert.ParamType import qualified Convert.PortDecl import qualified Convert.RemoveComments import qualified Convert.ResolveBindings +import qualified Convert.SeverityTask import qualified Convert.Simplify import qualified Convert.Stream import qualified Convert.StringParam @@ -119,6 +120,7 @@ initialPhases tops selectExclude = , selectExclude Job.Assert Convert.Assertion.convert , selectExclude Job.Always Convert.AlwaysKW.convert , Convert.Interface.disambiguate + , selectExclude Job.SeverityTask Convert.SeverityTask.convert , Convert.Package.convert , Convert.StructConst.convert , Convert.PortDecl.convert diff --git a/src/Convert/Scoper.hs b/src/Convert/Scoper.hs index 22279f38..b8f0d887 100644 --- a/src/Convert/Scoper.hs +++ b/src/Convert/Scoper.hs @@ -58,6 +58,10 @@ module Convert.Scoper , withinProcedureM , procedureLoc , procedureLocM + , sourceLocation + , sourceLocationM + , hierarchyPath + , hierarchyPathM , scopedError , scopedErrorM , isLoopVar @@ -367,12 +371,25 @@ procedureLoc = sProcedureLoc debugLocation :: Scopes a -> String debugLocation s = hierarchy ++ - if null latestTrace + if null location then " (use -v to get approximate source location)" - else ", near " ++ latestTrace + else ", near " ++ location + where + hierarchy = hierarchyPath s + location = sourceLocation s + +sourceLocationM :: Monad m => ScoperT a m String +sourceLocationM = gets sourceLocation + +sourceLocation :: Scopes a -> String +sourceLocation = sLatestTrace + +hierarchyPathM :: Monad m => ScoperT a m String +hierarchyPathM = gets hierarchyPath + +hierarchyPath :: Scopes a -> String +hierarchyPath = intercalate "." . map tierToStr . sCurrent where - hierarchy = intercalate "." $ map tierToStr $ sCurrent s - latestTrace = sLatestTrace s tierToStr :: Tier -> String tierToStr (Tier "" _) = "" tierToStr (Tier x "") = x diff --git a/src/Convert/SeverityTask.hs b/src/Convert/SeverityTask.hs new file mode 100644 index 00000000..3225fe2e --- /dev/null +++ b/src/Convert/SeverityTask.hs @@ -0,0 +1,64 @@ +{- sv2v + - Author: Ethan Sifferman + - + - Conversion of severity system tasks (IEEE 1800-2017 Section 20.10) and + - elaboration system tasks (Section 20.11) `$info`, `$warning`, `$error`, and + - `$fatal`, which sv2v collectively refers to as "severity tasks". + - + - 1. Severity task messages are converted into `$display` tasks. + - 2. `$fatal` tasks also run `$finish` directly after running `$display`. + -} + +module Convert.SeverityTask (convert) where + +import Data.Char (toUpper) +import Data.Functor ((<&>)) + +import Convert.Scoper +import Convert.Traverse +import Language.SystemVerilog.AST + +type SC = Scoper () + +convert :: [AST] -> [AST] +convert = map $ traverseDescriptions traverseDescription + +traverseDescription :: Description -> Description +traverseDescription = partScoper return traverseModuleItem return traverseStmt + +-- convert elaboration severity tasks +traverseModuleItem :: ModuleItem -> SC ModuleItem +traverseModuleItem (ElabTask severity taskArgs) = + elab severity taskArgs "elaboration" [] <&> Initial +traverseModuleItem other = return other + +-- convert standard severity tasks +traverseStmt :: Stmt -> SC Stmt +traverseStmt (SeverityStmt severity taskArgs) = + elab severity taskArgs "%0t" [Ident "$time"] +traverseStmt other = return other + +elab :: Severity -> [Expr] -> String -> [Expr] -> SC Stmt +elab severity args prefixStr prefixArgs = do + scopeName <- hierarchyPathM + fileLocation <- sourceLocationM + let contextArg = String $ msg scopeName fileLocation + let stmtDisplay = call "$display" $ contextArg : prefixArgs ++ displayArgs + return $ Block Seq "" [] [stmtDisplay, stmtFinish] + where + msg scope file = severityToString severity ++ " [" ++ prefixStr ++ "] " + ++ file ++ " - " ++ scope + ++ if null displayArgs then "" else "\\n msg: " + displayArgs = if severity /= SeverityFatal || null args + then args + else tail args + stmtFinish = if severity /= SeverityFatal + then Null + else call "$finish" $ if null args then [] else [head args] + +call :: Identifier -> [Expr] -> Stmt +call func args = Subroutine (Ident func) (Args args []) + +severityToString :: Severity -> String +severityToString severity = toUpper ch : str + where '$' : ch : str = show severity diff --git a/src/Job.hs b/src/Job.hs index 68ce4dc8..74409063 100644 --- a/src/Job.hs +++ b/src/Job.hs @@ -27,6 +27,7 @@ data Exclude | Assert | Interface | Logic + | SeverityTask | Succinct | UnbasedUnsized deriving (Typeable, Data, Eq) @@ -83,7 +84,7 @@ defaultJob = Job &= groupname "Conversion" , exclude = nam_ "exclude" &= name "E" &= typ "CONV" &= help ("Exclude a particular conversion (Always, Assert, Interface," - ++ " Logic, or UnbasedUnsized)") + ++ " Logic, SeverityTask, or UnbasedUnsized)") , verbose = nam "verbose" &= help "Retain certain conversion artifacts" , write = Stdout &= ignore -- parsed from the flexible flag below , writeRaw = "s" &= name "write" &= name "w" &= explicit diff --git a/sv2v.cabal b/sv2v.cabal index 4701ec65..30162856 100644 --- a/sv2v.cabal +++ b/sv2v.cabal @@ -98,6 +98,7 @@ executable sv2v Convert.RemoveComments Convert.ResolveBindings Convert.Scoper + Convert.SeverityTask Convert.Simplify Convert.Stream Convert.StringParam diff --git a/test/nosim/elab_task.sv b/test/core/elab_task.sv similarity index 77% rename from test/nosim/elab_task.sv rename to test/core/elab_task.sv index 87e14bb5..f9208037 100644 --- a/test/nosim/elab_task.sv +++ b/test/core/elab_task.sv @@ -6,5 +6,6 @@ module top; $error; $error("%b", 3); $fatal; - $fatal("%b", 4); + $fatal(0); + $fatal(1, "%b", 4); endmodule diff --git a/test/core/elab_task.sv.pat b/test/core/elab_task.sv.pat new file mode 100644 index 00000000..60e8d63d --- /dev/null +++ b/test/core/elab_task.sv.pat @@ -0,0 +1,5 @@ +affirm $finish; +affirm $display("Fatal [elaboration] elab_task.sv:9:5 - top"); +affirm $finish(0); +affirm $display("Fatal [elaboration] elab_task.sv:10:5 - top\\n msg: ", "%b", 4); +affirm $finish(1); diff --git a/test/core/elab_task.v b/test/core/elab_task.v new file mode 100644 index 00000000..3b86f2eb --- /dev/null +++ b/test/core/elab_task.v @@ -0,0 +1,20 @@ +module top; + initial $display("Info [elaboration] elab_task.sv:2:5 - top"); + initial $display("Info [elaboration] elab_task.sv:3:5 - top\n msg: %b", 1); + initial $display("Warning [elaboration] elab_task.sv:4:5 - top"); + initial $display("Warning [elaboration] elab_task.sv:5:5 - top\n msg: %b", 2); + initial $display("Error [elaboration] elab_task.sv:6:5 - top"); + initial $display("Error [elaboration] elab_task.sv:7:5 - top\n msg: %b", 3); + initial begin + $display("Fatal [elaboration] elab_task.sv:8:5 - top"); + $finish; + end + initial begin + $display("Fatal [elaboration] elab_task.sv:9:5 - top"); + $finish(0); + end + initial begin + $display("Fatal [elaboration] elab_task.sv:10:5 - top\n msg: %b", 4); + $finish(1); + end +endmodule diff --git a/test/core/severity_task.sv b/test/core/severity_task.sv new file mode 100644 index 00000000..65223b6f --- /dev/null +++ b/test/core/severity_task.sv @@ -0,0 +1,13 @@ +module top; + initial begin + $info; + $info("%b", 1); + $warning; + $warning("%b", 2); + $error; + $error("%b", 3); + $fatal; + $fatal(0); + $fatal(1, "%b", 4); + end +endmodule diff --git a/test/core/severity_task.sv.pat b/test/core/severity_task.sv.pat new file mode 100644 index 00000000..0ff5476b --- /dev/null +++ b/test/core/severity_task.sv.pat @@ -0,0 +1,5 @@ +affirm $finish; +affirm $display("Fatal [%0t] severity_task.sv:10:9 - top.", $time); +affirm $finish(0); +affirm $display("Fatal [%0t] severity_task.sv:11:9 - top.\\n msg: ", $time, "%b", 4); +affirm $finish(1); diff --git a/test/core/severity_task.v b/test/core/severity_task.v new file mode 100644 index 00000000..5c3feddd --- /dev/null +++ b/test/core/severity_task.v @@ -0,0 +1,16 @@ +module top; + initial begin + $display("Info [%0t] severity_task.sv:3:9 - top.", $time); + $display("Info [%0t] severity_task.sv:4:9 - top.\n msg: ", $time, "%b", 1); + $display("Warning [%0t] severity_task.sv:5:9 - top.", $time); + $display("Warning [%0t] severity_task.sv:6:9 - top.\n msg: ", $time, "%b", 2); + $display("Error [%0t] severity_task.sv:7:9 - top.", $time); + $display("Error [%0t] severity_task.sv:8:9 - top.\n msg: ", $time, "%b", 3); + $display("Fatal [%0t] severity_task.sv:9:9 - top.", $time); + $finish; + $display("Fatal [%0t] severity_task.sv:10:9 - top.", $time); + $finish(0); + $display("Fatal [%0t] severity_task.sv:11:9 - top.\n msg: ", $time, "%b", 4); + $finish(1); + end +endmodule diff --git a/test/lib/functions.sh b/test/lib/functions.sh index 58570c13..42273491 100644 --- a/test/lib/functions.sh +++ b/test/lib/functions.sh @@ -77,6 +77,9 @@ assertConverts() { ac_tmpd=$SHUNIT_TMPDIR/ac-conv-tmpd.v convert "conversion of pass through of $ac_file" $ac_tmpd $ac_tmpc + # remove source locations when checking the --pass-through invariant + removeSourceLocation $ac_file $ac_tmpa + removeSourceLocation $ac_tmpc $ac_tmpd diff $ac_tmpa $ac_tmpd > /dev/null assertTrue "pass through then conversion differs for $ac_file" $? @@ -173,6 +176,11 @@ simulateAndCompare() { simulate $cvs_vcd $cvs_log $cs $tb simulate $cvv_vcd $cvv_log $cv $tb + # clean log files by source locations + removeSourceLocation $ve $ref_log + removeSourceLocation $cs $cvs_log + removeSourceLocation $cv $cvv_log + # compare reference verilog to converted succinct output=`diff $ref_vcd $cvs_vcd` assertTrue "VE/CS VCDs are different:\n$output" $? @@ -199,3 +207,7 @@ runAndCapture() { stdout=`cat $SHUNIT_TMPDIR/stdout` stderr=`cat $SHUNIT_TMPDIR/stderr` } + +removeSourceLocation() { + sed -i.bak -E 's#'$1':[0-9]+(:[0-9]+)?##g' $2 +}