Commit 086eb786 by Zachary Snow

elaborate accesses to fields of struct constants

parent 4533e4ff
......@@ -6,6 +6,11 @@
static prefixes, which could cause deep recursion and run out of memory on
some designs
### Other Enhancements
* Added elaboration for accesses to fields of struct constants, which can
substantially improve performance on some designs
## v0.0.10
### Breaking Changes
......
......@@ -48,6 +48,7 @@ import qualified Convert.Simplify
import qualified Convert.Stream
import qualified Convert.StringParam
import qualified Convert.Struct
import qualified Convert.StructConst
import qualified Convert.TFBlock
import qualified Convert.Typedef
import qualified Convert.TypeOf
......@@ -114,6 +115,7 @@ initialPhases selectExclude =
, selectExclude Job.Assert Convert.Assertion.convert
, selectExclude Job.Always Convert.AlwaysKW.convert
, Convert.Package.convert
, Convert.StructConst.convert
, Convert.PortDecl.convert
, Convert.ParamNoDefault.convert
, Convert.ResolveBindings.convert
......
{- sv2v
- Author: Zachary Snow <zach@zachjs.com>
-
- High-level elaboration for struct constant accesses
-
- This greatly simplifies designs with long sequences of struct parameters
- which extend and reference one another, as seen in BlackParrot.
-}
module Convert.StructConst (convert) where
import Control.Monad.State.Strict
import Data.Maybe (fromMaybe)
import Data.Tuple (swap)
import qualified Data.Map.Strict as Map
import Convert.Traverse
import Language.SystemVerilog.AST
type StructType = [Field]
type StructValue = [(TypeOrExpr, Expr)]
type Const = (StructType, StructValue)
type Consts = Map.Map Identifier Const
type Types = Map.Map Identifier StructType
type SC = State (Types, Consts)
convert :: [AST] -> [AST]
convert = map $ traverseDescriptions convertDescription
convertDescription :: Description -> Description
convertDescription =
flip evalState mempty .
traverseModuleItemsM (traverseDeclsM elaborateDecl)
insertType :: Identifier -> [Field] -> SC ()
insertType ident typ = do
(types, consts) <- get
let types' = Map.insert ident typ types
put (types', consts)
insertConst :: Identifier -> Const -> SC ()
insertConst ident cnst = do
(types, consts) <- get
let consts' = Map.insert ident cnst consts
put (types, consts')
lookupType :: Type -> SC [Field]
lookupType (Alias ident []) = do
maybeFields <- gets $ Map.lookup ident . fst
return $ fromMaybe [] maybeFields
lookupType (Struct (Packed Unspecified) fields []) =
return fields
lookupType _ = return []
lookupConst :: Identifier -> SC (Maybe Const)
lookupConst param = gets $ Map.lookup param . snd
elaborateDecl :: Decl -> SC Decl
-- track struct type parameters
elaborateDecl decl@(ParamType Localparam x t)
| Struct (Packed Unspecified) fields [] <- t =
insertType x fields >> return decl
-- track and resolve struct constants
elaborateDecl (Param Localparam t x e) = do
e' <- elaborateExpr e
fields <- lookupType t
when (not $ null fields) $ do
maybeValues <- extractStructValue e'
case maybeValues of
Just values -> insertConst x (fields, values)
Nothing -> return ()
return $ Param Localparam t x e'
elaborateDecl decl = return decl
-- extract the pattern items, including for simple aliases
extractStructValue :: Expr -> SC (Maybe StructValue)
extractStructValue (Pattern values) = return $ Just values
extractStructValue (Ident param) = fmap (fmap snd) $ lookupConst param
extractStructValue _ = return Nothing
-- elaborate constant field accesses
elaborateExpr :: Expr -> SC Expr
elaborateExpr expr@(Dot (Ident param) field) =
fmap (fromMaybe expr . join . fmap (resolveParam field)) (lookupConst param)
elaborateExpr expr =
traverseSinglyNestedExprsM elaborateExpr expr
-- lookup value in struct constant
resolveParam :: Identifier -> Const -> Maybe Expr
resolveParam field (fields, values) = do
fieldType <- lookup field (map swap fields)
value <- mplus
(lookup (Right $ Ident field) values)
(lookup (Left UnknownType) values)
Just $ Cast (Left fieldType) value
......@@ -101,6 +101,7 @@ executable sv2v
Convert.Stream
Convert.StringParam
Convert.Struct
Convert.StructConst
Convert.TFBlock
Convert.Traverse
Convert.Typedef
......
package pkg;
typedef struct packed {
integer unsigned a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z;
} T;
`define step(b, o, f) f: o.f == "inv" ? b.f : o.f
`define extend(_b, _o) '{ \
`step(_b, _o, a), \
`step(_b, _o, b), \
`step(_b, _o, c), \
`step(_b, _o, d), \
`step(_b, _o, e), \
`step(_b, _o, f), \
`step(_b, _o, g), \
`step(_b, _o, h), \
`step(_b, _o, i), \
`step(_b, _o, j), \
`step(_b, _o, k), \
`step(_b, _o, l), \
`step(_b, _o, m), \
`step(_b, _o, n), \
`step(_b, _o, o), \
`step(_b, _o, p), \
`step(_b, _o, q), \
`step(_b, _o, r), \
`step(_b, _o, s), \
`step(_b, _o, t), \
`step(_b, _o, u), \
`step(_b, _o, v), \
`step(_b, _o, w), \
`step(_b, _o, x), \
`step(_b, _o, y), \
`step(_b, _o, z) \
}
localparam X = 1'd0;
localparam Y = 1'd1;
localparam T a_cfg = '{a: X, b: X, c: X, d: X, e: X, f: X, default: Y};
`define expand(let_a, let_b) \
localparam T let_a``_ext = '{let_a: Y, default: "inv"}; \
localparam T let_b``_cfg = `extend(let_a``_cfg, let_a``_ext);
`expand(a, b)
`expand(b, c)
`expand(c, d)
`expand(d, e)
`expand(e, f)
`expand(f, g)
`expand(g, h)
`expand(h, i)
`expand(i, j)
`expand(j, k)
`expand(k, l)
`expand(l, m)
`expand(m, n)
`expand(n, o)
`expand(o, p)
`expand(p, q)
`expand(q, r)
`expand(r, s)
`expand(s, t)
`expand(t, u)
`expand(u, v)
`expand(v, w)
`expand(w, x)
`expand(x, y)
`expand(y, z)
localparam P = z_cfg.z;
endpackage
module top;
initial $display(pkg::P);
endmodule
module top;
localparam P = 32'd1;
initial $display(P);
endmodule
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