Commit 5fae85e6 by Zachary Snow

very preliminary support for typedefs

parent f11f1efe
...@@ -10,22 +10,24 @@ import Language.SystemVerilog.AST ...@@ -10,22 +10,24 @@ import Language.SystemVerilog.AST
import qualified Convert.AlwaysKW import qualified Convert.AlwaysKW
import qualified Convert.Logic import qualified Convert.Logic
import qualified Convert.Typedef
type Phase = [Module] -> [Module] type Phase = AST -> AST
phases :: [Phase] phases :: [Phase]
phases = phases =
[ Convert.AlwaysKW.convert [ Convert.AlwaysKW.convert
, Convert.Logic.convert , Convert.Logic.convert
, Convert.Typedef.convert
] ]
run :: Phase run :: Phase
run = foldr (.) id phases run = foldr (.) id phases
convert :: Phase convert :: Phase
convert modules = convert descriptions =
let modules' = run modules let descriptions' = run descriptions
in in
if modules == modules' if descriptions == descriptions'
then modules then descriptions
else convert modules' else convert descriptions'
...@@ -10,7 +10,7 @@ import Convert.Template.ModuleItem (moduleItemConverter) ...@@ -10,7 +10,7 @@ import Convert.Template.ModuleItem (moduleItemConverter)
import Language.SystemVerilog.AST import Language.SystemVerilog.AST
convert :: [Module] -> [Module] convert :: AST -> AST
convert = moduleItemConverter convertModuleItem convert = moduleItemConverter convertModuleItem
-- Conversions: -- Conversions:
......
...@@ -19,14 +19,15 @@ import Language.SystemVerilog.AST ...@@ -19,14 +19,15 @@ import Language.SystemVerilog.AST
type RegIdents = Set.Set String type RegIdents = Set.Set String
convert :: [Module] -> [Module] convert :: AST -> AST
convert modules = map convertModule modules convert descriptions = map convertDescription descriptions
convertModule :: Module -> Module convertDescription :: Description -> Description
convertModule (Module name ports items) = convertDescription (Module name ports items) =
Module name ports $ map (convertModuleItem idents) items Module name ports $ map (convertModuleItem idents) items
where where
idents = Set.unions $ map getRegIdents items idents = Set.unions $ map getRegIdents items
convertDescription other = other
getStmtLHSs :: Stmt -> [LHS] getStmtLHSs :: Stmt -> [LHS]
getStmtLHSs (Block _ stmts) = concat $ map getStmtLHSs stmts getStmtLHSs (Block _ stmts) = concat $ map getStmtLHSs stmts
......
...@@ -13,15 +13,16 @@ import Language.SystemVerilog.AST ...@@ -13,15 +13,16 @@ import Language.SystemVerilog.AST
type Converter = ModuleItem -> ModuleItem type Converter = ModuleItem -> ModuleItem
moduleItemConverter :: Converter -> ([Module] -> [Module]) moduleItemConverter :: Converter -> (AST -> AST)
moduleItemConverter f = convert f moduleItemConverter f = convert f
convert :: Converter -> [Module] -> [Module] convert :: Converter -> AST -> AST
convert f modules = map (convertModule f) modules convert f modules = map (convertDescription f) modules
convertModule :: Converter -> Module -> Module convertDescription :: Converter -> Description -> Description
convertModule f (Module name ports items) = convertDescription f (Module name ports items) =
Module name ports $ map (convertModuleItem f) items Module name ports $ map (convertModuleItem f) items
convertDescription _ (Typedef a b) = Typedef a b
convertModuleItem :: Converter -> ModuleItem -> ModuleItem convertModuleItem :: Converter -> ModuleItem -> ModuleItem
convertModuleItem f (Generate items) = f $ Generate $ map (convertGenItem f) items convertModuleItem f (Generate items) = f $ Generate $ map (convertGenItem f) items
......
{- 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
module Language.SystemVerilog.AST module Language.SystemVerilog.AST
( Identifier ( Identifier
, Module (..) , Description(..)
, ModuleItem (..) , ModuleItem (..)
, Direction (..) , Direction (..)
, Type (..) , Type (..)
...@@ -16,6 +16,7 @@ module Language.SystemVerilog.AST ...@@ -16,6 +16,7 @@ module Language.SystemVerilog.AST
, IntegerV (..) , IntegerV (..)
, GenItem (..) , GenItem (..)
, AlwaysKW (..) , AlwaysKW (..)
, AST
, PortBinding , PortBinding
, Case , Case
, Range , Range
...@@ -38,12 +39,15 @@ type Identifier = String ...@@ -38,12 +39,15 @@ type Identifier = String
-- basing invariant checks. I want to avoid making a full type-checker though, -- basing invariant checks. I want to avoid making a full type-checker though,
-- as we should only be given valid SystemVerilog input files. -- as we should only be given valid SystemVerilog input files.
data Module type AST = [Description]
data Description
= Module Identifier [Identifier] [ModuleItem] = Module Identifier [Identifier] [ModuleItem]
| Typedef Type Identifier
deriving Eq deriving Eq
instance Show Module where instance Show Description where
showList modules _ = intercalate "\n" $ map show modules showList descriptions _ = intercalate "\n" $ map show descriptions
show (Module name ports items) = unlines show (Module name ports items) = unlines
[ "module " ++ name ++ portsStr ++ ";" [ "module " ++ name ++ portsStr ++ ";"
, indent $ unlines' $ map show items , indent $ unlines' $ map show items
...@@ -53,6 +57,7 @@ instance Show Module where ...@@ -53,6 +57,7 @@ instance Show Module where
if null ports if null ports
then "" then ""
else indentedParenList ports else indentedParenList ports
show (Typedef t x) = printf "typedef %s %s;" (show t) x
data Direction data Direction
= Input = Input
...@@ -69,12 +74,14 @@ data Type ...@@ -69,12 +74,14 @@ data Type
= Reg (Maybe Range) = Reg (Maybe Range)
| Wire (Maybe Range) | Wire (Maybe Range)
| Logic (Maybe Range) | Logic (Maybe Range)
| Alias String (Maybe Range)
deriving Eq deriving Eq
instance Show Type where instance Show Type where
show (Reg r) = "reg " ++ (showRange r) show (Reg r) = "reg " ++ (showRange r)
show (Wire r) = "wire " ++ (showRange r) show (Wire r) = "wire " ++ (showRange r)
show (Logic r) = "logic " ++ (showRange r) show (Logic r) = "logic " ++ (showRange r)
show (Alias t r) = t ++ " " ++ (showRange r)
data ModuleItem data ModuleItem
= Comment String = Comment String
......
...@@ -10,8 +10,8 @@ import Language.SystemVerilog.Parser.Preprocess ...@@ -10,8 +10,8 @@ import Language.SystemVerilog.Parser.Preprocess
import Language.SystemVerilog.Parser.Tokens import Language.SystemVerilog.Parser.Tokens
-- | Parses a file given a table of predefined macros, the file name, and the file contents. -- | Parses a file given a table of predefined macros, the file name, and the file contents.
parseFile :: [(String, String)] -> FilePath -> String -> [Module] parseFile :: [(String, String)] -> FilePath -> String -> AST
parseFile env file content = modules tokens parseFile env file content = descriptions tokens
where where
tokens = map relocate $ alexScanTokens $ preprocess env file content tokens = map relocate $ alexScanTokens $ preprocess env file content
relocate :: Token -> Token relocate :: Token -> Token
......
...@@ -82,6 +82,7 @@ tokens :- ...@@ -82,6 +82,7 @@ tokens :-
"parameter" { tok KW_parameter } "parameter" { tok KW_parameter }
"posedge" { tok KW_posedge } "posedge" { tok KW_posedge }
"reg" { tok KW_reg } "reg" { tok KW_reg }
"typedef" { tok KW_typedef }
"wire" { tok KW_wire } "wire" { tok KW_wire }
@simpleIdentifier { tok Id_simple } @simpleIdentifier { tok Id_simple }
......
{ {
module Language.SystemVerilog.Parser.Parse (modules) where module Language.SystemVerilog.Parser.Parse (descriptions) where
import Data.Bits import Data.Bits
import Data.List import Data.List
...@@ -9,7 +9,7 @@ import Language.SystemVerilog.AST ...@@ -9,7 +9,7 @@ import Language.SystemVerilog.AST
import Language.SystemVerilog.Parser.Tokens import Language.SystemVerilog.Parser.Tokens
} }
%name modules %name descriptions
%tokentype { Token } %tokentype { Token }
%error { parseError } %error { parseError }
...@@ -50,6 +50,7 @@ import Language.SystemVerilog.Parser.Tokens ...@@ -50,6 +50,7 @@ import Language.SystemVerilog.Parser.Tokens
"parameter" { Token KW_parameter _ _ } "parameter" { Token KW_parameter _ _ }
"posedge" { Token KW_posedge _ _ } "posedge" { Token KW_posedge _ _ }
"reg" { Token KW_reg _ _ } "reg" { Token KW_reg _ _ }
"typedef" { Token KW_typedef _ _ }
"wire" { Token KW_wire _ _ } "wire" { Token KW_wire _ _ }
simpleIdentifier { Token Id_simple _ _ } simpleIdentifier { Token Id_simple _ _ }
...@@ -164,14 +165,27 @@ opt(p) :: { Maybe a } ...@@ -164,14 +165,27 @@ opt(p) :: { Maybe a }
: p { Just $1 } : p { Just $1 }
| { Nothing } | { Nothing }
Modules :: { [Module] } Descriptions :: { [Description] }
: {- empty -} { [] } : {- empty -} { [] }
| Modules Module { $1 ++ [$2] } | Descriptions Description { $1 ++ [$2] }
Module :: { Module } Description :: { Description }
: "module" Identifier Params ";" ModuleItems "endmodule" opt(";") { Module $2 [] ($3 ++ $5) } : Module opt(";") { $1 }
| "module" Identifier Params PortNames ";" ModuleItems "endmodule" opt(";") { Module $2 $4 ($3 ++ $6) } | Typedef opt(";") { $1 }
| "module" Identifier Params PortDecls ";" ModuleItems "endmodule" opt(";") { Module $2 (getPortNames $4) ($3 ++ $4 ++ $6) }
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] } Params :: { [ModuleItem] }
: {- empty -} { [] } : {- empty -} { [] }
...@@ -224,14 +238,17 @@ ModuleItems :: { [ModuleItem] } ...@@ -224,14 +238,17 @@ ModuleItems :: { [ModuleItem] }
ModuleItem :: { [ModuleItem] } ModuleItem :: { [ModuleItem] }
: PortDecl(";") { $1 } : PortDecl(";") { $1 }
| "reg" opt(Range) VariableIdentifiers ";" { map (uncurry $ LocalNet $ Reg $2) $3 } -- TODO: Allowing Ranges on aliases creates conflicts
| "wire" opt(Range) VariableIdentifiers ";" { map (uncurry $ LocalNet $ Wire $2) $3 } | Identifier VariableIdentifiers ";" { map (uncurry $ LocalNet (Alias $1 Nothing)) $2 }
| "logic" opt(Range) VariableIdentifiers ";" { map (uncurry $ LocalNet $ Logic $2) $3 } | "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 } | ParameterDeclaration { map MIParameter $1 }
| LocalparamDeclaration { map MILocalparam $1 } | LocalparamDeclaration { map MILocalparam $1 }
| IntegerDeclaration { map MIIntegerV $1 } | IntegerDeclaration { map MIIntegerV $1 }
| "assign" LHS "=" Expr ";" { [Assign $2 $4] } | "assign" LHS "=" Expr ";" { [Assign $2 $4] }
| AlwaysKW Stmt { [AlwaysC $1 $2] } | AlwaysKW Stmt { [AlwaysC $1 $2] }
| Identifier ModuleInstantiations ";" { map (uncurry $ Instance $1 []) $2 }
| Identifier ParameterBindings ModuleInstantiations ";" { map (uncurry $ Instance $1 $2) $3 } | Identifier ParameterBindings ModuleInstantiations ";" { map (uncurry $ Instance $1 $2) $3 }
| "function" opt(RangeOrType) Identifier FunctionItems Stmt "endfunction" { [Function $2 $3 $4 $5] } | "function" opt(RangeOrType) Identifier FunctionItems Stmt "endfunction" { [Function $2 $3 $4 $5] }
| "genvar" Identifiers ";" { map Genvar $2 } | "genvar" Identifiers ";" { map Genvar $2 }
...@@ -337,8 +354,7 @@ Binding :: { (Identifier, Maybe Expr) } ...@@ -337,8 +354,7 @@ Binding :: { (Identifier, Maybe Expr) }
| Expr { ("", Just $1) } | Expr { ("", Just $1) }
ParameterBindings :: { [(Identifier, Maybe Expr)] } ParameterBindings :: { [(Identifier, Maybe Expr)] }
: {- empty -} { [] } : "#" "(" BindingsNonEmpty ")" { $3 }
| "#" "(" BindingsNonEmpty ")" { $3 }
Stmts :: { [Stmt] } Stmts :: { [Stmt] }
: {- empty -} { [] } : {- empty -} { [] }
......
...@@ -62,6 +62,7 @@ executable sv2v ...@@ -62,6 +62,7 @@ executable sv2v
Convert Convert
Convert.AlwaysKW Convert.AlwaysKW
Convert.Logic Convert.Logic
Convert.Typedef
Convert.Template.ModuleItem Convert.Template.ModuleItem
ghc-options: ghc-options:
-O3 -O3
......
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