mirror of https://github.com/zachjs/sv2v.git
elaborate accesses to fields of struct constants
This commit is contained in:
parent
4533e4fffb
commit
086eb78688
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -0,0 +1,97 @@
|
|||
{- 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
|
||||
|
|
|
|||
|
|
@ -0,0 +1,76 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
|
||||
module top;
|
||||
localparam P = 32'd1;
|
||||
initial $display(P);
|
||||
endmodule
|
||||
Loading…
Reference in New Issue