mirror of https://github.com/zachjs/sv2v.git
fix inefficiencies in logic conversion
- don't evaluate AST after procedural assignment collection - don't use State monad during rewrite - use Writer rather than State for procedural assignment collection - use Scoper access generation shortcut utility - cleanup as-patterns and legacy logic
This commit is contained in:
parent
5b2165d7a8
commit
69e66a215e
|
|
@ -25,7 +25,6 @@
|
||||||
|
|
||||||
module Convert.Logic (convert) where
|
module Convert.Logic (convert) where
|
||||||
|
|
||||||
import Control.Monad.State.Strict
|
|
||||||
import Control.Monad.Writer.Strict
|
import Control.Monad.Writer.Strict
|
||||||
import qualified Data.Map.Strict as Map
|
import qualified Data.Map.Strict as Map
|
||||||
import qualified Data.Set as Set
|
import qualified Data.Set as Set
|
||||||
|
|
@ -37,7 +36,7 @@ import Language.SystemVerilog.AST
|
||||||
type Ports = Map.Map Identifier [(Identifier, Direction)]
|
type Ports = Map.Map Identifier [(Identifier, Direction)]
|
||||||
type Location = [Identifier]
|
type Location = [Identifier]
|
||||||
type Locations = Set.Set Location
|
type Locations = Set.Set Location
|
||||||
type ST = ScoperT Type (State Locations)
|
type ST = ScoperT Type (Writer Locations)
|
||||||
|
|
||||||
convert :: [AST] -> [AST]
|
convert :: [AST] -> [AST]
|
||||||
convert =
|
convert =
|
||||||
|
|
@ -46,7 +45,7 @@ convert =
|
||||||
(traverseDescriptions . convertDescription)
|
(traverseDescriptions . convertDescription)
|
||||||
where
|
where
|
||||||
collectPortsM :: Description -> Writer Ports ()
|
collectPortsM :: Description -> Writer Ports ()
|
||||||
collectPortsM (orig @ (Part _ _ _ _ name portNames _)) =
|
collectPortsM orig@(Part _ _ _ _ name portNames _) =
|
||||||
tell $ Map.singleton name ports
|
tell $ Map.singleton name ports
|
||||||
where
|
where
|
||||||
ports = zip portNames (map lookupDir portNames)
|
ports = zip portNames (map lookupDir portNames)
|
||||||
|
|
@ -58,34 +57,24 @@ convert =
|
||||||
Nothing -> Inout
|
Nothing -> Inout
|
||||||
collectPortsM _ = return ()
|
collectPortsM _ = return ()
|
||||||
collectDeclDirsM :: ModuleItem -> Writer [(Identifier, Direction)] ()
|
collectDeclDirsM :: ModuleItem -> Writer [(Identifier, Direction)] ()
|
||||||
collectDeclDirsM (MIPackageItem (Decl (Variable dir t ident _ _))) =
|
collectDeclDirsM (MIPackageItem (Decl (Variable dir _ ident _ _))) =
|
||||||
case (dir, t) of
|
when (dir /= Local) $ tell [(ident, dir)]
|
||||||
(_, InterfaceT{}) -> tell [(ident, Local)]
|
collectDeclDirsM (MIPackageItem (Decl (Net dir _ _ _ ident _ _))) =
|
||||||
(Local, _) -> return ()
|
when (dir /= Local) $ tell [(ident, dir)]
|
||||||
_ -> tell [(ident, dir)]
|
|
||||||
collectDeclDirsM (MIPackageItem (Decl net @ Net{})) =
|
|
||||||
collectNetAsVarM (collectDeclDirsM . MIPackageItem . Decl) net
|
|
||||||
collectDeclDirsM _ = return ()
|
collectDeclDirsM _ = return ()
|
||||||
|
|
||||||
convertDescription :: Ports -> Description -> Description
|
convertDescription :: Ports -> Description -> Description
|
||||||
convertDescription ports (description @ (Part _ _ Module _ _ _ _)) =
|
convertDescription ports description@(Part _ _ Module _ _ _ _) =
|
||||||
evalState (operation description) Set.empty
|
-- rewrite reg continuous assignments and output port connections
|
||||||
|
partScoper (rewriteDeclM locations) (traverseModuleItemM ports)
|
||||||
|
return return description
|
||||||
where
|
where
|
||||||
operation =
|
-- write down which vars are procedurally assigned
|
||||||
-- log then rewrite
|
locations = execWriter $ partScoperT
|
||||||
partScoperT td tm tg ts >=>
|
traverseDeclM return return traverseStmtM description
|
||||||
partScoperT rd tm tg ts
|
|
||||||
td = traverseDeclM
|
|
||||||
rd = rewriteDeclM
|
|
||||||
tm = traverseModuleItemM ports
|
|
||||||
tg = traverseGenItemM
|
|
||||||
ts = traverseStmtM
|
|
||||||
convertDescription _ other = other
|
convertDescription _ other = other
|
||||||
|
|
||||||
traverseGenItemM :: GenItem -> ST GenItem
|
traverseModuleItemM :: Ports -> ModuleItem -> Scoper Type ModuleItem
|
||||||
traverseGenItemM = return
|
|
||||||
|
|
||||||
traverseModuleItemM :: Ports -> ModuleItem -> ST ModuleItem
|
|
||||||
traverseModuleItemM ports = embedScopes $ traverseModuleItem ports
|
traverseModuleItemM ports = embedScopes $ traverseModuleItem ports
|
||||||
|
|
||||||
traverseModuleItem :: Ports -> Scopes Type -> ModuleItem -> ModuleItem
|
traverseModuleItem :: Ports -> Scopes Type -> ModuleItem -> ModuleItem
|
||||||
|
|
@ -162,65 +151,58 @@ traverseModuleItem ports scopes =
|
||||||
fixModuleItem other = other
|
fixModuleItem other = other
|
||||||
|
|
||||||
traverseDeclM :: Decl -> ST Decl
|
traverseDeclM :: Decl -> ST Decl
|
||||||
traverseDeclM (decl @ (Variable _ t x _ _)) =
|
traverseDeclM decl@(Variable _ t x _ _) =
|
||||||
insertElem x t >> return decl
|
insertElem x t >> return decl
|
||||||
traverseDeclM (decl @ (Net _ _ _ t x _ _)) =
|
traverseDeclM decl@(Net _ _ _ t x _ _) =
|
||||||
insertElem x t >> return decl
|
insertElem x t >> return decl
|
||||||
traverseDeclM decl = return decl
|
traverseDeclM decl = return decl
|
||||||
|
|
||||||
rewriteDeclM :: Decl -> ST Decl
|
rewriteDeclM :: Locations -> Decl -> Scoper Type Decl
|
||||||
rewriteDeclM (Variable d (t @ (IntegerVector TLogic sg rs)) x a e) = do
|
rewriteDeclM locations (Variable d (IntegerVector TLogic sg rs) x a e) = do
|
||||||
insertElem x t
|
accesses <- localAccessesM x
|
||||||
details <- lookupElemM x
|
|
||||||
let Just (accesses, _, _) = details
|
|
||||||
let location = map accessName accesses
|
let location = map accessName accesses
|
||||||
usedAsReg <- lift $ gets $ Set.member location
|
let usedAsReg = Set.member location locations
|
||||||
blockLogic <- withinProcedureM
|
blockLogic <- withinProcedureM
|
||||||
if usedAsReg || blockLogic || e /= Nil
|
if blockLogic || usedAsReg || e /= Nil
|
||||||
then do
|
then do
|
||||||
let d' = if d == Inout then Output else d
|
let d' = if d == Inout then Output else d
|
||||||
let t' = IntegerVector TReg sg rs
|
let t' = IntegerVector TReg sg rs
|
||||||
insertElem x t'
|
insertElem accesses t'
|
||||||
return $ Variable d' t' x a e
|
return $ Variable d' t' x a e
|
||||||
else do
|
else do
|
||||||
let t' = Implicit sg rs
|
let t' = Implicit sg rs
|
||||||
insertElem x t'
|
insertElem accesses t'
|
||||||
return $ Net d TWire DefaultStrength t' x a e
|
return $ Net d TWire DefaultStrength t' x a e
|
||||||
rewriteDeclM (decl @ (Variable _ t x _ _)) =
|
rewriteDeclM _ decl@(Variable _ t x _ _) =
|
||||||
insertElem x t >> return decl
|
insertElem x t >> return decl
|
||||||
rewriteDeclM (Net d n s (IntegerVector _ sg rs) x a e) =
|
rewriteDeclM _ (Net d n s (IntegerVector _ sg rs) x a e) =
|
||||||
insertElem x t >> return (Net d n s t x a e)
|
insertElem x t >> return (Net d n s t x a e)
|
||||||
where t = Implicit sg rs
|
where t = Implicit sg rs
|
||||||
rewriteDeclM (decl @ (Net _ _ _ t x _ _)) =
|
rewriteDeclM _ decl@(Net _ _ _ t x _ _) =
|
||||||
insertElem x t >> return decl
|
insertElem x t >> return decl
|
||||||
rewriteDeclM (Param s (IntegerVector _ sg []) x e) =
|
rewriteDeclM _ (Param s (IntegerVector _ sg []) x e) =
|
||||||
return $ Param s (Implicit sg [(zero, zero)]) x e
|
return $ Param s (Implicit sg [(zero, zero)]) x e
|
||||||
where zero = RawNum 0
|
where zero = RawNum 0
|
||||||
rewriteDeclM (Param s (IntegerVector _ sg rs) x e) =
|
rewriteDeclM _ (Param s (IntegerVector _ sg rs) x e) =
|
||||||
return $ Param s (Implicit sg rs) x e
|
return $ Param s (Implicit sg rs) x e
|
||||||
rewriteDeclM decl = return decl
|
rewriteDeclM _ decl = return decl
|
||||||
|
|
||||||
traverseStmtM :: Stmt -> ST Stmt
|
traverseStmtM :: Stmt -> ST Stmt
|
||||||
traverseStmtM (Timing timing stmt) =
|
traverseStmtM stmt@Timing{} =
|
||||||
-- ignore the timing LHSs
|
-- ignore the timing LHSs
|
||||||
return $ Timing timing stmt
|
|
||||||
traverseStmtM (Subroutine (Ident f) args) = do
|
|
||||||
case args of
|
|
||||||
Args (_ : Ident x : _) [] ->
|
|
||||||
if f == "$readmemh" || f == "$readmemb"
|
|
||||||
then collectLHSM $ LHSIdent x
|
|
||||||
else return ()
|
|
||||||
_ -> return ()
|
|
||||||
return $ Subroutine (Ident f) args
|
|
||||||
traverseStmtM stmt = do
|
|
||||||
collectStmtLHSsM (collectNestedLHSsM collectLHSM) stmt
|
|
||||||
return stmt
|
return stmt
|
||||||
|
traverseStmtM stmt@(Subroutine (Ident f) (Args (_ : Ident x : _) [])) =
|
||||||
|
when (f == "$readmemh" || f == "$readmemb") (collectLHSM $ LHSIdent x)
|
||||||
|
>> return stmt
|
||||||
|
traverseStmtM stmt =
|
||||||
|
collectStmtLHSsM (collectNestedLHSsM collectLHSM) stmt
|
||||||
|
>> return stmt
|
||||||
|
|
||||||
collectLHSM :: LHS -> ST ()
|
collectLHSM :: LHS -> ST ()
|
||||||
collectLHSM lhs = do
|
collectLHSM lhs = do
|
||||||
details <- lookupElemM lhs
|
details <- lookupElemM lhs
|
||||||
case details of
|
case details of
|
||||||
Just (accesses, _, _) -> do
|
Just (accesses, _, _) ->
|
||||||
let location = map accessName accesses
|
lift $ tell $ Set.singleton location
|
||||||
lift $ modify $ Set.insert location
|
where location = map accessName accesses
|
||||||
Nothing -> return ()
|
Nothing -> return ()
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue