Commit 5fae85e6 by Zachary Snow

very preliminary support for typedefs

parent f11f1efe
......@@ -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
......
{- 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
( 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 }
......
{
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
......
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