Commit d47c5493 by Zachary Snow

added logic to module items; toying with initial Conversion

parent d36e5bfe
{- 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
......
......@@ -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
......
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