mirror of https://github.com/zachjs/sv2v.git
very preliminary support for typedefs
This commit is contained in:
parent
f11f1efea1
commit
5fae85e6cd
14
Convert.hs
14
Convert.hs
|
|
@ -10,22 +10,24 @@ import Language.SystemVerilog.AST
|
|||
|
||||
import qualified Convert.AlwaysKW
|
||||
import qualified Convert.Logic
|
||||
import qualified Convert.Typedef
|
||||
|
||||
type Phase = [Module] -> [Module]
|
||||
type Phase = AST -> AST
|
||||
|
||||
phases :: [Phase]
|
||||
phases =
|
||||
[ Convert.AlwaysKW.convert
|
||||
, Convert.Logic.convert
|
||||
, Convert.Typedef.convert
|
||||
]
|
||||
|
||||
run :: Phase
|
||||
run = foldr (.) id phases
|
||||
|
||||
convert :: Phase
|
||||
convert modules =
|
||||
let modules' = run modules
|
||||
convert descriptions =
|
||||
let descriptions' = run descriptions
|
||||
in
|
||||
if modules == modules'
|
||||
then modules
|
||||
else convert modules'
|
||||
if descriptions == descriptions'
|
||||
then descriptions
|
||||
else convert descriptions'
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import Convert.Template.ModuleItem (moduleItemConverter)
|
|||
|
||||
import Language.SystemVerilog.AST
|
||||
|
||||
convert :: [Module] -> [Module]
|
||||
convert :: AST -> AST
|
||||
convert = moduleItemConverter convertModuleItem
|
||||
|
||||
-- Conversions:
|
||||
|
|
|
|||
|
|
@ -19,14 +19,15 @@ import Language.SystemVerilog.AST
|
|||
|
||||
type RegIdents = Set.Set String
|
||||
|
||||
convert :: [Module] -> [Module]
|
||||
convert modules = map convertModule modules
|
||||
convert :: AST -> AST
|
||||
convert descriptions = map convertDescription descriptions
|
||||
|
||||
convertModule :: Module -> Module
|
||||
convertModule (Module name ports items) =
|
||||
convertDescription :: Description -> Description
|
||||
convertDescription (Module name ports items) =
|
||||
Module name ports $ map (convertModuleItem idents) items
|
||||
where
|
||||
idents = Set.unions $ map getRegIdents items
|
||||
convertDescription other = other
|
||||
|
||||
getStmtLHSs :: Stmt -> [LHS]
|
||||
getStmtLHSs (Block _ stmts) = concat $ map getStmtLHSs stmts
|
||||
|
|
|
|||
|
|
@ -13,15 +13,16 @@ import Language.SystemVerilog.AST
|
|||
|
||||
type Converter = ModuleItem -> ModuleItem
|
||||
|
||||
moduleItemConverter :: Converter -> ([Module] -> [Module])
|
||||
moduleItemConverter :: Converter -> (AST -> AST)
|
||||
moduleItemConverter f = convert f
|
||||
|
||||
convert :: Converter -> [Module] -> [Module]
|
||||
convert f modules = map (convertModule f) modules
|
||||
convert :: Converter -> AST -> AST
|
||||
convert f modules = map (convertDescription f) modules
|
||||
|
||||
convertModule :: Converter -> Module -> Module
|
||||
convertModule f (Module name ports items) =
|
||||
convertDescription :: Converter -> Description -> Description
|
||||
convertDescription f (Module name ports items) =
|
||||
Module name ports $ map (convertModuleItem f) items
|
||||
convertDescription _ (Typedef a b) = Typedef a b
|
||||
|
||||
convertModuleItem :: Converter -> ModuleItem -> ModuleItem
|
||||
convertModuleItem f (Generate items) = f $ Generate $ map (convertGenItem f) items
|
||||
|
|
|
|||
|
|
@ -0,0 +1,56 @@
|
|||
{- sv2v
|
||||
- Author: Zachary Snow <zach@zachjs.com>
|
||||
-
|
||||
- Conversion for `typedef`
|
||||
-}
|
||||
|
||||
-- TODO: Right now we only support typedefs for module data items. Function
|
||||
-- parameters, block items, etc., probably support typedefs, too.
|
||||
|
||||
module Convert.Typedef (convert) where
|
||||
|
||||
import Data.Maybe
|
||||
import qualified Data.Map as Map
|
||||
|
||||
import Language.SystemVerilog.AST
|
||||
|
||||
type Types = Map.Map Identifier Type
|
||||
|
||||
convert :: AST -> AST
|
||||
convert descriptions =
|
||||
filter (not . isTypedef) $ map (convertDescription types) descriptions
|
||||
where
|
||||
types = Map.fromList $ mapMaybe getTypedef descriptions
|
||||
getTypedef :: Description -> Maybe (Identifier, Type)
|
||||
getTypedef (Typedef a b) = Just (b, a)
|
||||
getTypedef _ = Nothing
|
||||
|
||||
isTypedef :: Description -> Bool
|
||||
isTypedef (Typedef _ _) = True
|
||||
isTypedef _ = False
|
||||
|
||||
convertDescription :: Types -> Description -> Description
|
||||
convertDescription types (Module name ports items) =
|
||||
Module name ports $ map (convertModuleItem types) items
|
||||
convertDescription _ other = other
|
||||
|
||||
resolveType :: Types -> Type -> Type
|
||||
resolveType _ (Reg mr) = Reg mr
|
||||
resolveType _ (Wire mr) = Wire mr
|
||||
resolveType _ (Logic mr) = Logic mr
|
||||
resolveType types (Alias st mr1) =
|
||||
case resolveType types $ types Map.! st of
|
||||
(Reg mr2) -> Reg $ combineRanges mr1 mr2
|
||||
(Wire mr2) -> Wire $ combineRanges mr1 mr2
|
||||
(Logic mr2) -> Logic $ combineRanges mr1 mr2
|
||||
(Alias _ _) -> error $ "resolveType invariant failed on " ++ st
|
||||
where
|
||||
combineRanges :: Maybe Range -> Maybe Range -> Maybe Range
|
||||
combineRanges Nothing other = other
|
||||
combineRanges other Nothing = other
|
||||
combineRanges _ _ = error $ "alias " ++ st ++ " leads to 2-D vectorized type"
|
||||
|
||||
convertModuleItem :: Types -> ModuleItem -> ModuleItem
|
||||
convertModuleItem types (LocalNet t ident val) =
|
||||
LocalNet (resolveType types t) ident val
|
||||
convertModuleItem _ other = other
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
module Language.SystemVerilog.AST
|
||||
( Identifier
|
||||
, Module (..)
|
||||
, Description(..)
|
||||
, ModuleItem (..)
|
||||
, Direction (..)
|
||||
, Type (..)
|
||||
|
|
@ -16,6 +16,7 @@ module Language.SystemVerilog.AST
|
|||
, IntegerV (..)
|
||||
, GenItem (..)
|
||||
, AlwaysKW (..)
|
||||
, AST
|
||||
, PortBinding
|
||||
, Case
|
||||
, Range
|
||||
|
|
@ -38,12 +39,15 @@ type Identifier = String
|
|||
-- basing invariant checks. I want to avoid making a full type-checker though,
|
||||
-- as we should only be given valid SystemVerilog input files.
|
||||
|
||||
data Module
|
||||
type AST = [Description]
|
||||
|
||||
data Description
|
||||
= Module Identifier [Identifier] [ModuleItem]
|
||||
| Typedef Type Identifier
|
||||
deriving Eq
|
||||
|
||||
instance Show Module where
|
||||
showList modules _ = intercalate "\n" $ map show modules
|
||||
instance Show Description where
|
||||
showList descriptions _ = intercalate "\n" $ map show descriptions
|
||||
show (Module name ports items) = unlines
|
||||
[ "module " ++ name ++ portsStr ++ ";"
|
||||
, indent $ unlines' $ map show items
|
||||
|
|
@ -53,6 +57,7 @@ instance Show Module where
|
|||
if null ports
|
||||
then ""
|
||||
else indentedParenList ports
|
||||
show (Typedef t x) = printf "typedef %s %s;" (show t) x
|
||||
|
||||
data Direction
|
||||
= Input
|
||||
|
|
@ -69,12 +74,14 @@ data Type
|
|||
= Reg (Maybe Range)
|
||||
| Wire (Maybe Range)
|
||||
| Logic (Maybe Range)
|
||||
| Alias String (Maybe Range)
|
||||
deriving Eq
|
||||
|
||||
instance Show Type where
|
||||
show (Reg r) = "reg " ++ (showRange r)
|
||||
show (Wire r) = "wire " ++ (showRange r)
|
||||
show (Logic r) = "logic " ++ (showRange r)
|
||||
show (Alias t r) = t ++ " " ++ (showRange r)
|
||||
|
||||
data ModuleItem
|
||||
= Comment String
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@ import Language.SystemVerilog.Parser.Preprocess
|
|||
import Language.SystemVerilog.Parser.Tokens
|
||||
|
||||
-- | Parses a file given a table of predefined macros, the file name, and the file contents.
|
||||
parseFile :: [(String, String)] -> FilePath -> String -> [Module]
|
||||
parseFile env file content = modules tokens
|
||||
parseFile :: [(String, String)] -> FilePath -> String -> AST
|
||||
parseFile env file content = descriptions tokens
|
||||
where
|
||||
tokens = map relocate $ alexScanTokens $ preprocess env file content
|
||||
relocate :: Token -> Token
|
||||
|
|
|
|||
|
|
@ -82,6 +82,7 @@ tokens :-
|
|||
"parameter" { tok KW_parameter }
|
||||
"posedge" { tok KW_posedge }
|
||||
"reg" { tok KW_reg }
|
||||
"typedef" { tok KW_typedef }
|
||||
"wire" { tok KW_wire }
|
||||
|
||||
@simpleIdentifier { tok Id_simple }
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
module Language.SystemVerilog.Parser.Parse (modules) where
|
||||
module Language.SystemVerilog.Parser.Parse (descriptions) where
|
||||
|
||||
import Data.Bits
|
||||
import Data.List
|
||||
|
|
@ -9,7 +9,7 @@ import Language.SystemVerilog.AST
|
|||
import Language.SystemVerilog.Parser.Tokens
|
||||
}
|
||||
|
||||
%name modules
|
||||
%name descriptions
|
||||
%tokentype { Token }
|
||||
%error { parseError }
|
||||
|
||||
|
|
@ -50,6 +50,7 @@ import Language.SystemVerilog.Parser.Tokens
|
|||
"parameter" { Token KW_parameter _ _ }
|
||||
"posedge" { Token KW_posedge _ _ }
|
||||
"reg" { Token KW_reg _ _ }
|
||||
"typedef" { Token KW_typedef _ _ }
|
||||
"wire" { Token KW_wire _ _ }
|
||||
|
||||
simpleIdentifier { Token Id_simple _ _ }
|
||||
|
|
@ -164,14 +165,27 @@ opt(p) :: { Maybe a }
|
|||
: p { Just $1 }
|
||||
| { Nothing }
|
||||
|
||||
Modules :: { [Module] }
|
||||
Descriptions :: { [Description] }
|
||||
: {- empty -} { [] }
|
||||
| Modules Module { $1 ++ [$2] }
|
||||
| Descriptions Description { $1 ++ [$2] }
|
||||
|
||||
Module :: { Module }
|
||||
: "module" Identifier Params ";" ModuleItems "endmodule" opt(";") { Module $2 [] ($3 ++ $5) }
|
||||
| "module" Identifier Params PortNames ";" ModuleItems "endmodule" opt(";") { Module $2 $4 ($3 ++ $6) }
|
||||
| "module" Identifier Params PortDecls ";" ModuleItems "endmodule" opt(";") { Module $2 (getPortNames $4) ($3 ++ $4 ++ $6) }
|
||||
Description :: { Description }
|
||||
: Module opt(";") { $1 }
|
||||
| Typedef opt(";") { $1 }
|
||||
|
||||
Typedef :: { Description }
|
||||
: "typedef" Type Identifier ";" { Typedef $2 $3 }
|
||||
|
||||
Type :: { Type }
|
||||
: "wire" opt(Range) { Wire $2 }
|
||||
| "reg" opt(Range) { Reg $2 }
|
||||
| "logic" opt(Range) { Logic $2 }
|
||||
| Identifier opt(Range) { Alias $1 $2 }
|
||||
|
||||
Module :: { Description }
|
||||
: "module" Identifier Params ";" ModuleItems "endmodule" { Module $2 [] ($3 ++ $5) }
|
||||
| "module" Identifier Params PortNames ";" ModuleItems "endmodule" { Module $2 $4 ($3 ++ $6) }
|
||||
| "module" Identifier Params PortDecls ";" ModuleItems "endmodule" { Module $2 (getPortNames $4) ($3 ++ $4 ++ $6) }
|
||||
|
||||
Params :: { [ModuleItem] }
|
||||
: {- empty -} { [] }
|
||||
|
|
@ -224,14 +238,17 @@ ModuleItems :: { [ModuleItem] }
|
|||
|
||||
ModuleItem :: { [ModuleItem] }
|
||||
: PortDecl(";") { $1 }
|
||||
| "reg" opt(Range) VariableIdentifiers ";" { map (uncurry $ LocalNet $ Reg $2) $3 }
|
||||
| "wire" opt(Range) VariableIdentifiers ";" { map (uncurry $ LocalNet $ Wire $2) $3 }
|
||||
| "logic" opt(Range) VariableIdentifiers ";" { map (uncurry $ LocalNet $ Logic $2) $3 }
|
||||
-- TODO: Allowing Ranges on aliases creates conflicts
|
||||
| Identifier VariableIdentifiers ";" { map (uncurry $ LocalNet (Alias $1 Nothing)) $2 }
|
||||
| "wire" opt(Range) VariableIdentifiers ";" { map (uncurry $ LocalNet $ Wire $2) $3 }
|
||||
| "reg" opt(Range) VariableIdentifiers ";" { map (uncurry $ LocalNet $ Reg $2) $3 }
|
||||
| "logic" opt(Range) VariableIdentifiers ";" { map (uncurry $ LocalNet $ Logic $2) $3 }
|
||||
| ParameterDeclaration { map MIParameter $1 }
|
||||
| LocalparamDeclaration { map MILocalparam $1 }
|
||||
| IntegerDeclaration { map MIIntegerV $1 }
|
||||
| "assign" LHS "=" Expr ";" { [Assign $2 $4] }
|
||||
| AlwaysKW Stmt { [AlwaysC $1 $2] }
|
||||
| Identifier ModuleInstantiations ";" { map (uncurry $ Instance $1 []) $2 }
|
||||
| Identifier ParameterBindings ModuleInstantiations ";" { map (uncurry $ Instance $1 $2) $3 }
|
||||
| "function" opt(RangeOrType) Identifier FunctionItems Stmt "endfunction" { [Function $2 $3 $4 $5] }
|
||||
| "genvar" Identifiers ";" { map Genvar $2 }
|
||||
|
|
@ -337,8 +354,7 @@ Binding :: { (Identifier, Maybe Expr) }
|
|||
| Expr { ("", Just $1) }
|
||||
|
||||
ParameterBindings :: { [(Identifier, Maybe Expr)] }
|
||||
: {- empty -} { [] }
|
||||
| "#" "(" BindingsNonEmpty ")" { $3 }
|
||||
: "#" "(" BindingsNonEmpty ")" { $3 }
|
||||
|
||||
Stmts :: { [Stmt] }
|
||||
: {- empty -} { [] }
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ executable sv2v
|
|||
Convert
|
||||
Convert.AlwaysKW
|
||||
Convert.Logic
|
||||
Convert.Typedef
|
||||
Convert.Template.ModuleItem
|
||||
ghc-options:
|
||||
-O3
|
||||
|
|
|
|||
Loading…
Reference in New Issue