Commit 659461b8 by Zachary Snow

always construct conversion; more modular conversion approach

parent 35a75cc4
......@@ -4,106 +4,28 @@
- 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
import qualified Convert.AlwaysKW
import qualified Convert.Logic
onlyAsWire :: Possibilities
onlyAsWire = Set.fromList [AsWire]
onlyAsReg :: Possibilities
onlyAsReg = Set.fromList [AsReg]
asEither :: Possibilities
asEither = Set.fromList [AsWire, AsReg]
type Phase = [Module] -> [Module]
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 (Timing _ s) = getStmtLHSs s
getStmtLHSs (Null) = []
phases :: [Phase]
phases =
[ Convert.AlwaysKW.convert
, Convert.Logic.convert
]
getTypeInfoModuleItem :: ModulePorts -> ModuleItem -> TypeInfo
getTypeInfoModuleItem _ (Assign lhs _) =
Map.fromList $ zip (getLHSIdentifiers lhs) (repeat onlyAsWire)
getTypeInfoModuleItem _ (AlwaysC _ 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
run :: Phase
run = foldr (.) id phases
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
convert :: Phase
convert modules =
let modules' = run modules
in
if modules == modules'
then modules
else convert modules'
{- sv2v
- Author: Zachary Snow <zach@zachjs.com>
-
- Conversion for `always_comb` and `always_ff`
-}
module Convert.AlwaysKW (convert) where
import Convert.Template.ModuleItem (moduleItemConverter)
import Language.SystemVerilog.AST
convert :: [Module] -> [Module]
convert = moduleItemConverter convertModuleItem
-- Conversions:
-- `always_comb` -> `always @*`
-- `always_ff` -> `always`
convertModuleItem :: ModuleItem -> ModuleItem
convertModuleItem (AlwaysC AlwaysComb stmt) =
AlwaysC Always $ Timing SenseStar stmt
convertModuleItem (AlwaysC AlwaysFF stmt) =
AlwaysC Always stmt
convertModuleItem other = other
{- 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 qualified Data.Set as Set
import Language.SystemVerilog.AST
type RegIdents = Set.Set String
convert :: [Module] -> [Module]
convert modules = map convertModule modules
convertModule :: Module -> Module
convertModule (Module name ports items) =
Module name ports $ map (convertModuleItem idents) items
where
idents = Set.unions $ map getRegIdents items
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 (Timing _ s) = getStmtLHSs s
getStmtLHSs (Null) = []
getLHSIdents :: LHS -> [Identifier]
getLHSIdents (LHS vx ) = [vx]
getLHSIdents (LHSBit vx _) = [vx]
getLHSIdents (LHSRange vx _) = [vx]
getLHSIdents (LHSConcat lhss) = concat $ map getLHSIdents lhss
getRegIdents :: ModuleItem -> RegIdents
getRegIdents (AlwaysC _ stmt) =
Set.fromList idents
where
lhss = getStmtLHSs stmt
idents = concat $ map getLHSIdents lhss
getRegIdents _ = Set.empty
convertModuleItem :: RegIdents -> ModuleItem -> ModuleItem
convertModuleItem idents (LocalNet (Logic mr) ident val) =
LocalNet (t mr) ident val
where
t = if Set.member ident idents then Reg else Wire
convertModuleItem _ other = other
{- sv2v
- Author: Zachary Snow <zach@zachjs.com>
-
- Template converter for ModuleItem transformations
-
- Also has coverage for ModuleItems inside of generate blocks
-}
module Convert.Template.ModuleItem (moduleItemConverter) where
import Data.Maybe
import Language.SystemVerilog.AST
type Converter = ModuleItem -> ModuleItem
moduleItemConverter :: Converter -> ([Module] -> [Module])
moduleItemConverter f = convert f
convert :: Converter -> [Module] -> [Module]
convert f modules = map (convertModule f) modules
convertModule :: Converter -> Module -> Module
convertModule f (Module name ports items) =
Module name ports $ map (convertModuleItem f) items
convertModuleItem :: Converter -> ModuleItem -> ModuleItem
convertModuleItem f (Generate items) = f $ Generate $ map (convertGenItem f) items
convertModuleItem f other = f other
convertGenItem :: Converter -> GenItem -> GenItem
convertGenItem f item = convertGenItem' item
where
convertGenItem' :: GenItem -> GenItem
convertGenItem' (GenBlock x items) = GenBlock x $ map convertGenItem' items
convertGenItem' (GenFor a b c d items) = GenFor a b c d $ map convertGenItem' items
convertGenItem' (GenIf e i1 i2) = GenIf e (convertGenItem' i1) (convertGenItem' i2)
convertGenItem' (GenNull) = GenNull
convertGenItem' (GenModuleItem moduleItem) = GenModuleItem $ f moduleItem
convertGenItem' (GenCase e cases def) = GenCase e cases' def'
where
cases' = zip (map fst cases) (map (convertGenItem' . snd) cases)
def' = if def == Nothing
then Nothing
else Just $ convertGenItem' $ fromJust def
......@@ -60,6 +60,9 @@ executable sv2v
Language.SystemVerilog.Parser.Preprocess
Language.SystemVerilog.Parser.Tokens
Convert
Convert.AlwaysKW
Convert.Logic
Convert.Template.ModuleItem
ghc-options:
-O3
-threaded
......
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