Commit 6743725c by Zachary Snow

support partial packing of multidimensional unpacked arrays

parent 3955c47e
{-# LANGUAGE FlexibleInstances #-}
{- sv2v {- sv2v
- Author: Zachary Snow <zach@zachjs.com> - Author: Zachary Snow <zach@zachjs.com>
- -
- Conversion for any unpacked array which must be packed because it is: A) a - Conversion for any unpacked array which must be packed because it is: A) a
- port; B) is bound to a port; C) is assigned a value in a single assignment; - port; B) is bound to a port; C) is assigned a value in a single assignment;
- or D) is assigned to an unpacked array which itself must be packed. - or D) is assigned to an unpacked array which itself must be packed. The
- - conversion allows for an array to be partially packed if all flat usages of
- The scoped nature of declarations makes this challenging. While scoping is - the array explicitly specify some of the unpacked dimensions.
- obeyed in general, if any of a set of *equivalent* declarations within a
- module is packed, all of the declarations are packed. This is because we only
- record the declaration that needs to be packed when a relevant usage is
- encountered.
-} -}
module Convert.UnpackedArray (convert) where module Convert.UnpackedArray (convert) where
import Control.Monad.State.Strict import Control.Monad.State.Strict
import qualified Data.Set as Set import qualified Data.Map.Strict as Map
import Convert.Scoper import Convert.Scoper
import Convert.Traverse import Convert.Traverse
import Language.SystemVerilog.AST import Language.SystemVerilog.AST
type Location = [Identifier] type Location = [Identifier]
type Locations = Set.Set Location type Locations = Map.Map Location Int
type ST = ScoperT Decl (State Locations) type ST = ScoperT Decl (State Locations)
convert :: [AST] -> [AST] convert :: [AST] -> [AST]
...@@ -30,7 +27,7 @@ convert = map $ traverseDescriptions convertDescription ...@@ -30,7 +27,7 @@ convert = map $ traverseDescriptions convertDescription
convertDescription :: Description -> Description convertDescription :: Description -> Description
convertDescription (description @ (Part _ _ Module _ _ ports _)) = convertDescription (description @ (Part _ _ Module _ _ ports _)) =
evalState (operation description) Set.empty evalState (operation description) Map.empty
where where
operation = partScoperT operation = partScoperT
(traverseDeclM ports) traverseModuleItemM noop traverseStmtM >=> (traverseDeclM ports) traverseModuleItemM noop traverseStmtM >=>
...@@ -57,13 +54,14 @@ rewriteDeclM (decl @ (Variable d t x a e)) = do ...@@ -57,13 +54,14 @@ rewriteDeclM (decl @ (Variable d t x a e)) = do
details <- lookupElemM x details <- lookupElemM x
let Just (accesses, _, _) = details let Just (accesses, _, _) = details
let location = map accessName accesses let location = map accessName accesses
usedAsPacked <- lift $ gets $ Set.member location usedAsPacked <- lift $ gets $ Map.lookup location
if usedAsPacked case usedAsPacked of
then do Just depth -> do
let (tf, rs) = typeRanges t let (tf, rs) = typeRanges t
let t' = tf $ a ++ rs let (shifted, rest) = splitAt (length a - depth) a
return $ Variable d t' x [] e let t' = tf $ shifted ++ rs
else return decl return $ Variable d t' x rest e
Nothing -> return decl
rewriteDeclM other = return other rewriteDeclM other = return other
traverseModuleItemM :: ModuleItem -> ST ModuleItem traverseModuleItemM :: ModuleItem -> ST ModuleItem
...@@ -109,11 +107,32 @@ traverseAsgnM (x, y) = do ...@@ -109,11 +107,32 @@ traverseAsgnM (x, y) = do
flatUsageM y flatUsageM y
return (x, y) return (x, y)
flatUsageM :: ScopeKey e => e -> ST () class ScopeKey t => Key t where
flatUsageM x = do unbit :: t -> (t, Int)
details <- lookupElemM x
instance Key Expr where
unbit (Bit e _) = (e', n + 1)
where (e', n) = unbit e
unbit (Range e _ _) = (e', n)
where (e', n) = unbit e
unbit e = (e, 0)
instance Key LHS where
unbit (LHSBit e _) = (e', n + 1)
where (e', n) = unbit e
unbit (LHSRange e _ _) = (e', n)
where (e', n) = unbit e
unbit e = (e, 0)
instance Key Identifier where
unbit x = (x, 0)
flatUsageM :: Key k => k -> ST ()
flatUsageM k = do
let (k', depth) = unbit k
details <- lookupElemM k'
case details of case details of
Just (accesses, _, _) -> do Just (accesses, _, _) -> do
let location = map accessName accesses let location = map accessName accesses
lift $ modify $ Set.insert location lift $ modify $ Map.insertWith min location depth
Nothing -> return () Nothing -> return ()
module example(
input wire [7:0] inp,
output wire [7:0] out
);
assign out = ~inp;
endmodule
module top;
reg arr1 [7:0][1:0];
reg arr2 [7:0][1:0][1:0];
wire [7:0] out1, out2;
example e1(arr1[0], out1);
example e2(arr2[0][0], out2);
initial begin
#1 arr1[0] = 8'hAD;
#1 arr2[0][0] = 8'h42;
end
endmodule
module example(
input wire [7:0] inp,
output wire [7:0] out
);
assign out = ~inp;
endmodule
module top;
reg [7:0] arr1 [1:0];
reg [7:0] arr2 [1:0][1:0];
wire [7:0] out1, out2;
example e1(arr1[0], out1);
example e2(arr2[0][0], out2);
initial begin
#1 arr1[0] = 8'hAD;
#1 arr2[0][0] = 8'h42;
end
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