diff --git a/CHANGELOG.md b/CHANGELOG.md index c1e3bc9..59292cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ * Added support for excluding the conversion of unbased unsized literals (e.g., `'1`, `'x`) via `--exclude UnbasedUniszed` * Added support for enumerated type ranges (e.g., `enum { X[3:5] }`) +* Added support for passing through DPI imports and exports ### Other Enhancements diff --git a/src/Convert/Package.hs b/src/Convert/Package.hs index 927b634..71c95e3 100644 --- a/src/Convert/Package.hs +++ b/src/Convert/Package.hs @@ -778,6 +778,8 @@ piNames (Decl (Net _ _ _ _ ident _ _)) = [ident] piNames (Decl (Param _ _ ident _)) = [ident] piNames (Decl (ParamType _ ident _)) = [ident] piNames (Decl (CommentDecl _)) = [] -piNames (Import x y) = [show $ Import x y] -piNames (Export x y) = [show $ Export x y] +piNames item@DPIImport{} = [show item] +piNames item@DPIExport{} = [show item] +piNames item@Import{} = [show item] +piNames item@Export{} = [show item] piNames (Directive _) = [] diff --git a/src/Convert/RemoveComments.hs b/src/Convert/RemoveComments.hs index 5e53db7..35ada6d 100644 --- a/src/Convert/RemoveComments.hs +++ b/src/Convert/RemoveComments.hs @@ -39,6 +39,9 @@ convertPackageItem (Task l x decls stmts) = where decls' = convertDecls decls stmts' = convertStmts stmts +convertPackageItem (DPIImport spec prop alias typ name decls) = + DPIImport spec prop alias typ name decls' + where decls' = convertDecls decls convertPackageItem other = other convertStmt :: Stmt -> Stmt diff --git a/src/Convert/Scoper.hs b/src/Convert/Scoper.hs index d00fed4..95e6f94 100644 --- a/src/Convert/Scoper.hs +++ b/src/Convert/Scoper.hs @@ -561,6 +561,14 @@ scopeModuleItem declMapperRaw moduleItemMapper genItemMapper stmtMapperRaw = return $ MIPackageItem $ Task ml x' decls' stmts' fullModuleItemMapper (MIPackageItem (Decl decl)) = declMapper decl >>= return . MIPackageItem . Decl + fullModuleItemMapper (MIPackageItem item@DPIImport{}) = do + let DPIImport spec prop alias typ name decls = item + (typ', name') <- redirectTFDecl typ name + decls' <- mapM declMapper decls + let item' = DPIImport spec prop alias typ' name' decls' + return $ MIPackageItem item' + fullModuleItemMapper (MIPackageItem (DPIExport spec alias kw name)) = + return $ MIPackageItem $ DPIExport spec alias kw name fullModuleItemMapper (AlwaysC kw stmt) = do enterProcedure stmt' <- fullStmtMapper stmt diff --git a/src/Convert/Traverse.hs b/src/Convert/Traverse.hs index 0dfe858..de78ac3 100644 --- a/src/Convert/Traverse.hs +++ b/src/Convert/Traverse.hs @@ -618,6 +618,14 @@ traverseNodesM exprMapper declMapper typeMapper lhsMapper stmtMapper = return $ MIPackageItem $ Import x y moduleItemMapper (MIPackageItem (Export x y)) = return $ MIPackageItem $ Export x y + moduleItemMapper (MIPackageItem item@DPIImport{}) = do + let DPIImport spec prop alias typ name decls = item + typ' <- typeMapper typ + decls' <- mapM declMapper decls + let item' = DPIImport spec prop alias typ' name decls' + return $ MIPackageItem item' + moduleItemMapper (MIPackageItem (DPIExport spec alias kw name)) = + return $ MIPackageItem $ DPIExport spec alias kw name moduleItemMapper (AssertionItem (mx, a)) = do a' <- traverseAssertionStmtsM stmtMapper a a'' <- traverseAssertionExprsM exprMapper a' diff --git a/src/Language/SystemVerilog/AST/Description.hs b/src/Language/SystemVerilog/AST/Description.hs index 225c660..bd66953 100644 --- a/src/Language/SystemVerilog/AST/Description.hs +++ b/src/Language/SystemVerilog/AST/Description.hs @@ -1,3 +1,4 @@ +{-# LANGUAGE PatternSynonyms #-} {- sv2v - Author: Zachary Snow - Initial Verilog AST Author: Tom Hawkins @@ -12,6 +13,8 @@ module Language.SystemVerilog.AST.Description , Lifetime (..) , Qualifier (..) , ClassItem + , DPIImportProperty (..) + , DPIExportKW (..) ) where import Data.List (intercalate) @@ -22,7 +25,7 @@ import Language.SystemVerilog.AST.ShowHelp import Language.SystemVerilog.AST.Attr (Attr) import Language.SystemVerilog.AST.Decl (Decl(CommentDecl)) import Language.SystemVerilog.AST.Stmt (Stmt) -import Language.SystemVerilog.AST.Type (Type, Identifier) +import Language.SystemVerilog.AST.Type (Type, Identifier, pattern UnknownType) import {-# SOURCE #-} Language.SystemVerilog.AST.ModuleItem (ModuleItem) data Description @@ -82,6 +85,8 @@ data PackageItem | Export Identifier Identifier | Decl Decl | Directive String + | DPIImport String DPIImportProperty Identifier Type Identifier [Decl] + | DPIExport String Identifier DPIExportKW Identifier deriving Eq instance Show PackageItem where @@ -95,6 +100,22 @@ instance Show PackageItem where show (Export x y) = printf "export %s::%s;" (showWildcard x) (showWildcard y) show (Decl decl) = show decl show (Directive str) = str + show (DPIImport spec prop alias typ name decls) = + printf "import %s %s%s %s %s(%s);" + (show spec) (showPad prop) aliasStr protoStr name declsStr + where + aliasStr = if null alias then "" else alias ++ " = " + protoStr = + if typ == UnknownType + then "task" + else "function " ++ show typ + declsStr = + if null decls + then "" + else "\n\t" ++ showDecls decls ++ "\n" + show (DPIExport spec alias kw name) = + printf "export %s %s%s %s;" (show spec) aliasStr (show kw) name + where aliasStr = if null alias then "" else alias ++ " = " showWildcard :: Identifier -> String showWildcard "" = "*" @@ -137,3 +158,23 @@ instance Show Qualifier where show QStatic = "static" show QLocal = "local" show QProtected = "protected" + +data DPIImportProperty + = DPIContext + | DPIPure + | DPINone + deriving Eq + +instance Show DPIImportProperty where + show DPIContext = "context" + show DPIPure = "pure" + show DPINone = "" + +data DPIExportKW + = DPIExportTask + | DPIExportFunction + deriving Eq + +instance Show DPIExportKW where + show DPIExportTask = "task" + show DPIExportFunction = "function" diff --git a/src/Language/SystemVerilog/AST/Type.hs b/src/Language/SystemVerilog/AST/Type.hs index 1f423a3..a2ac9fe 100644 --- a/src/Language/SystemVerilog/AST/Type.hs +++ b/src/Language/SystemVerilog/AST/Type.hs @@ -181,6 +181,7 @@ data NonIntegerType | TRealtime | TString | TEvent + | TChandle deriving Eq instance Show NetType where @@ -213,6 +214,7 @@ instance Show NonIntegerType where show TRealtime = "realtime" show TString = "string" show TEvent = "event" + show TChandle = "chandle" data Packing = Unpacked diff --git a/src/Language/SystemVerilog/Parser/Parse.y b/src/Language/SystemVerilog/Parser/Parse.y index a755144..3b79895 100644 --- a/src/Language/SystemVerilog/Parser/Parse.y +++ b/src/Language/SystemVerilog/Parser/Parse.y @@ -518,6 +518,7 @@ NonIntegerTypeP :: { (Position, NonIntegerType) } | "realtime" { withPos $1 TRealtime } | "string" { withPos $1 TString } | "event" { withPos $1 TEvent } + | "chandle" { withPos $1 TChandle } EnumItems :: { [EnumItem] } : EnumItem { $1 } @@ -904,6 +905,7 @@ NonDeclPackageItem :: { [PackageItem] } | ImportOrExport { $1 } | ForwardTypedef ";" { $1 } | TimeunitsDeclaration { $1 } + | DPIImportExport { [$1] } | Directive { [Directive $1] } ImportOrExport :: { [PackageItem] } @@ -931,6 +933,31 @@ TimeunitsDeclaration :: { [PackageItem] } | "timeunit" Time "/" Time ";" { [] } | "timeprecision" Time ";" { [] } +DPIImportExport :: { PackageItem } + : "import" DPISpecString OptDPIImportProperty OptDPIAlias DPITFProto { makeDPIImport $2 $3 $4 $5 } + | "export" DPISpecString OptDPIAlias DPIExportKW Identifier ";" { DPIExport $2 $3 $4 $5 } + +DPIExportKW :: { DPIExportKW } + : "task" { DPIExportTask } + | "function" { DPIExportFunction } + +DPISpecString :: { String } + : String { $1 } + +OptDPIAlias :: { Identifier } + : Identifier "=" { $1 } + | {- empty -} { "" } + +OptDPIImportProperty :: { DPIImportProperty } + : "context" { DPIContext } + | "pure" { DPIPure } + | {- empty -} { DPINone } + +DPITFProto :: { (Type, Identifier, [Decl]) } + : "function" FuncRetAndName TFItems { (fst $2 , snd $2, $3) } + | "function" "void" Identifier TFItems { (UnknownType, $3, $4) } + | "task" Identifier TFItems { (UnknownType, $2, $3) } + Directive :: { String } : "`celldefine" { tokenString $1 } | "`endcelldefine" { tokenString $1 } @@ -1742,4 +1769,8 @@ makeEnumItems (_, root) (l, r) base = then reverse [r..l] else [l..r] +makeDPIImport :: String -> DPIImportProperty -> Identifier + -> (Type, Identifier, [Decl]) -> PackageItem +makeDPIImport a b c (d, e, f) = DPIImport a b c d e f + } diff --git a/test/nosim/dpi.sv b/test/nosim/dpi.sv new file mode 100644 index 0000000..c73a119 --- /dev/null +++ b/test/nosim/dpi.sv @@ -0,0 +1,38 @@ +module top; + +/* From IEEE 1800-2017 Section 35.4 */ + +export "DPI-C" f_plus = function \f+ ; // "f+" exported as "f_plus" +export "DPI-C" function f; // "f" exported under its own name +import "DPI-C" init_1 = function void \init[1] (); // "init_1" is a linkage name +import "DPI-C" \begin = function void \init[2] (); // "begin" is a linkage name + +/* From IEEE 1800-2017 Section 35.5.4 */ + +import "DPI-C" function void myInit(); + +// from standard math library +import "DPI-C" pure function real sin(real foo /* TODO support unnamed params */ ); + +// from standard C library: memory management +import "DPI-C" function chandle malloc(int size); // standard C function +import "DPI-C" function void free(chandle ptr); // standard C functionS + +// abstract data structure: queue +import "DPI-C" function chandle newQueue(input string name_of_queue); + +// Note the following import uses the same foreign function for +// implementation as the prior import, but has different SystemVerilog name +// and provides a default value for the argument. +import "DPI-C" newQueue=function chandle newAnonQueue(input string s/* =null TODO support default values */); +import "DPI-C" function chandle newElem(bit [15:0] foo /* TODO support unnamed params */ ); +import "DPI-C" function void enqueue(chandle queue, chandle elem); +import "DPI-C" function chandle dequeue(chandle queue); + +// miscellanea +import "DPI-C" function bit [15:0] getStimulus(input integer x); +import "DPI-C" context function void processTransaction(chandle elem, +output logic [64:1] arr [0:63]); +import "DPI-C" task checkResults(input string s, bit [511:0] packet); + +endmodule