mirror of https://github.com/zachjs/sv2v.git
66 lines
2.3 KiB
Haskell
66 lines
2.3 KiB
Haskell
{- sv2v
|
|
- Author: Zachary Snow <zach@zachjs.com>
|
|
-
|
|
- Conversion for `logic`
|
|
-}
|
|
|
|
-- 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.
|
|
|
|
-- It seems like logic only becomes reg if it is assigned to in an always block.
|
|
|
|
module Convert.Logic (convert) where
|
|
|
|
import Control.Monad.Writer
|
|
import qualified Data.Set as Set
|
|
|
|
import Convert.Traverse
|
|
import Language.SystemVerilog.AST
|
|
|
|
type RegIdents = Set.Set String
|
|
|
|
convert :: AST -> AST
|
|
convert = traverseDescriptions convertDescription
|
|
|
|
convertDescription :: Description -> Description
|
|
convertDescription orig =
|
|
if shouldConvert
|
|
then traverseModuleItems conversion orig
|
|
else orig
|
|
where
|
|
shouldConvert = case orig of
|
|
Part _ Interface _ _ _ _ -> False
|
|
Part _ Module _ _ _ _ -> True
|
|
PackageItem _ -> True
|
|
Directive _ -> False
|
|
conversion = traverseDecls convertDecl . convertModuleItem
|
|
idents = execWriter (collectModuleItemsM regIdents orig)
|
|
convertModuleItem :: ModuleItem -> ModuleItem
|
|
convertModuleItem (MIDecl (Variable dir (IntegerVector TLogic sg mr) ident a me)) =
|
|
MIDecl $ Variable dir (t mr) ident a me
|
|
where
|
|
t = if sg /= Unspecified || Set.member ident idents
|
|
then IntegerVector TReg sg
|
|
else Net TWire
|
|
convertModuleItem other = other
|
|
-- all other logics (i.e. inside of functions) become regs
|
|
convertDecl :: Decl -> Decl
|
|
convertDecl (Variable d (IntegerVector TLogic sg rs) x a me) =
|
|
Variable d (IntegerVector TReg sg rs) x a me
|
|
convertDecl other = other
|
|
|
|
regIdents :: ModuleItem -> Writer RegIdents ()
|
|
regIdents (AlwaysC _ stmt) =
|
|
collectStmtLHSsM (collectNestedLHSsM idents) $
|
|
traverseNestedStmts removeTimings stmt
|
|
where
|
|
idents :: LHS -> Writer RegIdents ()
|
|
idents (LHSIdent vx ) = tell $ Set.singleton vx
|
|
idents _ = return () -- the collector recurses for us
|
|
removeTimings :: Stmt -> Stmt
|
|
removeTimings (Timing _ s) = s
|
|
removeTimings other = other
|
|
regIdents _ = return ()
|