mirror of https://github.com/zachjs/sv2v.git
added logic to module items; toying with initial Conversion
This commit is contained in:
parent
d36e5bfe0b
commit
d47c5493a3
|
|
@ -0,0 +1,108 @@
|
|||
{- sv2v
|
||||
- Author: Zachary Snow <zach@zachjs.com>
|
||||
-
|
||||
- SystemVerilog to Verilog conversion
|
||||
-}
|
||||
|
||||
-- XXX: Note that, for now, we're going to shove the first few conversions all
|
||||
-- into this same file, more or less. As patterns start becoming clearer, we
|
||||
-- should be making helpers to make traversing the AST much easier.
|
||||
|
||||
-- Regarding `logic` conversion: The SystemVerilog grammar has the concept of a
|
||||
-- `data_declaration`, which seems to cover things much more generally. While
|
||||
-- obviously `logic` can appear as module items or ports, they can also be
|
||||
-- function arguments, for example.
|
||||
|
||||
module Convert (convert) where
|
||||
|
||||
--import Data.List
|
||||
import Text.Printf
|
||||
import Data.Maybe
|
||||
import qualified Data.Set as Set
|
||||
import qualified Data.Map.Strict as Map
|
||||
|
||||
import Language.SystemVerilog.AST
|
||||
|
||||
data Possibility = AsWire | AsReg deriving (Eq, Ord)
|
||||
type Possibilities = Set.Set Possibility
|
||||
type TypeInfo = Map.Map String Possibilities
|
||||
type ModulePorts = Map.Map String [Direction]
|
||||
|
||||
-- TODO: It now seems like logic only becomes reg if it is assigned to in an
|
||||
-- always block. If this is true, it obviously could dramatically simplify this
|
||||
-- initial transformation.
|
||||
|
||||
convert :: [Module] -> [Module]
|
||||
convert modules = map (convertModule portsInfo) modules
|
||||
where
|
||||
portsInfo = Map.fromList $ map getPorts modules
|
||||
getPorts :: Module -> (Identifier, [Direction])
|
||||
getPorts (Module name ports items) =
|
||||
let portDirMap = Map.fromList $ mapMaybe getDirection items
|
||||
in (name, map (portDirMap Map.!) ports)
|
||||
where
|
||||
getDirection :: ModuleItem -> Maybe (Identifier, Direction)
|
||||
getDirection (PortDecl dir _ ident) = Just (ident, dir)
|
||||
getDirection _ = Nothing
|
||||
|
||||
convertModule :: ModulePorts -> Module -> Module
|
||||
convertModule modules (Module name ports items) =
|
||||
Module name ports (map (convertModuleItem info) items)
|
||||
where
|
||||
info = foldr (Map.unionWith Set.intersection) Map.empty (map (getTypeInfoModuleItem modules) items)
|
||||
|
||||
getLHSIdentifiers :: LHS -> [Identifier]
|
||||
getLHSIdentifiers (LHS vx ) = [vx]
|
||||
getLHSIdentifiers (LHSBit vx _) = [vx]
|
||||
getLHSIdentifiers (LHSRange vx _) = [vx]
|
||||
getLHSIdentifiers (LHSConcat lhss) = concat $ map getLHSIdentifiers lhss
|
||||
|
||||
onlyAsWire :: Possibilities
|
||||
onlyAsWire = Set.fromList [AsWire]
|
||||
onlyAsReg :: Possibilities
|
||||
onlyAsReg = Set.fromList [AsReg]
|
||||
asEither :: Possibilities
|
||||
asEither = Set.fromList [AsWire, AsReg]
|
||||
|
||||
getStmtLHSs :: Stmt -> [LHS]
|
||||
getStmtLHSs (Block _ stmts) = concat $ map getStmtLHSs stmts
|
||||
getStmtLHSs (Case e cases (Just stmt)) = (getStmtLHSs stmt) ++ (getStmtLHSs $ Case e cases Nothing)
|
||||
getStmtLHSs (Case _ cases Nothing) = concat $ map getStmtLHSs $ map snd cases
|
||||
getStmtLHSs (BlockingAssignment lhs _) = [lhs]
|
||||
getStmtLHSs (NonBlockingAssignment lhs _) = [lhs]
|
||||
getStmtLHSs (For _ _ _ stmt) = getStmtLHSs stmt
|
||||
getStmtLHSs (If _ s1 s2) = (getStmtLHSs s1) ++ (getStmtLHSs s2)
|
||||
getStmtLHSs (Null) = []
|
||||
|
||||
getTypeInfoModuleItem :: ModulePorts -> ModuleItem -> TypeInfo
|
||||
getTypeInfoModuleItem _ (Assign lhs _) =
|
||||
Map.fromList $ zip (getLHSIdentifiers lhs) (repeat onlyAsWire)
|
||||
getTypeInfoModuleItem _ (Always _ stmt) =
|
||||
Map.fromList $ zip idents (repeat onlyAsReg)
|
||||
where
|
||||
lhss = getStmtLHSs stmt
|
||||
idents = concat $ map getLHSIdentifiers lhss
|
||||
--getTypeInfoModuleItem modules (Instance name _ _ bindings) =
|
||||
-- case Map.lookup name modules of
|
||||
-- Nothing -> Map.empty
|
||||
-- Just dirs ->
|
||||
--
|
||||
-- where
|
||||
-- isDirect :: PortBinding -> Bool
|
||||
-- isDirect x = snd x == Nothing
|
||||
-- directs = map fst $ filter isDirect bindings
|
||||
--getTypeInfoModuleItem _ (Function (Maybe FuncRet) Identifier [(Bool, BlockItemDeclaration)] Stmt
|
||||
--getTypeInfoModuleItem _ (Generate [GenItem]
|
||||
getTypeInfoModuleItem _ _ = Map.empty
|
||||
|
||||
convertModuleItem :: TypeInfo -> ModuleItem -> ModuleItem
|
||||
convertModuleItem info (LocalNet (Logic mr) ident val) =
|
||||
LocalNet (t mr) ident val
|
||||
where
|
||||
t = case Map.lookup ident info of
|
||||
Nothing -> Wire
|
||||
Just possibilities ->
|
||||
if Set.member AsWire possibilities then Wire
|
||||
else if Set.member AsReg possibilities then Reg
|
||||
else error $ printf "item %s has not possibilities" ident
|
||||
convertModuleItem _ other = other
|
||||
|
|
@ -65,13 +65,15 @@ instance Show Direction where
|
|||
show Inout = "inout"
|
||||
|
||||
data Type
|
||||
= Reg (Maybe Range)
|
||||
| Wire (Maybe Range)
|
||||
= Reg (Maybe Range)
|
||||
| Wire (Maybe Range)
|
||||
| Logic (Maybe Range)
|
||||
deriving Eq
|
||||
|
||||
instance Show Type where
|
||||
show (Reg r) = "reg " ++ (showRange r)
|
||||
show (Wire r) = "wire " ++ (showRange r)
|
||||
show (Reg r) = "reg " ++ (showRange r)
|
||||
show (Wire r) = "wire " ++ (showRange r)
|
||||
show (Logic r) = "logic " ++ (showRange r)
|
||||
|
||||
data ModuleItem
|
||||
= Comment String
|
||||
|
|
|
|||
|
|
@ -78,6 +78,7 @@ tokens :-
|
|||
"input" { tok KW_input }
|
||||
"integer" { tok KW_integer }
|
||||
"localparam" { tok KW_localparam }
|
||||
"logic" { tok KW_logic }
|
||||
"module" { tok KW_module }
|
||||
"negedge" { tok KW_negedge }
|
||||
"or" { tok KW_or }
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ import Language.SystemVerilog.Parser.Tokens
|
|||
"input" { Token KW_input _ _ }
|
||||
"integer" { Token KW_integer _ _ }
|
||||
"localparam" { Token KW_localparam _ _ }
|
||||
"logic" { Token KW_logic _ _ }
|
||||
"module" { Token KW_module _ _ }
|
||||
"negedge" { Token KW_negedge _ _ }
|
||||
"or" { Token KW_or _ _ }
|
||||
|
|
@ -201,10 +202,12 @@ PortDeclsFollow :: { [ModuleItem] }
|
|||
PortDecl(delim) :: { [ModuleItem] }
|
||||
: "inout" opt(NetType) opt(Range) Identifiers delim { portDeclToModuleItems Inout $2 $3 (zip $4 (repeat Nothing)) }
|
||||
| "input" opt(NetType) opt(Range) Identifiers delim { portDeclToModuleItems Input $2 $3 (zip $4 (repeat Nothing)) }
|
||||
| "output" opt(NetType) opt(Range) Identifiers delim { portDeclToModuleItems Output $2 $3 (zip $4 (repeat Nothing)) }
|
||||
| "output" "reg" opt(Range) VariablePortIdentifiers delim { portDeclToModuleItems Output (Just Reg) $3 $4 }
|
||||
NetType
|
||||
: "wire" { Wire }
|
||||
| "output" "wire" opt(Range) Identifiers delim { portDeclToModuleItems Output (Just Wire ) $3 (zip $4 (repeat Nothing)) }
|
||||
| "output" "reg" opt(Range) VariablePortIdentifiers delim { portDeclToModuleItems Output (Just Reg ) $3 $4 }
|
||||
| "output" "logic" opt(Range) VariablePortIdentifiers delim { portDeclToModuleItems Output (Just Logic) $3 $4 }
|
||||
NetType :: { Maybe Range -> Type }
|
||||
: "wire" { Wire }
|
||||
| "logic" { Logic }
|
||||
VariablePortIdentifiers :: { [(Identifier, Maybe Expr)] }
|
||||
: VariablePortIdentifier { [$1] }
|
||||
| VariablePortIdentifiers "," VariablePortIdentifier { $1 ++ [$3] }
|
||||
|
|
@ -218,8 +221,9 @@ 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 }
|
||||
| "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 }
|
||||
| ParameterDeclaration { map MIParameter $1 }
|
||||
| LocalparamDeclaration { map MILocalparam $1 }
|
||||
| IntegerDeclaration { map MIIntegerV $1 }
|
||||
|
|
|
|||
|
|
@ -49,7 +49,8 @@ executable sv2v
|
|||
happy >= 1 && < 2
|
||||
build-depends:
|
||||
array,
|
||||
base
|
||||
base,
|
||||
containers
|
||||
other-modules:
|
||||
Language.SystemVerilog
|
||||
Language.SystemVerilog.AST
|
||||
|
|
@ -58,6 +59,7 @@ executable sv2v
|
|||
Language.SystemVerilog.Parser.Parse
|
||||
Language.SystemVerilog.Parser.Preprocess
|
||||
Language.SystemVerilog.Parser.Tokens
|
||||
Convert
|
||||
ghc-options:
|
||||
-O3
|
||||
-threaded
|
||||
|
|
|
|||
4
sv2v.hs
4
sv2v.hs
|
|
@ -10,12 +10,14 @@ import System.Environment
|
|||
|
||||
import Language.SystemVerilog.Parser
|
||||
|
||||
import Convert (convert)
|
||||
|
||||
main :: IO ()
|
||||
main = do
|
||||
[filePath] <- getArgs
|
||||
content <- readFile filePath
|
||||
let ast = parseFile [] filePath content
|
||||
let res = Right ast
|
||||
let res = Right (convert ast)
|
||||
case res of
|
||||
Left _ -> do
|
||||
--hPrint stderr err
|
||||
|
|
|
|||
Loading…
Reference in New Issue