diff --git a/doc/user_guide/bluetcl.tex b/doc/user_guide/bluetcl.tex index 96baa7bb5..9ef3e72fd 100644 --- a/doc/user_guide/bluetcl.tex +++ b/doc/user_guide/bluetcl.tex @@ -337,7 +337,13 @@ \subsubsubsection{Bluetcl::module} {\bf module} {\bf methods} {\em modname}& Returns a list of the flattened methods in the module. \\ \hline -{\bf module} {\bf ports} {\em modname}& Returns a list of the ports in the module. \\ +{\bf module} {\bf ports} {\em modname}& Returns a list of the ports in the +module, organized by interface element. For each method, the entry includes +its argument ports (\te{args}) and a \te{results} field listing the method's +output ports, each given as a \te{port} name and bit \te{size}. The +\te{results} list may be empty (for an action method with no return value) or +contain more than one port (when a method's result is split across several +output ports). \\ \hline {\bf module} {\bf porttypes} {\em modname}& Returns a list of the types of the ports in the module. \\ @@ -430,7 +436,8 @@ \subsubsubsection{Bluetcl::submodule} \hline {\bf submodule} {\bf full} {\em modname}& Returns information about each submodule in the specified module and the rules which use the methods -of the submodule. \\ +of the submodule. The per-method port information uses the same format as +{\bf module ports}, including the \te{results} field of output ports. \\ \hline \hline \end{tabular} diff --git a/src/Libraries/Base1/Prelude.bs b/src/Libraries/Base1/Prelude.bs index 1758af0ad..55fa7d573 100644 --- a/src/Libraries/Base1/Prelude.bs +++ b/src/Libraries/Base1/Prelude.bs @@ -173,7 +173,7 @@ package Prelude( Tuple6, tuple6, Has_tpl_6(..), Tuple7, tuple7, Has_tpl_7(..), Tuple8, tuple8, Has_tpl_8(..), - AppendTuple(..), AppendTuple', AppendTuple'', TupleSize, TupleSize', + AppendTuple(..), AppendTuple', AppendTuple'', TupleSize(..), TupleSize', -- lists required for desugaring List(..), @@ -259,8 +259,8 @@ package Prelude( NumConArg(..), StarConArg(..), OtherConArg(..), MetaConsNamed(..), MetaConsAnon(..), MetaField(..), - WrapField(..), WrapMethod(..), WrapPorts(..), - Port(..), unPort, SplitPorts(..) + WrapField(..), WrapMethod(..), WrapPorts(..), NonEmptyBits(..), + Port(..), unPort, SplitPorts(..), PrimSeqTupleBits(..) ) where infixr 0 $ @@ -993,9 +993,9 @@ fromPrimAction a = ActionValue (\aw -> AVStruct { avValue = _; avAction = a; avW type Action = ActionValue () --X@ \begin{verbatim} ---X@ typedef ActionValue_#(0) Action_; +--X@ typedef ActionValue_#(void) Action_; --X@ \end{verbatim} -type Action_ = ActionValue_ 0 +type Action_ = ActionValue_ () --@ An empty \te{Action}. --@ \index{noAction@\te{noAction} (empty action)} @@ -1012,23 +1012,36 @@ noAction = fromPrimAction primNoActions (:<-) :: Reg a -> ActionValue a -> Action (:<-) r av = av `bind` r._write ---X@ A primitive \te{ActionValue} of bits +--X@ A primitive \te{ActionValue} of bits. +--X@ The type parameter should be either (), Bit n, or a tuple of Bit n. --X@ \begin{verbatim} ---X@ struct ActionValue_ #(type n); +--X@ struct ActionValue_ #(type a; --X@ \end{verbatim} -struct ActionValue_ n +struct ActionValue_ a = - avValue_ :: Bit n + avValue_ :: a avAction_ :: PrimAction -toActionValue_ :: (Bits a n) => ActionValue a -> ActionValue_ n -toActionValue_ (ActionValue av) = +toActionValue_ :: (Bits a n) => ActionValue a -> ActionValue_ (Bit n) +toActionValue_ = bitsToActionValue_ ∘ fmap pack + +fromActionValue_ :: (Bits a n) => ActionValue_ (Bit n) -> ActionValue a +fromActionValue_ = fmap unpack ∘ bitsFromActionValue_ + +toAction_ :: Action -> Action_ +toAction_ = bitsToActionValue_ + +fromAction_ :: Action_ -> Action +fromAction_ = bitsFromActionValue_ + +bitsToActionValue_ :: ActionValue a -> ActionValue_ a +bitsToActionValue_ (ActionValue av) = letseq av' = av ActionWorld - in ActionValue_ { avValue_ = pack av'.avValue; avAction_ = av'.avAction} + in ActionValue_ { avValue_ = av'.avValue; avAction_ = av'.avAction} -fromActionValue_ :: (Bits a n) => ActionValue_ n -> ActionValue a -fromActionValue_ av_ = ActionValue (\aw -> - AVStruct { avValue = unpack av_.avValue_; avAction = av_.avAction_; avWorld = aw}) +bitsFromActionValue_ :: ActionValue_ a -> ActionValue a +bitsFromActionValue_ av_ = ActionValue (\ aw -> + AVStruct { avValue = av_.avValue_; avAction = av_.avAction_; avWorld = aw}) -- ---------------------------------------------------------------- @@ -3344,9 +3357,9 @@ $time = fromActionValue_ (__time__) $stime :: ActionValue (Bit 32) $stime = fromActionValue_ (__stime__) -foreign __time__ :: ActionValue_ 64 = "$time" +foreign __time__ :: ActionValue_ (Bit 64) = "$time" -foreign __stime__ :: ActionValue_ 32 = "$stime" +foreign __stime__ :: ActionValue_ (Bit 32) = "$stime" -- File type and system tasks which use it data File = InvalidFile | @@ -3400,7 +3413,7 @@ foreign $fflush :: PrimAction = "$fflush" -- Type checking is done by bsc -- $fopen :: String -> ActionValue#(File) -- $fopen :: String -> String -> ActionValue#(File) -foreign $fopen :: ActionValue_ 32 = "$fopen" +foreign $fopen :: ActionValue_ (Bit 32) = "$fopen" -- The arguments for these are handled internally @@ -3409,16 +3422,16 @@ foreign $fwriteb :: PrimAction = "$fwriteb" foreign $fwriteo :: PrimAction = "$fwriteo" foreign $fwriteh :: PrimAction = "$fwriteh" -foreign $swriteAV :: ActionValue_ n = "$swriteAV" +foreign $swriteAV :: ActionValue_ (Bit n) = "$swriteAV" foreign $swrite :: PrimAction = "$swrite" -foreign $swritebAV :: ActionValue_ n = "$swritebAV" +foreign $swritebAV :: ActionValue_ (Bit n) = "$swritebAV" foreign $swriteb :: PrimAction = "$swriteb" -foreign $swriteoAV :: ActionValue_ n = "$swriteoAV" +foreign $swriteoAV :: ActionValue_ (Bit n) = "$swriteoAV" foreign $swriteo :: PrimAction = "$swriteo" -foreign $swritehAV :: ActionValue_ n = "$swritehAV" +foreign $swritehAV :: ActionValue_ (Bit n) = "$swritehAV" foreign $swriteh :: PrimAction = "$swriteh" -foreign $sformatAV :: ActionValue_ n = "$sformatAV" +foreign $sformatAV :: ActionValue_ (Bit n) = "$sformatAV" foreign $sformat :: PrimAction = "$sformat" foreign $fdisplay :: PrimAction = "$fdisplay" @@ -3426,20 +3439,19 @@ foreign $fdisplayb :: PrimAction = "$fdisplayb" foreign $fdisplayo :: PrimAction = "$fdisplayo" foreign $fdisplayh :: PrimAction = "$fdisplayh" -foreign $random :: ActionValue_ 32 = "$random" +foreign $random :: ActionValue_ (Bit 32) = "$random" $fgetc :: File -> ActionValue (Int 32) -- to allow space for -1 $fgetc f = fromActionValue_ (__fgetc__ (pack f)) -foreign __fgetc__ :: Bit 32 -> ActionValue_ 32 = "$fgetc" +foreign __fgetc__ :: Bit 32 -> ActionValue_ (Bit 32) = "$fgetc" $fclose :: File -> Action -$fclose f = fromActionValue_ (__fclose__ (pack f)) +$fclose f = fromAction_ (__fclose__ (pack f)) foreign __fclose__ :: Bit 32 -> Action_ = "$fclose" $ungetc :: Bit 8 -> File -> ActionValue (Int 32) $ungetc c f = fromActionValue_ ( __fungetc__ c (pack f)) -foreign __fungetc__ :: Bit 8 -> Bit 32 -> ActionValue_ 32 = "$ungetc" - +foreign __fungetc__ :: Bit 8 -> Bit 32 -> ActionValue_ (Bit 32) = "$ungetc" -- "standard" file descriptors stdin :: File @@ -3454,7 +3466,7 @@ stdout_mcd = MCD 1 $test$plusargs :: String -> ActionValue Bool $test$plusargs x = fromActionValue_ (__testplusargs__ x) -foreign __testplusargs__ :: String -> ActionValue_ 1 = "$test$plusargs" +foreign __testplusargs__ :: String -> ActionValue_ (Bit 1) = "$test$plusargs" ------------------ @@ -3536,6 +3548,7 @@ tuple8 :: a -> b -> c -> d -> e -> f -> g -> h -> Tuple8 a b c d e f g h tuple8 a b c d e f g h = (a,b,c,d,e,f,g,h) class AppendTuple a b c | a b -> c where + type TAppendTuple a b = c appendTuple :: a -> b -> c splitTuple :: c -> (a, b) @@ -3575,7 +3588,8 @@ instance (AppendTuple'' a b c) => AppendTuple'' (h, a) b (h, c) where splitTuple'' (x, y) = case splitTuple'' y of (w, z) -> ((x, w), z) -class TupleSize a n | a -> n where {} +class TupleSize a n | a -> n where + type TTupleSize a = n instance TupleSize () 0 where {} instance (TupleSize' a n) => TupleSize a n where {} @@ -4608,18 +4622,16 @@ data (MetaField :: $ -> # -> *) name idx = MetaField deriving (FShow) --- Tag a method with metadata. --- Currently just the list of input port names. --- Should eventually include the output port names, when we support multiple output ports. -primitive primMethod :: List String -> a -> a +-- Tag a method with metadata: the input and output port names. +primitive primMethod :: List String -> List String -> a -> a -- Convert bewtween a field in an interface that is being synthesized, -- and a field in the corresponding field in the generated wrapper interface. -- Also takes the name of the field for error reporting purposes. class (WrapField :: $ -> * -> * -> *) name f w | name f -> w where - -- Given a proxy value for the field name, and the values of the prefix and arg_names pragmas, + -- Given a proxy value for the field name, and the values of the prefix, arg_names and result pragmas, -- converts a synthesized interface field value to its wrapper interface field. - toWrapField :: StrArg name -> String -> List String -> f -> w + toWrapField :: StrArg name -> String -> List String -> String -> f -> w -- Given a proxy value for the field name, converts a wrapper interface field value -- to its synthesized interface field. @@ -4630,35 +4642,39 @@ class (WrapField :: $ -> * -> * -> *) name f w | name f -> w where saveFieldPortTypes :: StrArg name -> f -> Maybe Name__ -> String -> List String -> String -> Module () instance (WrapMethod m w) => (WrapField name m w) where - toWrapField _ prefix names = - let baseNames = methodArgBaseNames (_ :: m) prefix names 1 - in primMethod (inputPortNames (_ :: m) baseNames) ∘ toWrapMethod + toWrapField _ prefix argNames resultName = + let argBaseNames = methodArgBaseNames (_ :: m) prefix argNames 1 + in primMethod + (inputPortNames (_ :: m) argBaseNames) + (outputPortNames (_ :: m) resultName) + ∘ toWrapMethod fromWrapField _ = fromWrapMethod - saveFieldPortTypes _ _ modName prefix names = - let baseNames = methodArgBaseNames (_ :: m) prefix names 1 - in saveMethodPortTypes (_ :: m) modName baseNames + saveFieldPortTypes _ _ modName prefix argNames resultName = + let baseNames = methodArgBaseNames (_ :: m) prefix argNames 1 + in saveMethodPortTypes (_ :: m) modName baseNames resultName -- TODO: It doesn't seem possible to have a PrimAction field in a synthesized interface, -- but this case was being handled in GenWrap. instance WrapField name PrimAction PrimAction where - toWrapField _ _ _ = id + toWrapField _ _ _ _ = id fromWrapField _ = id saveFieldPortTypes _ _ _ _ _ _ = return () instance WrapField name Clock Clock where - toWrapField _ _ _ = id + toWrapField _ _ _ _ = id fromWrapField _ = id saveFieldPortTypes _ _ _ _ _ _ = return () instance WrapField name Reset Reset where - toWrapField _ _ _ = id + toWrapField _ _ _ _ = id fromWrapField _ = id saveFieldPortTypes _ _ _ _ _ _ = return () instance (Bits a n) => WrapField name (Inout a) (Inout_ n) where - toWrapField _ _ _ = primInoutCast0 + toWrapField _ _ _ _ = primInoutCast0 fromWrapField _ = primInoutUncast0 - saveFieldPortTypes _ _ modName _ _ result = primSavePortType modName result $ typeOf (_ :: (Inout a)) + saveFieldPortTypes _ _ modName _ _ result = + primSavePortType modName result $ typeOf (_ :: (Inout a)) class WrapMethod m w | m -> w where -- Convert a synthesized interface method to its wrapper interface method. @@ -4673,10 +4689,13 @@ class WrapMethod m w | m -> w where -- Compute the list of input port names for a method, from the argument base names. inputPortNames :: m -> List String -> List String + -- Compute the list of input port names for a method, from the result base name. + outputPortNames :: m -> String -> List String + -- Save the port types for a method, given the module name, argument base names and result name. saveMethodPortTypes :: m -> Maybe Name__ -> List String -> String -> Module () -instance (SplitPorts a p, TupleSize p n, WrapPorts p pb, WrapMethod b v, Curry (pb -> v) w) => +instance (WrapPorts (PortsOf a) pb, WrapMethod b v, Curry (pb -> v) w) => WrapMethod (a -> b) w where toWrapMethod f = curryN $ toWrapMethod ∘ f ∘ unsplitPorts ∘ unpackPorts fromWrapMethod f = fromWrapMethod ∘ uncurryN f ∘ packPorts ∘ splitPorts @@ -4691,94 +4710,135 @@ instance (SplitPorts a p, TupleSize p n, WrapPorts p pb, WrapMethod b v, Curry ( (prefix +++ "_" +++ integerToString i) (methodArgBaseNames (_ :: b) prefix Nil $ i + 1) - inputPortNames _ (Cons h t) = checkPortNames (_ :: a) h `listPrimAppend` inputPortNames (_ :: b) t + inputPortNames _ (Cons h t) = + filterZeroWidthPorts (_ :: PortsOf a) (checkPortNames (_ :: a) h) + `listPrimAppend` inputPortNames (_ :: b) t inputPortNames _ Nil = error "inputPortNames: empty arg names list" + outputPortNames _ = outputPortNames (_ :: b) + saveMethodPortTypes _ modName (Cons h t) result = do - savePortTypes (_ :: p) modName $ checkPortNames (_ :: a) h + savePortTypes (_ :: PortsOf a) modName $ checkPortNames (_ :: a) h saveMethodPortTypes (_ :: b) modName t result saveMethodPortTypes _ _ Nil _ = error "saveMethodPortTypes: empty arg names list" -instance (Bits a n) => WrapMethod (ActionValue a) (ActionValue_ n) where - toWrapMethod = toActionValue_ - fromWrapMethod = fromActionValue_ +instance (WrapPorts (PortsOf a) pb, PrimSeqTupleBits pb) => + WrapMethod (ActionValue a) (ActionValue_ pb) where + toWrapMethod = bitsToActionValue_ ∘ fmap (primDeepSeqTupleBits ∘ packPorts ∘ splitPorts) + fromWrapMethod = fmap (unsplitPorts ∘ unpackPorts) ∘ bitsFromActionValue_ methodArgBaseNames _ _ Nil _ = Nil methodArgBaseNames prx prefix argNames _ = primError (getEvalPosition prx) $ integerToString (listLength argNames) +++ " excess arg_names provided for method " +++ prefix inputPortNames _ Nil = Nil inputPortNames _ (Cons _ _) = error "inputPortNames: uncaught excess arg names" - saveMethodPortTypes _ modName _ result = primSavePortType modName result $ typeOf (_ :: a) + outputPortNames _ base = filterZeroWidthPorts (_ :: PortsOf a) $ checkPortNames (_ :: a) base + saveMethodPortTypes _ modName _ result = + savePortTypes (_ :: PortsOf a) modName $ checkPortNames (_ :: a) result -instance (Bits a n) => WrapMethod a (Bit n) where - toWrapMethod = pack - fromWrapMethod = unpack +instance (WrapPorts (PortsOf a) pb, PrimSeqTupleBits pb) => + WrapMethod a pb where + toWrapMethod = primDeepSeqTupleBits ∘ packPorts ∘ splitPorts + fromWrapMethod = unsplitPorts ∘ unpackPorts methodArgBaseNames _ _ Nil _ = Nil methodArgBaseNames prx prefix argNames _ = primError (getEvalPosition prx) $ integerToString (listLength argNames) +++ " excess arg_names provided for method " +++ prefix inputPortNames _ Nil = Nil inputPortNames _ (Cons _ _) = error "inputPortNames: uncaught excess arg names" - saveMethodPortTypes _ modName _ result = primSavePortType modName result $ typeOf (_ :: a) - -{- -Eventually, we should support splitting multiple output ports. -instance (SplitPorts a p, TupleSize p n, WrapPorts p pb) => WrapMethod (ActionValue a) (ActionValue pb) where - toWrapMethod = fmap packPorts - fromWrapMethod = fmap unpackPorts - outputPortNames _ base = checkPortNames (_ :: a) base - saveMethodPortTypes _ modName _ result = - savePortTypes (_ :: p) modName $ checkPortNames (_ :: a) result - -instance (SplitPorts a p, TupleSize p n, WrapPorts p pb) => WrapMethod a pb where - toWrapMethod a = packPorts a - fromWrapMethod a = unpackPorts a - outputPortNames _ base = checkPortNames (_ :: a) base + outputPortNames _ base = filterZeroWidthPorts (_ :: PortsOf a) $ checkPortNames (_ :: a) base saveMethodPortTypes _ modName _ result = - savePortTypes (_ :: p) modName $ checkPortNames (_ :: a) result --} + savePortTypes (_ :: PortsOf a) modName $ checkPortNames (_ :: a) result class WrapPorts p pb | p -> pb where - -- Convert from a tuple of values to a tuple of bits. + -- Convert from a tuple of Port values to a tuple of bits. packPorts :: p -> pb - -- Convert from a tuple of bits to a tuple of values. + -- Convert from a tuple of bits to a tuple of Port values. unpackPorts :: pb -> p -- Save the port types, given their names. savePortTypes :: p -> Maybe Name__ -> List String -> Module () - -instance (Bits a n, WrapPorts b bb) => WrapPorts (Port a, b) (Bit n, bb) where - packPorts (Port a, b) = (pack a, packPorts b) - unpackPorts (a, b) = (Port $ unpack a, unpackPorts b) + -- Filter the port names to only those that have non-zero width. + filterZeroWidthPorts :: p -> List String -> List String + +instance (Bits a n, NonEmptyBits n ab, WrapPorts b bb) => + WrapPorts (Port a, b) (TAppendTuple ab bb) where + packPorts (Port a, b) = toNonEmptyBits (pack a) `appendTuple` packPorts b + unpackPorts p = case splitTuple p of + (ab, bb) -> (Port (unpack (fromNonEmptyBits ab)), unpackPorts bb) savePortTypes _ modName (Cons h t) = do - primSavePortType modName h $ typeOf (_ :: a) + if valueOf n > 0 + then primSavePortType modName h $ typeOf (_ :: a) + else return () savePortTypes (_ :: b) modName t savePortTypes _ _ Nil = error "savePortTypes: empty port names list" - -instance (Bits a n) => WrapPorts (Port a) (Bit n) where - packPorts (Port a) = pack a - unpackPorts = Port ∘ unpack - savePortTypes _ modName (Cons h _) = primSavePortType modName h $ typeOf (_ :: a) - savePortTypes _ _ Nil = error "savePortTypes: empty port names list" + filterZeroWidthPorts _ (Cons h t) = + if valueOf n > 0 + then Cons h (filterZeroWidthPorts (_ :: b) t) + else filterZeroWidthPorts (_ :: b) t + filterZeroWidthPorts _ Nil = error "filterZeroWidthPorts: empty port names list" + +instance (Bits a n, NonEmptyBits n pb) => WrapPorts (Port a) pb where + packPorts (Port a) = toNonEmptyBits (pack a) + unpackPorts = Port ∘ unpack ∘ fromNonEmptyBits + savePortTypes _ modName (Cons h Nil) = primSavePortType modName h $ typeOf (_ :: a) + savePortTypes _ _ _ = error "savePortTypes: expected one port name" + filterZeroWidthPorts _ (Cons h Nil) = + if valueOf n > 0 then Cons h Nil else Nil + filterZeroWidthPorts _ _ = error "filterZeroWidthPorts: expected one port name" instance WrapPorts () () where packPorts _ = () unpackPorts _ = () - savePortTypes _ _ _ = return () + savePortTypes _ _ Nil = return () + savePortTypes _ _ _ = error "savePortTypes: non-empty port names list" + filterZeroWidthPorts _ Nil = Nil + filterZeroWidthPorts _ _ = error "filterZeroWidthPorts: non-empty port names list" + +-- Helper class to conditionally convert Bit 0 to () +class NonEmptyBits n pb | n -> pb where + toNonEmptyBits :: Bit n -> pb + fromNonEmptyBits :: pb -> Bit n + +instance NonEmptyBits 0 () where + toNonEmptyBits _ = () + fromNonEmptyBits _ = 0 + +instance NonEmptyBits n (Bit n) where + toNonEmptyBits = id + fromNonEmptyBits = id + +-- Force a tuple of bit values to be fully expanded by the evaluator. +primDeepSeqTupleBits :: (PrimSeqTupleBits a) => a -> a +primDeepSeqTupleBits a = primSeqTupleBits a a + +class PrimSeqTupleBits a where + primSeqTupleBits :: a -> b -> b + +instance (PrimSeqTupleBits b) => PrimSeqTupleBits (Bit n, b) where + primSeqTupleBits (a, b) c = primSeq a (primSeqTupleBits b c) + +instance PrimSeqTupleBits (Bit n) where + primSeqTupleBits = primSeq + +instance PrimSeqTupleBits () where + primSeqTupleBits () = id -- Compute the list port names for type 'a' given a base name. -- Check that the number of port names matches the number of ports. --- This error should only occur if there is an error in a WrapPorts instance. -checkPortNames :: (SplitPorts a p, TupleSize p n) => a -> String -> List String +-- This error should only occur if there is an error in a SplitPorts instance. +checkPortNames :: (SplitPorts a p) => a -> String -> List String checkPortNames proxy base = let pn = portNames proxy base + n = valueOf (TTupleSize p) in - if listLength pn /= valueOf n + if listLength pn /= n then primError (getEvalPosition proxy) $ - "SplitPorts: " +++ base +++ " has " +++ integerToString (valueOf n) +++ + "SplitPorts: " +++ base +++ " has " +++ integerToString n +++ " ports, but " +++ integerToString (listLength pn) +++ " port names were given" else pn class SplitPorts a p | a -> p where + type PortsOf a = p -- Convert a value to a tuple of values corresponding to ports. splitPorts :: a -> p -- Combine a tuple of values corresponding to ports into a value. @@ -4822,7 +4882,7 @@ class SplitTuplePorts a p | a -> p where unsplitTuplePorts :: p -> a splitTuplePortNames :: Integer -> a -> String -> List String -instance (SplitPorts a p, SplitTuplePorts b q, AppendTuple p q r) => SplitTuplePorts (a, b) r where +instance (SplitPorts a p, SplitTuplePorts b q) => SplitTuplePorts (a, b) (TAppendTuple p q) where splitTuplePorts (a, b) = splitPorts a `appendTuple` splitTuplePorts b unsplitTuplePorts x = case splitTuple x of (a, b) -> (unsplitPorts a, unsplitTuplePorts b) diff --git a/src/Libraries/Base1/SplitPorts.bs b/src/Libraries/Base1/SplitPorts.bs index 01c82f1ae..265257f9b 100644 --- a/src/Libraries/Base1/SplitPorts.bs +++ b/src/Libraries/Base1/SplitPorts.bs @@ -12,12 +12,12 @@ data DeepSplit a = DeepSplit a -- Tag to indicate that the DeepSplitPorts recursion should terminate data NoSplit a = NoSplit a -instance (ShallowSplitPorts a p) => SplitPorts (ShallowSplit a) p where +instance SplitPorts (ShallowSplit a) (ShallowPortsOf a) where splitPorts (ShallowSplit x) = shallowSplitPorts x unsplitPorts = ShallowSplit ∘ shallowUnsplitPorts portNames _ = shallowSplitPortNames (_ :: a) -instance (DeepSplitPorts a p) => SplitPorts (DeepSplit a) p where +instance SplitPorts (DeepSplit a) (DeepPortsOf a) where splitPorts (DeepSplit x) = deepSplitPorts x unsplitPorts = DeepSplit ∘ deepUnsplitPorts portNames _ = deepSplitPortNames (_ :: a) @@ -30,6 +30,7 @@ instance DeepSplitPorts (NoSplit a) (Port a) where -- Helper class using generics, to split a struct or vector into a tuple of ports. class ShallowSplitPorts a p | a -> p where + type ShallowPortsOf a = p shallowSplitPorts :: a -> p shallowUnsplitPorts :: p -> a shallowSplitPortNames :: a -> String -> List String @@ -44,7 +45,8 @@ class ShallowSplitPorts' r p | r -> p where shallowUnsplitPorts' :: p -> r shallowSplitPortNames' :: r -> String -> List String -instance (ShallowSplitPorts' a p, ShallowSplitPorts' b q, AppendTuple p q r) => ShallowSplitPorts' (a, b) r where +instance (ShallowSplitPorts' a p, ShallowSplitPorts' b q) => + ShallowSplitPorts' (a, b) (TAppendTuple p q) where shallowSplitPorts' (a, b) = shallowSplitPorts' a `appendTuple` shallowSplitPorts' b shallowUnsplitPorts' x = case splitTuple x of (a, b) -> (shallowUnsplitPorts' a, shallowUnsplitPorts' b) @@ -77,7 +79,7 @@ instance (ShallowSplitPorts' r p) => ShallowSplitPorts' (Meta m r) p where shallowUnsplitPorts' = Meta ∘ shallowUnsplitPorts' shallowSplitPortNames' _ = shallowSplitPortNames' (_ :: r) -instance (SplitPorts a p) => ShallowSplitPorts' (Conc a) p where +instance ShallowSplitPorts' (Conc a) (PortsOf a) where shallowSplitPorts' (Conc x) = splitPorts x shallowUnsplitPorts' = Conc ∘ unsplitPorts shallowSplitPortNames' _ = portNames (_ :: a) @@ -85,6 +87,7 @@ instance (SplitPorts a p) => ShallowSplitPorts' (Conc a) p where -- Helper class using generics, to recursively split structs and vectors into a tuple of ports. class DeepSplitPorts a p | a -> p where + type DeepPortsOf a = p deepSplitPorts :: a -> p deepUnsplitPorts :: p -> a deepSplitPortNames :: a -> String -> List String @@ -142,7 +145,7 @@ class DeepSplitPorts' r a p | r a -> p where deepSplitPortNames' :: r -> a -> String -> List String -- Terminate recursion for n /= 1 constructors -instance (SplitPorts a p) => DeepSplitPorts' r a p where +instance DeepSplitPorts' r a (PortsOf a) where deepSplitPorts' _ = splitPorts deepUnsplitPorts' _ = unsplitPorts deepSplitPortNames' _ = portNames @@ -158,7 +161,8 @@ class DeepSplitPorts'' r p | r -> p where deepUnsplitPorts'' :: p -> r deepSplitPortNames'' :: r -> String -> List String -instance (DeepSplitPorts'' a p, DeepSplitPorts'' b q, AppendTuple p q r) => DeepSplitPorts'' (a, b) r where +instance (DeepSplitPorts'' a p, DeepSplitPorts'' b q) => + DeepSplitPorts'' (a, b) (TAppendTuple p q) where deepSplitPorts'' (a, b) = deepSplitPorts'' a `appendTuple` deepSplitPorts'' b deepUnsplitPorts'' x = case splitTuple x of (a, b) -> (deepUnsplitPorts'' a, deepUnsplitPorts'' b) diff --git a/src/Libraries/Base1/Vector.bs b/src/Libraries/Base1/Vector.bs index f514a205e..ba577fe20 100644 --- a/src/Libraries/Base1/Vector.bs +++ b/src/Libraries/Base1/Vector.bs @@ -1293,14 +1293,14 @@ instance ConcatTuple 1 a a where unconcatTuple x = cons x nil -- Linear recursive implementation: O(n^2) --- instance (Add n1 1 n, ConcatTuple n1 a b, AppendTuple a b c) => ConcatTuple n a c where +-- instance (Add n1 1 n, ConcatTuple n1 a b) => ConcatTuple n a (TAppendTuple a b) where -- concatTuple v = appendTuple (head v) $ concatTuple (tail v) -- unconcatTuple x = case splitTuple x of -- (y, z) -> cons y $ unconcatTuple z -- O(n lg n) optimization: split into chunks that are powers of 2 -instance (Add lgn 1 (TLog (TAdd n 1)), Add (TExp lgn) n1 n, ConcatTuple n1 a b, ConcatTuple' lgn a c, AppendTuple b c d) => - ConcatTuple n a d where +instance (Add lgn 1 (TLog (TAdd n 1)), Add (TExp lgn) n1 n, ConcatTuple n1 a b, ConcatTuple' lgn a c) => + ConcatTuple n a (TAppendTuple b c) where concatTuple v = let v1 :: Vector n1 a = take v v2 :: Vector (TExp lgn) a = drop v @@ -1320,7 +1320,7 @@ instance ConcatTuple' 0 a a where concatTuple' v = head v unconcatTuple' x = cons x nil -instance (Add n1 1 n, ConcatTuple' n1 a b, AppendTuple b b c) => ConcatTuple' n a c where +instance (Add n1 1 n, ConcatTuple' n1 a b) => ConcatTuple' n a (TAppendTuple b b) where concatTuple' v = let v1 :: Vector (TExp n1) a = take v v2 :: Vector (TExp n1) a = drop v diff --git a/src/bluesim/bs_prim_ops.h b/src/bluesim/bs_prim_ops.h index 08e3d1fd7..2ed2ea9d4 100644 --- a/src/bluesim/bs_prim_ops.h +++ b/src/bluesim/bs_prim_ops.h @@ -1654,7 +1654,7 @@ static inline void wop_primExtractWide(unsigned int dst_sz, static inline void wop_primExtractWide(unsigned int dst_sz, unsigned int src_sz, - tUWide & src, + const tUWide & src, unsigned int high_sz, unsigned int high, unsigned int low_sz, unsigned int low, tUWide &dst) diff --git a/src/bluesim/bs_wide_data.h b/src/bluesim/bs_wide_data.h index 2c056b3f7..dd4496fa8 100644 --- a/src/bluesim/bs_wide_data.h +++ b/src/bluesim/bs_wide_data.h @@ -102,7 +102,7 @@ class WideData unsigned int extract32(unsigned int hi, unsigned int lo) const; unsigned long long extract64(unsigned int hi, unsigned int lo) const; WideData extractWide(unsigned int hi, unsigned int lo) const; - void wop_extractWide(unsigned int hi, unsigned int lo, WideData& result); + void wop_extractWide(unsigned int hi, unsigned int lo, WideData& result) const; void clear(unsigned int from = 0); void clear(unsigned int from, unsigned int to); void set(unsigned int from = 0); diff --git a/src/bluesim/wide_data.cxx b/src/bluesim/wide_data.cxx index f718ce233..f30f1169c 100644 --- a/src/bluesim/wide_data.cxx +++ b/src/bluesim/wide_data.cxx @@ -1755,7 +1755,7 @@ void wop_rem(const WideData& v1, const WideData& v2, WideData &result) /*** function calls ***/ /* maybe useful */ -void WideData::wop_extractWide(uint hi, uint lo, WideData& result) +void WideData::wop_extractWide(uint hi, uint lo, WideData& result) const { copy_bits_to_0(result.data, data, lo, (hi-lo+1)); clear_bits(result.data, (hi-lo+1), (result.numWords() * WORD_SIZE) - 1); diff --git a/src/comp/AAddScheduleDefs.hs b/src/comp/AAddScheduleDefs.hs index 44449a2ed..d90ae6e8a 100644 --- a/src/comp/AAddScheduleDefs.hs +++ b/src/comp/AAddScheduleDefs.hs @@ -105,12 +105,12 @@ aAddScheduleDefs flags pps pkg aschedinfo = -- The ExprMaps map from a method name (not RDY) to the expression -- for that method's ready or enable condition. let pre_rdy_map = M.fromList $ - [ (dropReadyPrefixId (aIfaceName m), adef_expr (aif_value m)) + [ (dropReadyPrefixId (aif_name m), adef_expr $ aif_value m) | m <- ifc0 - , isRdyId (aIfaceName m) + , isRdyId (aif_name m) ] pre_en_map = M.fromList $ - [ (aIfaceName m, e) + [ (aif_name m, e) | m <- ifc0 , (Just e) <- [getMethodEnExpr m] ] @@ -280,11 +280,11 @@ mkIfcWFs _ _ _ = [] -- ignore RDY methods, clocks, resets, inouts -- Get the map from a method to its rule names (or def name, for value method) buildRuleMap :: AIFace -> Maybe (Id, [Id]) buildRuleMap m@(AIAction {}) = - Just (aIfaceName m, map aRuleName (aIfaceRules m)) + Just (aif_name m, map aRuleName (aIfaceRules m)) buildRuleMap m@(AIActionValue {}) = - Just (aIfaceName m, map aRuleName (aIfaceRules m)) + Just (aif_name m, map aRuleName (aIfaceRules m)) buildRuleMap m@(AIDef { aif_name = mid }) | not (isRdyId mid) = - Just (mid, [aIfaceName m]) + Just (mid, [aif_name m]) buildRuleMap _ = Nothing -- Replace the value in a RDY method diff --git a/src/comp/ACheck.hs b/src/comp/ACheck.hs index f42553812..cc044f850 100644 --- a/src/comp/ACheck.hs +++ b/src/comp/ACheck.hs @@ -422,6 +422,8 @@ checkUse :: S.Set AId -> S.Set AId -> S.Set AId -> AExpr -> [AId] checkUse ds is ps (APrim _ _ _ es) = checkUses ds is ps es checkUse ds is ps (AMethCall _ i m es) = checkUses ds is ps es -- XXX check i and m ? checkUse ds is ps (AMethValue _ i m) = [] -- XXX check i and m ? +checkUse ds is ps (ATuple _ es) = checkUses ds is ps es +checkUse ds is ps (ATupleSel _ e _) = checkUse ds is ps e checkUse ds is ps (ANoInlineFunCall _ _ _ es) = checkUses ds is ps es checkUse ds is ps (AFunCall { ae_args = es }) = checkUses ds is ps es -- because all of the expressions used are used by the ATaskAction diff --git a/src/comp/AConv.hs b/src/comp/AConv.hs index 2ea42a585..9259beccd 100644 --- a/src/comp/AConv.hs +++ b/src/comp/AConv.hs @@ -13,8 +13,8 @@ import Id import FStringCompat import Flags(Flags) import PreStrings(sSigned) -import PreIds(idBit, idAVAction_, idAVValue_, idClockOsc, idClockGate, - idInout_, idPrimArray) +import PreIds(idBit, idActionValue_, idAVAction_, idAVValue_, idClockOsc, idClockGate, + idInout_, idPrimArray, idPrimPair, idPrimFst, idPrimSnd, idPrimUnit) import Pragma import Error(internalError, EMsg, WMsg, ErrMsg(..), ErrorHandle, bsError, bsWarning) @@ -28,7 +28,6 @@ import GenWrapUtils(isGenId, dropGenSuffixId) import Prim import Data.List(genericLength, nub) import Data.Maybe(fromMaybe) -import CType(TISort(..), StructSubType(..)) import VModInfo(lookupOutputClockWires, lookupOutputResetWire, lookupIfcInoutWire, vArgs, VArgInfo(..)) import SignalNaming @@ -187,18 +186,18 @@ aDo imod@(IModule mi fmod be wi ps iks its clks rsts itvs pts idefs rs ifc ffcal flags <- getFlags -- AVInst keeps the types of method ports - let tsConv :: Id -> [IType] -> ([AType], Maybe AType, Maybe AType) + let tsConv :: Id -> [IType] -> ([AType], Maybe AType, [AType]) tsConv i ts = let inputs = initOrErr "tsConv" ts res = lastOrErr "tsConv" ts in_types = map (aTypeConv i) inputs (en_type, val_type) - | isitActionValue_ res && getAV_Size res > 0 - = (Just (ATBit 1), Just (ATBit (getAV_Size res))) + | isitActionValue_ res + = (Just (ATBit 1), aTupleTypesConv i (getAV_Type res)) | isActionType res - = (Just (ATBit 1), Nothing) + = (Just (ATBit 1), []) | otherwise - = (Nothing, Just (aTypeConv i res)) + = (Nothing, aTupleTypesConv i res) in (in_types, en_type, val_type) let (IRules sps irule_list) = rs @@ -366,9 +365,7 @@ aIface flags iface@(IEFace i its maybe_e maybe_rs wp fi) = do ++ ppReadable iface) | otherwise -> do - -- internal error if type actionvalue XXX ae <- aExpr e - --trace ("exit v " ++ ppReadable i) $ return () return (AIDef i its' wp g (ADef i (aTypeConv i t) ae []) fi []) (Nothing, Just rs) -> do @@ -507,69 +504,22 @@ aExpr (IAps (ICon i (ICSel { })) ts (e:es)) = internalError ("aExpr: too many arguments to avValue_: " ++ ppReadable es) --- value part of ActionValue task without arguments -aExpr e@(IAps (ICon m (ICSel { })) _ - [(ICon i (ICForeign {fName = name, - isC = isC, - foports = Nothing, - fcallNo = mn}))]) - | m == idAVValue_ = - let n = case (mn) of - Nothing -> internalError - ("aExpr: avValue_ on ICForeign without fcallNo") - Just val -> val - t = aTypeConvE e (iGetType e) - in - return (ATaskValue t i name isC n) +aExpr e@(IAps (ICon _ (ICSel {})) _ _) = aSelExpr sels selExpr + where + (sels, selExpr) = unfoldICSel e + + unfoldICSel :: IExpr a -> ([(Id, AType)], [IExpr a]) + unfoldICSel e@(IAps (ICon i (ICSel {})) _ [e']) = + let (sels, a) = unfoldICSel e' + in ((i, aTypeConvE e $ iGetType e) : sels, a) + unfoldICSel e@(IAps (ICon i (ICSel {})) _ a@(_:_)) = + ([(i, aTypeConvE e $ iGetType e)], a) + -- a selector is always applied to at least its object operand + unfoldICSel e@(IAps (ICon _ (ICSel {})) _ []) = + internalError ("AConv.unfoldICSel: ICSel applied to no arguments:\n" ++ + ppReadable e) + unfoldICSel e = ([], [e]) --- value part of ActionValue task with arguments -aExpr e@(IAps (ICon m (ICSel { })) _ - [(IAps (ICon i (ICForeign {fName = name, - isC = isC, - foports = Nothing, - fcallNo = mn})) fts fes)]) - | m == idAVValue_ = - let n = case (mn) of - Nothing -> internalError - ("aExpr: avValue_ on ICForeign without fcallNo") - Just val -> val - t = aTypeConvE e (iGetType e) - in - -- the value side carries no arguments - -- the cookie "n" will connect it back up to the action side - return (ATaskValue t i name isC n) - --- value part of ActionValue method -aExpr e@(IAps (ICon sel_id (ICSel { })) ts - [(IAps (ICon m (ICSel { })) _ (ICon i (ICStateVar { }) : es))]) - | (sel_id == idAVValue_) = do - i' <- transId i - let atype = aTypeConvE e (iGetType e) - -- arguments should have been dropped in IExpand - when (not (null es)) $ - internalError ("AConv.aExpr actionvalue value with args " ++ - ppReadable e) - -- IExpand is failing to optimize away bit-zero results from methods - -- and foreign functions, so catch that here for ActionValue methods - return $ if (atype == aTZero) - then ASInt i (ATBit 0) (ilDec 0) - else AMethValue atype i' m - --- value method -aExpr e@(IAps (ICon m (ICSel { })) _ (ICon i (ICStateVar { }) : es)) = do - i' <- transId i - let atype = aTypeConvE e (iGetType e) - es' <- mapM aSExpr es - return $ AMethCall atype i' m es' - -aExpr e@(IAps (ICon m (ICSel { })) _ [(ICon i (ICClock { iClock = c }))]) | m == idClockGate = do - ac <- aClock c - return (aclock_gate ac) --- XXX This is here because aClock calls aSExpr on the oscillator. However, --- XXX that should be the only place where an osc ever appears in an expr. -aExpr e@(IAps (ICon m (ICSel { })) _ [(ICon i (ICClock { iClock = c }))]) | m == idClockOsc = do - ac <- aClock c - return (aclock_osc ac) aExpr (IAps (ICon _ (ICCon { iConType = ITAp _ t, conTagInfo = cti })) _ _) | t == itBit1 = return $ aSBool (conNo cti /= 0) aExpr e@(IAps (ICon i (ICForeign { fName = name, isC = isC, foports = Nothing})) ts es) = do @@ -593,6 +543,11 @@ aExpr e@(IAps (ICon i (ICForeign { fName = name, isC = False, foports = (Just op return $ ANoInlineFunCall t i' (ANoInlineFun name ns ops Nothing) es' +aExpr e@(IAps (ICon i _) _ _) | i == idPrimPair = do + let at = aTypeConvE e (iGetType e) + aes <- aTupleExpr e + return (ATuple at aes) + aExpr e@(ICon v (ICModPort { iConType = t })) = return (ASPort (aTypeConvE e t) v) aExpr e@(ICon v (ICModParam { iConType = t })) = return (ASParam (aTypeConvE e t) v) aExpr e@(ICon v (ICMethArg { iConType = t })) = return (ASPort (aTypeConvE e t) v) @@ -638,11 +593,110 @@ aExpr e@(ICon _ (ICInout { iConType = it, iInout = i})) | (isitInout_ it) = do ai <- aInout i return (ASInout at ai) +aExpr (ICon i _) | i == idPrimUnit = return $ ASInt i (ATBit 0) (ilDec 0) + aExpr e = internalError ("AConv.aExpr at " ++ ppString p ++ ":" ++ ppReadable e ++ "\n" ++ (show p) ++ ":" ++ (showTypeless e)) where p = getIExprPosition e +aTupleExpr :: IExpr a -> M [AExpr] +aTupleExpr (IAps (ICon i _) [t1, t2] [e1, e2]) | i == idPrimPair = do + ae1 <- aSExpr e1 + ae2 <- aTupleExpr e2 + return (ae1:ae2) +aTupleExpr e = fmap (:[]) (aSExpr e) + +-- the PrimFst/PrimSnd selectors that project an element out of a +-- tuple-returning method's result +isTupleSelector :: Id -> Bool +isTupleSelector s = s == idPrimFst || s == idPrimSnd + +aSelExpr :: [(Id, AType)] -> [IExpr a] -> M AExpr + +-- value part of ActionValue task without arguments +aSelExpr [(m, t)] [(ICon i (ICForeign {fName = name, + isC = isC, + foports = Nothing, + fcallNo = mn}))] + | m == idAVValue_ = + let n = case (mn) of + Nothing -> internalError + ("aExpr: avValue_ on ICForeign without fcallNo") + Just val -> val + in + return (ATaskValue t i name isC n) + +-- value part of ActionValue task with arguments +aSelExpr [(m, t)] [(IAps (ICon i (ICForeign {fName = name, + isC = isC, + foports = Nothing, + fcallNo = mn})) fts fes)] + | m == idAVValue_ = + let n = case (mn) of + Nothing -> internalError + ("aExpr: avValue_ on ICForeign without fcallNo") + Just val -> val + in + -- the value side carries no arguments + -- the cookie "n" will connect it back up to the action side + return (ATaskValue t i name isC n) + +-- A port selected (via PrimFst/PrimSnd) from a value method that returns a +-- tuple. The value method still carries its arguments. The number of PrimSnd +-- selectors skipped to reach the method is the 0-based output port index. +aSelExpr sels (ICon i (ICStateVar { }) : es) + | (pfx@((_, atype) : _), [(m, atypeTup)]) <- span (isTupleSelector . fst) sels = do + i' <- transId i + es' <- mapM aSExpr es + let idx = toInteger $ length (filter ((== idPrimSnd) . fst) pfx) + return $ ATupleSel atype (AMethCall atypeTup i' m es') (idx + 1) + +-- The value part of an ActionValue method, either bare or with a port selected +-- (via PrimFst/PrimSnd) from a tuple-returning method. The arguments were +-- dropped in IExpand, so none should remain. When there are leading +-- PrimFst/PrimSnd selectors, the number of PrimSnd selectors is the 0-based +-- output port index. +aSelExpr sels base@(ICon i (ICStateVar { }) : es) + | (pfx, [(iav, atypeTup), (m, _)]) <- span (isTupleSelector . fst) sels + , iav == idAVValue_ = do + i' <- transId i + when (not (null es)) $ + internalError ("AConv.aExpr actionvalue value with args " ++ + ppReadable sels ++ "\n" ++ ppReadable base) + let meth = AMethValue atypeTup i' m + case pfx of + -- bare ActionValue output. + -- IExpand is failing to optimize away bit-zero results from methods + -- and foreign functions, so catch that here for ActionValue methods. + [] -> return $ if (atypeTup == aTZero) + then ASInt i (ATBit 0) (ilDec 0) + else meth + -- a port selected from a tuple-returning ActionValue method + ((_, atype) : _) -> do + let idx = toInteger $ length (filter ((== idPrimSnd) . fst) pfx) + return $ ATupleSel atype meth (idx + 1) + +-- value method +aSelExpr [(m, atype)] (ICon i (ICStateVar { }) : es) = do + i' <- transId i + es' <- mapM aSExpr es + return $ AMethCall atype i' m es' + +aSelExpr [(m, _)] [ICon i (ICClock { iClock = c })] | m == idClockGate = do + ac <- aClock c + return (aclock_gate ac) +-- XXX This is here because aClock calls aSExpr on the oscillator. However, +-- XXX that should be the only place where an osc ever appears in an expr. +aSelExpr [(m, _)] [ICon i (ICClock { iClock = c })] | m == idClockOsc = do + ac <- aClock c + return (aclock_osc ac) + +aSelExpr sels base = internalError + ("AConv.aSelExpr:" ++ + ppReadable sels ++ "\n" ++ ppReadable base) + + aEDef :: Id -> IExpr a -> [DefProp] -> M AExpr aEDef i e ps = do da <- getDA @@ -662,12 +716,14 @@ aTypeConv _ (ITAp (ITCon i _ _) (ITNum n)) | i == idInout_ = ATAbstract idInout_ aTypeConv a (ITAp (ITCon r _ _) elem_ty) | r == idPrimArray = -- no way to get the size internalError("aTypeConv: array: " ++ ppReadable a) +aTypeConv a t@(ITAp (ITAp (ITCon p _ _) _) _) | p == idPrimPair = + ATTuple (aTupleTypesConv a t) aTypeConv _ t | t == itReal = ATReal aTypeConv _ t | t == itString = ATString Nothing -- Deal with AVs -aTypeConv _ (ITAp (ITCon i t (TIstruct SStruct fs@(val:_))) (ITNum n)) = - ATBit n - -- internalError ("Yes\n\n" ++ (show a) ++"\n\n" ++ (show n)) +aTypeConv a (ITAp (ITCon i _ _) t) | i == idActionValue_ = + aTypeConv a t +aTypeConv a (ITCon i _ _) | i == idPrimUnit = ATBit 0 aTypeConv _ t = abs t [] where abs (ITCon i _ _) ns = ATAbstract i (reverse ns) abs (ITAp t _) ns = abs t ns @@ -684,17 +740,25 @@ aTypeConvE a (ITAp (ITCon r _ _) elem_ty) | r == idPrimArray = -- XXX we could examine the expression and find the type -- XXX but this func isn't used to get the type of PrimBuildArray internalError ("aTypeConv: array: " ++ ppReadable a) +aTypeConvE _ t@(ITAp (ITAp (ITCon p _ _) _) _) | p == idPrimPair = + ATTuple (aTupleTypesConv p t) aTypeConvE a t | t == itReal = ATReal aTypeConvE a t | t == itString = case a of (ICon _ (ICString _ s)) -> ATString (Just (genericLength s)) otherwise -> ATString Nothing +aTypeConvE a (ITCon i _ _) | i == idPrimUnit = ATBit 0 aTypeConvE a t = abs t [] where abs (ITCon i _ _) ns = ATAbstract i (reverse ns) abs (ITAp t _) ns = abs t ns abs _ _ = -- ATAbstract idBit [] -- XXX what's this internalError ("aTypeConvE|" ++ show t) +aTupleTypesConv :: Id -> IType -> [AType] +aTupleTypesConv a (ITAp (ITAp (ITCon p _ _) t1) t2) | p == idPrimPair = + aTypeConv a t1 : aTupleTypesConv a t2 +aTupleTypesConv a t = [aTypeConv a t] + realPrim :: PrimOp -> Bool realPrim p = p `elem` [ diff --git a/src/comp/ADropUndet.hs b/src/comp/ADropUndet.hs index 2e9a0fb9f..fd764c4e1 100644 --- a/src/comp/ADropUndet.hs +++ b/src/comp/ADropUndet.hs @@ -100,6 +100,8 @@ hasNoActionValue :: M.Map AId Bool -> AExpr -> Bool hasNoActionValue avm (APrim { ae_args = es }) = all (hasNoActionValue avm) es hasNoActionValue avm (AMethCall { ae_args = es }) = all (hasNoActionValue avm) es hasNoActionValue avm (AMethValue {}) = False +hasNoActionValue avm (ATuple _ es) = all (hasNoActionValue avm) es +hasNoActionValue avm (ATupleSel { ae_exp = e }) = hasNoActionValue avm e hasNoActionValue avm (ANoInlineFunCall { ae_args = es }) = all (hasNoActionValue avm) es hasNoActionValue avm (AFunCall { ae_args = es }) = all (hasNoActionValue avm) es hasNoActionValue avm (ATaskValue {}) = False diff --git a/src/comp/ADumpSchedule.hs b/src/comp/ADumpSchedule.hs index ab6ecd630..5f0c59dda 100644 --- a/src/comp/ADumpSchedule.hs +++ b/src/comp/ADumpSchedule.hs @@ -322,7 +322,7 @@ genMethodDumpMap vSchedInfo ifc = methodDumpMap -- don't include output clocks and resets -- don't include ready Ids methodList = filter (not . isRdyId) $ - map aIfaceName (aIfaceMethods ifc) + map aif_name (aIfaceMethods ifc) methodRdys = [(mn, p) | (AIDef { aif_name = mn, aif_value = (ADef _ _ p _) }) <- ifc, isRdyId mn] methodDumpMap = [ (mid, p, clist) diff --git a/src/comp/AExpand.hs b/src/comp/AExpand.hs index 7f3227c5d..8b00f678d 100644 --- a/src/comp/AExpand.hs +++ b/src/comp/AExpand.hs @@ -458,6 +458,8 @@ isSimple c (APrim i t PrimConcat es) = c && all (is isSimple c e@(APrim _ _ p es) = c && isSmall e && cheap p es -- && all (isSimple c) es isSimple c (AMethCall _ _ _ es) = null es isSimple c (AMethValue _ _ _) = True +isSimple c (ATupleSel _ e _) = isSimple c e +isSimple c (ATuple _ es) = all (isSimple c) es -- foreign function calls cannot be inlined -- (except for $signed and $unsigned - handled by mustInline) isSimple c e@(AFunCall { }) = False @@ -537,6 +539,13 @@ getExprSize (APrim _ _ _ es) = (nub $ concat vars, sum terms, 1 + maximum depths getExprSize (AMethCall t i mid args) = ([mid],1,1) getExprSize (AMethValue t i mid) = ([mid],1,1) +-- Tuple construction and selection only appear at port boundaries, where they +-- pack/unpack a method's output port values. They are pure wiring and generate +-- no logic, so (like PrimBNot/PrimInv above) they add no terms or depth: the +-- size is just that of the underlying expression(s). +getExprSize (ATupleSel t e i) = getExprSize e +getExprSize (ATuple t es) = (nub $ concat vars, sum terms, maximum depths) + where (vars,terms,depths) = unzip3 $ map getExprSize es getExprSize (ATaskValue { }) = ([], 1,1) getExprSize (ASPort t i) = ([i], 1,1) getExprSize (ASParam t i) = ([i], 1,1) diff --git a/src/comp/AExpr2STP.hs b/src/comp/AExpr2STP.hs index ce45f26cd..ef9309577 100644 --- a/src/comp/AExpr2STP.hs +++ b/src/comp/AExpr2STP.hs @@ -32,7 +32,7 @@ import PFPrint import Util(itos, map_insertMany, makePairs) import TopUtils(withElapsed) -import AExpr2Util(getMethodOutputPort) +import AExpr2Util(getSingleMethodOutputPort, getMethodOutputPortAt) import Debug.Trace(traceM) import IOUtil(progArgs) @@ -579,21 +579,29 @@ convAExpr2SExpr mty (APrim i (ATBit width) p args) = do -- Method calls create independent variables, with given width -- XXX Passing the current context is just a heuristic -- XXX TODO: some methods calls may be mutex, such as FIFO.full and FIFO.empty +-- A bare AMethCall/AMethValue (with no ATupleSel applied) refers to a method +-- with a single output port; a method with multiple output ports is always +-- wrapped in an ATupleSel selecting one of them (handled in the arms below). +-- Reaching the internalError here would mean a multi-output method was used +-- without selecting a port. +-- the port helpers canonicalize to the actual port name, so that methods which +-- share the same output port appear logically equivalent +-- XXX These could be unevaluated functions, applied to converted arguments convAExpr2SExpr mty (AMethCall ty@(ATBit width) modId methId args) = do - -- get the actual port name, so that methods which share the same output port - -- will appear logically equivalent smap <- gets stateMap - let portId = getMethodOutputPort smap modId methId - e = (AMethCall ty modId portId args) - -- XXX This could be an unevaluated function, applied to converted arguments + let e = AMethCall ty modId (getSingleMethodOutputPort smap modId methId) args addUnknownExpr mty e width convAExpr2SExpr mty (AMethValue ty@(ATBit width) modId methId) = do - -- get the actual port name, so that methods which share the same output port - -- will appear logically equivalent smap <- gets stateMap - let portId = getMethodOutputPort smap modId methId - e = (AMethValue ty modId portId) - -- XXX This could be an unevaluated function, applied to converted arguments + let e = AMethValue ty modId (getSingleMethodOutputPort smap modId methId) + addUnknownExpr mty e width +convAExpr2SExpr mty (ATupleSel ty@(ATBit width) (AMethCall _ modId methId args) selIdx) = do + smap <- gets stateMap + let e = AMethCall ty modId (getMethodOutputPortAt smap modId methId selIdx) args + addUnknownExpr mty e width +convAExpr2SExpr mty (ATupleSel ty@(ATBit width) (AMethValue _ modId methId) selIdx) = do + smap <- gets stateMap + let e = AMethValue ty modId (getMethodOutputPortAt smap modId methId selIdx) addUnknownExpr mty e width convAExpr2SExpr mty e@(AMGate (ATBit 1) _ _) = diff --git a/src/comp/AExpr2Util.hs b/src/comp/AExpr2Util.hs index 104a25735..3f8111775 100644 --- a/src/comp/AExpr2Util.hs +++ b/src/comp/AExpr2Util.hs @@ -1,11 +1,13 @@ -- Common code used by various converters module AExpr2Util( - getMethodOutputPort + getMethodOutputPorts, + getSingleMethodOutputPort, + getMethodOutputPortAt ) where import qualified Data.Map as M -import Data.List(find) +import Data.List(find, genericIndex) import ErrorUtil(internalError) import PPrint @@ -32,8 +34,8 @@ import VModInfo(VModInfo(..), VFieldInfo(..), vName_to_id) -- XXX we can replace them with an unevaluated function applied to its arguments! -- XXX That way, the SMT solver will handle any equivalence of the arguments. -getMethodOutputPort :: (M.Map AId VModInfo) -> AId -> AId -> AId -getMethodOutputPort stateMap modId methId = +getMethodOutputPorts :: (M.Map AId VModInfo) -> AId -> AId -> [AId] +getMethodOutputPorts stateMap modId methId = let mod_err = internalError("canonMethCalls: module not found: " ++ ppReadable modId) fields = vFields $ M.findWithDefault mod_err modId stateMap @@ -41,14 +43,28 @@ getMethodOutputPort stateMap modId methId = ppReadable (modId, methId)) findFn (Method { vf_name = i }) = qualEq i methId findFn _ = False - mport = case (find findFn fields) of - Just (Method { vf_output = mo }) -> mo + ports = case (find findFn fields) of + Just (Method { vf_outputs = os }) -> os _ -> meth_err out_err = internalError("canonMethCalls: method has no output: " ++ ppReadable (modId, methId)) - in case mport of - Just (vn,_) -> vName_to_id vn - _ -> out_err + in if null ports then out_err else map (vName_to_id . fst) ports + +-- A bare method reference (with no tuple selection) refers to a method with a +-- single output port. Return that (canonical) port, failing if the method has +-- multiple output ports (those must be reached through a tuple selector). +getSingleMethodOutputPort :: (M.Map AId VModInfo) -> AId -> AId -> AId +getSingleMethodOutputPort stateMap modId methId = + case getMethodOutputPorts stateMap modId methId of + [portId] -> portId + ports -> internalError ("getSingleMethodOutputPort: unexpected output ports: " ++ + ppReadable (modId, methId, ports)) + +-- The output port at the given tuple-selector index, for a method whose result +-- is split across multiple output ports. +getMethodOutputPortAt :: (M.Map AId VModInfo) -> AId -> AId -> Integer -> AId +getMethodOutputPortAt stateMap modId methId selIdx = + getMethodOutputPorts stateMap modId methId `genericIndex` selIdx -- ------------------------- diff --git a/src/comp/AExpr2Yices.hs b/src/comp/AExpr2Yices.hs index b621930e0..2a8f8700e 100644 --- a/src/comp/AExpr2Yices.hs +++ b/src/comp/AExpr2Yices.hs @@ -30,7 +30,7 @@ import VModInfo(VModInfo) import PFPrint import Util(itos, map_insertMany, makePairs) import TopUtils(withElapsed) -import AExpr2Util(getMethodOutputPort) +import AExpr2Util(getSingleMethodOutputPort, getMethodOutputPortAt) import Debug.Trace(traceM) import IOUtil(progArgs) @@ -583,20 +583,29 @@ convAExpr2YExpr mty (APrim i (ATBit width) p args) = do -- Method calls create independent variables, with given width -- XXX Passing the current context is just a heuristic -- XXX TODO: some methods calls may be mutex, such as FIFO.full and FIFO.empty +-- A bare AMethCall/AMethValue (with no ATupleSel applied) refers to a method +-- with a single output port; a method with multiple output ports is always +-- wrapped in an ATupleSel selecting one of them (handled in the arms below). +-- Reaching the internalError here would mean a multi-output method was used +-- without selecting a port. +-- the port helpers canonicalize to the actual port name, so that methods which +-- share the same output port appear logically equivalent +-- XXX These could be unevaluated functions, applied to converted arguments convAExpr2YExpr mty (AMethCall ty@(ATBit width) modId methId args) = do - -- get the actual port name, so that methods which share the same output port - -- will appear logically equivalent smap <- gets stateMap - let portId = getMethodOutputPort smap modId methId - e = (AMethCall ty modId portId args) - -- XXX This could be an unevaluated function, applied to converted arguments + let e = AMethCall ty modId (getSingleMethodOutputPort smap modId methId) args addUnknownExpr mty e width convAExpr2YExpr mty (AMethValue ty@(ATBit width) modId methId) = do - -- get the actual port name, so that methods which share the same output port - -- will appear logically equivalent smap <- gets stateMap - let portId = getMethodOutputPort smap modId methId - e = (AMethValue ty modId portId) + let e = AMethValue ty modId (getSingleMethodOutputPort smap modId methId) + addUnknownExpr mty e width +convAExpr2YExpr mty (ATupleSel ty@(ATBit width) (AMethCall _ modId methId args) selIdx) = do + smap <- gets stateMap + let e = AMethCall ty modId (getMethodOutputPortAt smap modId methId selIdx) args + addUnknownExpr mty e width +convAExpr2YExpr mty (ATupleSel ty@(ATBit width) (AMethValue _ modId methId) selIdx) = do + smap <- gets stateMap + let e = AMethValue ty modId (getMethodOutputPortAt smap modId methId selIdx) addUnknownExpr mty e width convAExpr2YExpr mty e@(AMGate (ATBit 1) _ _) = diff --git a/src/comp/ANoInline.hs b/src/comp/ANoInline.hs index 4cee039c9..8b5449fed 100644 --- a/src/comp/ANoInline.hs +++ b/src/comp/ANoInline.hs @@ -157,7 +157,7 @@ liftAExpr True (ANoInlineFunCall t i f es) = do liftAExpr _ (APrim aid ty op es) = do es' <- mapM (liftAExpr False) es return $ APrim aid ty op es' -liftAExpr _ (AMethCall ty aid mid es) = do +liftAExpr _ (AMethCall ty aid mid es) = do es' <- mapM (liftAExpr False) es return $ AMethCall ty aid mid es' liftAExpr _ (AFunCall ty aid fun isC es) = do diff --git a/src/comp/APaths.hs b/src/comp/APaths.hs index 4b6e9bc64..5b761890e 100644 --- a/src/comp/APaths.hs +++ b/src/comp/APaths.hs @@ -116,7 +116,7 @@ import VModInfo(vPath, vFields, vArgs, import Pragma import Control.Monad(when) import Data.Maybe(isJust, isNothing, fromJust) -import Data.List(partition) +import Data.List(partition, genericIndex) import Id(unQualId, getIdBaseString) import Eval import Position(getPosition) @@ -170,8 +170,8 @@ data PathNode = PNDef AId | -- arguments to methods of submodules (Ids: instance, method, arg #) PNStateMethodArg AId AId Integer | - -- return values of methods of submodules (Ids: instance, method) - PNStateMethodRes AId AId | + -- return values of methods of submodules (Ids: instance, method, result #) + PNStateMethodRes AId AId Integer | -- enable signal of action methods of submodules (Ids: instance, method) PNStateMethodEnable AId AId | -- imported state has no ready signal @@ -190,8 +190,8 @@ data PathNode = PNWillFire AId | -- arguments to methods of current module (Ids: method, argument) PNTopMethodArg AId AId | - -- return values of methods of current module (Id: method) - PNTopMethodRes AId | + -- return values of methods of current module (Ids: method, result #) + PNTopMethodRes AId Integer | -- this is an internal graph node for the method's ready signal, -- the real output port is handled by a separate read method -- (Id: method) @@ -228,8 +228,8 @@ printPathNode use_pvprint d p node = fsep [text "Argument", pp port_id, s2par "of method", quotes (pp meth_id), s2par "of submodule", quotes (pp inst_id)] - (PNStateMethodRes inst_id meth_id) -> - fsep [s2par "Return value", + (PNStateMethodRes inst_id meth_id port_id) -> + fsep [s2par "Return value", pp port_id, s2par "of method", quotes (pp meth_id), s2par "of submodule", quotes (pp inst_id)] (PNStateMethodEnable inst_id meth_id) -> @@ -255,8 +255,8 @@ printPathNode use_pvprint d p node = (PNTopMethodArg meth_id arg_id) -> fsep [text "Argument", pp arg_id, s2par "of top-level method", quotes (pp meth_id)] - (PNTopMethodRes meth_id) -> - fsep [text "Output", + (PNTopMethodRes meth_id res_num) -> + fsep [text "Output", pp res_num, s2par "of top-level method", quotes (pp meth_id)] (PNTopMethodReady meth_id) -> fsep [s2par "Ready condition", @@ -290,14 +290,14 @@ instance PVPrint PathNode where instance NFData PathNode where rnf (PNDef aid) = rnf aid rnf (PNStateMethodArg a1 a2 n) = rnf3 a1 a2 n - rnf (PNStateMethodRes a1 a2) = rnf2 a1 a2 + rnf (PNStateMethodRes a1 a2 n) = rnf3 a1 a2 n rnf (PNStateMethodEnable a1 a2) = rnf2 a1 a2 rnf (PNStateArgument aid vn n) = rnf3 aid vn n rnf (PNStateMethodArgMux a1 a2) = rnf2 a1 a2 rnf (PNCanFire aid) = rnf aid rnf (PNWillFire aid) = rnf aid rnf (PNTopMethodArg a1 a2) = rnf2 a1 a2 - rnf (PNTopMethodRes aid) = rnf aid + rnf (PNTopMethodRes aid n) = rnf2 aid n rnf (PNTopMethodReady aid) = rnf aid rnf (PNTopMethodEnable aid) = rnf aid rnf (PNTopArgument aid n) = rnf2 aid n @@ -314,7 +314,7 @@ filterPNDefs pns = filter (not . isPNDef) pns isPNDef _ = False alwaysRdyNode :: [PProp] -> PathNode -> Bool -alwaysRdyNode pps (PNTopMethodRes m) = isAlwaysRdy pps m +alwaysRdyNode pps (PNTopMethodRes m _) = isAlwaysRdy pps m alwaysRdyNode pps _ = False enWhenRdyNode :: [PProp] -> PathNode -> Bool @@ -475,13 +475,13 @@ aPathsPreSched errh flags apkg = do -- 1) method name -- 2) input argument list zipped with [1..] -- 3) (Maybe VName) if method has an enable signal (action method) - -- 4) (Maybe VName) if method has a result (now only value methods) + -- 4) result list zipped with [1..] (value methods only) -- 5) (Maybe Id) if method has an associated clock -- Note: the VPort's are stripped of VeriPortProp to be just VName -- XXX is the VeriPortProp info worth keeping? state_instances :: [ ( AId, [(VName, VName)], [(VName, Integer, AExpr)], - [(AId, [(VName,Integer)], Maybe VName, Maybe VName, Maybe AId)] ) ] + [(AId, [(VName,Integer)], Maybe VName, [(VName, Integer)], Maybe AId)] ) ] state_instances = [(inst_id, nns, args, meth_info) | avi <- vs, @@ -498,12 +498,13 @@ aPathsPreSched errh flags apkg = do -- method info let meth_info = - [(meth_id, numbered_args, maybe_EN, maybe_res, maybe_clk) | + [(meth_id, numbered_args, maybe_EN, numbered_res, maybe_clk) | vfieldinfo@(Method { vf_name = meth_id }) <- vFields vmi, let args = map fst (vf_inputs vfieldinfo), let numbered_args = zip args [1..], let maybe_EN = (vf_enable vfieldinfo) >>= return . fst, - let maybe_res = (vf_output vfieldinfo) >>= return . fst, + let res = (vf_outputs vfieldinfo) >>= return . fst, + let numbered_res = zip res [1..], let maybe_clk = vf_clock vfieldinfo ] ] @@ -511,13 +512,14 @@ aPathsPreSched errh flags apkg = do state_input_nodes = [ PNStateMethodArg inst_id meth_id arg_num | (inst_id, _, _, methods) <- state_instances, - (meth_id, numbered_args, maybe_EN, maybe_res, _) <- methods, + (meth_id, numbered_args, maybe_EN, _, _) <- methods, arg_num <- map snd numbered_args ] state_output_nodes = - [ PNStateMethodRes inst_id meth_id | + [ PNStateMethodRes inst_id meth_id res_num | (inst_id, _, _, methods) <- state_instances, - (meth_id, _, _, Just res_name, _) <- methods + (meth_id, _, _, numbered_res, _) <- methods, + res_num <- map snd numbered_res ] state_enable_nodes = [ PNStateMethodEnable inst_id meth_id | @@ -558,7 +560,7 @@ aPathsPreSched errh flags apkg = do let method_inputs = [(arg, PNTopMethodArg m arg) | (AIDef { aif_inputs = args, - aif_value = (ADef m _ _ _) }) <- ifc, + aif_name = m }) <- ifc, (arg,_) <- args] ++ [(arg, PNTopMethodArg m arg) | (AIAction { aif_inputs = args, aif_name = m }) <- ifc, @@ -567,9 +569,14 @@ aPathsPreSched errh flags apkg = do aif_name = m }) <- ifc, (arg,_) <- args] + num_outputs (ADef {adef_type = ATTuple ts}) = fromIntegral (length ts) + num_outputs _ = 1 + method_outputs = - [(m, PNTopMethodRes m) | (AIDef { aif_value = (ADef m _ _ _) }) <- ifc] ++ - [(m, PNTopMethodRes m) | (AIActionValue { aif_name = m, aif_value = (ADef m' _ _ _) }) <- ifc] + [(m, PNTopMethodRes m res) | (AIDef { aif_name = m, aif_value = v }) <- ifc, + res <- [1..(num_outputs v)] ] ++ + [(m, PNTopMethodRes m res) | (AIActionValue { aif_name = m, aif_value = v }) <- ifc, + res <- [1..(num_outputs v)] ] method_enables = -- Name creation is safe, since it is based on VFieldInfo @@ -620,7 +627,7 @@ aPathsPreSched errh flags apkg = do -- These are internal graph nodes, not part of the interface. -- There are separate read methods which become the Verilog ports. - method_ready_nodes = map (PNTopMethodReady . aIfaceName) ifc + method_ready_nodes = map (PNTopMethodReady . aif_name) ifc -- ---------- @@ -683,17 +690,24 @@ aPathsPreSched errh flags apkg = do -- methods (ifc) let mkMethodEdges :: AIFace -> [(PathNode,PathNode)] - mkMethodEdges (AIDef mid inputs wp rdy (ADef m _ e _) _ _) = + mkMethodEdges (AIDef mid inputs wp rdy def@(ADef _ t e _) _ _) = -- connect the rdy expression (likely just an ASDef reference) -- to the internal graph node for the method ready - (mkEdges (PNTopMethodReady m) rdy env) ++ + (mkEdges (PNTopMethodReady mid) rdy env) ++ -- make faux connections from the rdy to the arguments, so that -- dependencies in the other direction are caught as loops - [(PNTopMethodReady m, PNTopMethodArg m arg) | (arg,_) <- inputs] ++ + [(PNTopMethodReady mid, PNTopMethodArg mid arg) | (arg,_) <- inputs] ++ + if length result_types /= length results + then internalError + ("APaths.aPathsPreSched: unexpected method results: " ++ ppReadable def) -- connect the definition to the method result -- (this method has no enable, so it cannot contribute to any -- methcall argument muxes, so just use "mkEdges") - (mkEdges (PNTopMethodRes m) e env) + else [edge | (res, e') <- zip [1..] results, edge <- mkEdges (PNTopMethodRes mid res) e' env] + where result_types | ATTuple ts <- t = ts + | otherwise = [t] + results | ATuple { ae_elems = elems } <- e = elems + | otherwise = [e] mkMethodEdges (AIAction inputs wp rdy m rs fi) = let rdy_node = PNTopMethodReady m en_node = PNTopMethodEnable m @@ -726,7 +740,7 @@ aPathsPreSched errh flags apkg = do -- connect the rules concatMap mkMRuleEdges rs - mkMethodEdges (AIActionValue inputs wp rdy m rs (ADef m' _ e _) fi) = + mkMethodEdges (AIActionValue inputs wp rdy m rs def@(ADef _ t e _) fi) = let rdy_node = PNTopMethodReady m en_node = PNTopMethodEnable m mkMRuleEdges (ARule ri _ _ _ rpred actions _ _) = @@ -748,6 +762,10 @@ aPathsPreSched errh flags apkg = do [(en_node, wf_node)] ++ -- add edges from rule WillFire to ENs in each action (concatMap (mkActionEdges env wf_node) actions) + result_types | ATTuple ts <- t = ts + | otherwise = [t] + results | ATuple { ae_elems = elems } <- e = elems + | otherwise = [e] in -- make faux connections from the rdy to the arguments and the -- enable, so that dependencies in the other direction are caught @@ -755,10 +773,14 @@ aPathsPreSched errh flags apkg = do [(rdy_node, en_node)] ++ [(rdy_node, PNTopMethodArg m arg) | (arg,_) <- inputs] ++ - -- connect the definition to the method result + (if length result_types /= length results + then internalError + ("APaths.aPathsPreSched: unexpected method results: " ++ ppReadable def) + -- connect the definitions to the method results -- (this method's Enable could contribute to methcall argument -- muxes, so use "mkEdgesWithMux") - (mkEdgesWithMux en_node (PNTopMethodRes m) e env) ++ + else [edge | (res, e') <- zip [1..] results, + edge <- (mkEdgesWithMux en_node (PNTopMethodRes m res) e' env)]) ++ -- connect the rules concatMap mkMRuleEdges rs @@ -788,9 +810,10 @@ aPathsPreSched errh flags apkg = do -- (but there are paths for instantiation arguments which become ports) let findOutputPathNodes inst_id vname methods = - [ (clk, PNStateMethodRes inst_id meth_id) | - (meth_id, _, _, Just res, clk) <- methods, - res == vname + [ (clk, PNStateMethodRes inst_id meth_id res_num) | + (meth_id, _, _, numbered_res, clk) <- methods, + (res_name, res_num) <- numbered_res, + res_name == vname ] findInputPathNodes inst_id vname methods argpairs = [ (Nothing, PNStateArgument inst_id arg_id arg_num) | @@ -885,7 +908,7 @@ aPathsPreSched errh flags apkg = do n <- filter (\x -> not (S.member x pathnodeset)) [n1,n2] ] when (not (null unknown_nodes)) $ internalError ("APath.aPaths': nodes not in graph: " ++ - show unknown_nodes) + ppReadable unknown_nodes ++ "\npathnodes = " ++ ppReadable pathnodes) -- ==================== -- Construct the graph @@ -905,10 +928,10 @@ aPathsPreSched errh flags apkg = do -- For urgency to be computed by paths, we must assume a path from -- a method's ready signal to its enable signal. - let rdy_to_en_edges = [(PNTopMethodRes rdy_id, PNTopMethodEnable m_id) | + let rdy_to_en_edges = [(PNTopMethodRes rdy_id 1, PNTopMethodEnable m_id) | (AIAction { aif_pred = (ASDef _ rdy_id), aif_name = m_id, aif_fieldinfo = m_fi }) <- ifc ] ++ - [(PNTopMethodRes rdy_id, PNTopMethodEnable m_id) | + [(PNTopMethodRes rdy_id 1, PNTopMethodEnable m_id) | (AIActionValue { aif_pred = (ASDef _ rdy_id), aif_name = m_id, aif_fieldinfo = m_fi }) <- ifc ] @@ -928,7 +951,7 @@ aPathsPreSched errh flags apkg = do -- edges from WF to RDY of value method [ (wf_rule_id, meth_id, filtered_path) | (PNWillFire wf_rule_id, rs) <- zip will_fire_nodes reachables, - (AIDef { aif_value = (ADef meth_id _ _ _) }) <- ifc, + (AIDef { aif_name = meth_id }) <- ifc, let meth_node = (PNTopMethodReady meth_id), let mpath = lookup meth_node rs, isJust mpath, @@ -1066,14 +1089,14 @@ aPathsPostSched flags pps apkg pathGraphInfo (ASchedule scheds _) = do -- We don't currently need the argument conversion info, because -- the node already contains the converted name (and not the number) let meth_info_map = M.fromList $ - [ (meth_id, ({-numbered_args,-} maybe_EN, maybe_res)) | + [ (meth_id, ({-numbered_args,-} maybe_EN, res)) | meth <- apkg_interface apkg, let vfieldinfo = aif_fieldinfo meth, let meth_id = vf_name vfieldinfo, --let args = map fst (vf_inputs vfieldinfo), --let numbered_args = zip args [1..], let maybe_EN = (vf_enable vfieldinfo) >>= return . fst, - let maybe_res = (vf_output vfieldinfo) >>= return . fst + let res = (vf_outputs vfieldinfo) >>= return . fst ] let findMethod m = @@ -1084,10 +1107,9 @@ aPathsPostSched flags pps apkg pathGraphInfo (ASchedule scheds _) = do -- the "arg" is already the VName and not a number let convertArg m arg = aidToVName arg - let convertRes m = + let convertRes m res_num = case (findMethod m) of - (_, Just res) -> res - _ -> internalError ("APaths convertRes: " ++ ppReadable m) + (_, res) -> res `genericIndex` (res_num - 1) let convertEnable m = case (findMethod m) of @@ -1096,7 +1118,7 @@ aPathsPostSched flags pps apkg pathGraphInfo (ASchedule scheds _) = do -- convert PathNode back to VName let pnToVName (PNTopMethodArg m arg) = convertArg m arg - pnToVName (PNTopMethodRes m) = convertRes m + pnToVName (PNTopMethodRes m res) = convertRes m res pnToVName (PNTopMethodEnable m) = convertEnable m pnToVName (PNTopArgument a _) = aidToVName a pnToVName (PNTopClkGate a) = aidToVName a @@ -1219,9 +1241,31 @@ findEdges env (AMethCall t i qmi exprs) = (edges, ms) = concatUnzip (map f (zip [1..] exprs)) meth_arg_mux = PNStateMethodArgMux i mi muxes = if null exprs then ms else meth_arg_mux:ms - in ([PNStateMethodRes i mi], edges, muxes) + in ([PNStateMethodRes i mi 1], edges, muxes) findEdges env (AMethValue t i qmi) = - ([PNStateMethodRes i (unQualId qmi)], [], []) + ([PNStateMethodRes i (unQualId qmi) 1], [], []) +findEdges env (ATupleSel _ (AMethCall t i qmi exprs) oi) = + -- make edges between exprs and meth input + -- return the output connection + let mi = unQualId qmi + -- like mkEdgesWithMux, but want to return the muxes, not connect them + f (n,exp) = let (is, edges, muxes) = findEdges env exp + pn = PNStateMethodArg i mi n + es = edges ++ (connectEdge pn is) + in (es, muxes) + (edges, ms) = concatUnzip (map f (zip [1..] exprs)) + meth_arg_mux = PNStateMethodArgMux i mi + muxes = if null exprs then ms else meth_arg_mux:ms + in ([PNStateMethodRes i mi oi], edges, muxes) +findEdges env (ATupleSel _ (AMethValue t i qmi) oi) = + ([PNStateMethodRes i (unQualId qmi) oi], [], []) +findEdges env (ATupleSel _ e _) = + internalError + ("APaths.findEdges: unexpected ATupleSel expression: " ++ ppReadable e) + +findEdges env (ATuple _ es) = + -- return any connections found in the element expressions + concatUnzip3 (map (findEdges env) es) findEdges env (ANoInlineFunCall { ae_args = es }) = -- return the function call inputs -- and return any connections found in the argument expressions diff --git a/src/comp/ARankMethCalls.hs b/src/comp/ARankMethCalls.hs index 9826b41b9..6efc07bdb 100644 --- a/src/comp/ARankMethCalls.hs +++ b/src/comp/ARankMethCalls.hs @@ -42,7 +42,7 @@ aRankMethCalls errh pprops orig_pkg = aRankMethCallsInternal :: ErrorHandle -> [[Id]] -> APackage -> IO APackage aRankMethCallsInternal _ [] orig_pkg = return orig_pkg aRankMethCallsInternal errh orig_ranks orig_pkg = - do let method_map = [(aIfaceName m, m) | m <- apkg_interface orig_pkg] + do let method_map = [(aif_name m, m) | m <- apkg_interface orig_pkg] rule_map = [(dropRulePrefixId (arule_id r), r) | r <- apkg_rules orig_pkg] def_map = [(adef_objid d, d) | d <- apkg_local_defs orig_pkg] -- add method ready signals foreach method in (* perf_spec *) @@ -127,6 +127,12 @@ instance RankMethCalls AExpr where defs_to_rewrite) rankMethCalls ver expr@(AMethValue { ameth_id = name }) = (expr { ameth_id = rankId ver name }, []) + rankMethCalls ver expr@(ATuple { ae_elems = elems }) = + let (ranked_elems, defs_to_rewrite) = rankMethCalls ver elems + in (expr { ae_elems = ranked_elems }, defs_to_rewrite) + rankMethCalls ver expr@(ATupleSel { ae_exp = e }) = + let (ranked_e, defs_to_rewrite) = rankMethCalls ver e + in (expr { ae_exp = ranked_e }, defs_to_rewrite) rankMethCalls ver expr@(ANoInlineFunCall { ae_args = args }) = let (ranked_args, defs_to_rewrite) = rankMethCalls ver args in (expr { ae_args = ranked_args }, defs_to_rewrite) diff --git a/src/comp/ARenameIO.hs b/src/comp/ARenameIO.hs index deb852f21..9403b7b44 100644 --- a/src/comp/ARenameIO.hs +++ b/src/comp/ARenameIO.hs @@ -134,11 +134,11 @@ trSI mp si = trM (Nothing) = Nothing trM (Just x) = Just (tr mp x) - trMeth ami@(ASPMethodInfo i ty mr me mv args rs) = + trMeth ami@(ASPMethodInfo i ty mr me vs args rs) = ami { aspm_name = tr mp i, aspm_mrdyid = trM mr, aspm_menableid = trM me, - aspm_mresultid = trM mv, + aspm_resultids = map (tr mp) vs, aspm_inputs = map (tr mp) args } in ASPSignalInfo { diff --git a/src/comp/ASchedule.hs b/src/comp/ASchedule.hs index a6ddbfcb0..de940b265 100644 --- a/src/comp/ASchedule.hs +++ b/src/comp/ASchedule.hs @@ -4139,11 +4139,11 @@ cvtIfc (AIActionValue _ _ ifPred ifId ifRs (ADef dId t _ _) _) = -- rule, dId and rId will be the same) [(Rule rId rOrig [ifPred, rPred] [ifPred, rPred, dExpr] rActs) | (ARule rId rps rDesc rWireProps rPred rActs _ rOrig) <- ifRs] - where dExpr = ASDef t dId -cvtIfc (AIDef _ _ _ ifPred (ADef dId t _ _) _ _) - | isRdyId dId = [] - | otherwise = [(Rule dId Nothing [ifPred] [ifPred,dExpr] [])] - where dExpr = ASDef t dId + where dExpr = ASDef t dId +cvtIfc (AIDef mId _ _ _ _ _ _) | isRdyId mId = [] +cvtIfc (AIDef mId _ _ ifPred (ADef dId t _ _) _ _) = + [(Rule mId Nothing [ifPred] [ifPred, dExpr] [])] + where dExpr = ASDef t dId cvtIfc (AIClock {}) = [] cvtIfc (AIReset {}) = [] cvtIfc (AIInout {}) = [] diff --git a/src/comp/AState.hs b/src/comp/AState.hs index dda4ded85..fbfc648d4 100644 --- a/src/comp/AState.hs +++ b/src/comp/AState.hs @@ -37,6 +37,7 @@ import AUses(useDropCond) import AVerilogUtil(vNameToTask) import RSchedule(RAT, ratToNestedLists) import Wires(WireProps(..)) +import Data.Maybe (listToMaybe) --import Debug.Trace --import Util(traces) @@ -209,12 +210,12 @@ aState' flags pps schedule_info apkg = do -- We separate out the RDY defs for always_ready methods from others, -- because we want the defs (they feed into enables) but do want the -- RDY ports. - isAlwaysReadyMethod m = (isRdyId (aIfaceName m)) && (isAlwaysRdy pps (aIfaceName m)) + isAlwaysReadyMethod m = (isRdyId (aif_name m)) && (isAlwaysRdy pps (aif_name m)) (always_rdy_ifc,other_ifc) = partition isAlwaysReadyMethod ifc outs :: [ADef] - outs = concatMap (outputDefToADef fmod pps) other_ifc + outs = concatMap (outputDefToADefs fmod pps) other_ifc always_ready_defs :: [ADef] - always_ready_defs = concatMap (outputDefToADef fmod pps) always_rdy_ifc + always_ready_defs = concatMap (outputDefToADefs fmod pps) always_rdy_ifc --traceM( "ifc are: " ++ ppReadable ifc ) ; --traceM( "outs are: " ++ ppReadable outs ) ; @@ -413,7 +414,7 @@ aState' flags pps schedule_info apkg = do -- mkEmuxxs needs to know which are the value methods, because -- selectors for muxes are RDY for value methods (instead of WILLFIRE) - value_method_ids = [ i | (AIDef { aif_value = (ADef i _ _ _) }) <- ifc ] + value_method_ids = [ i | (AIDef { aif_name = i }) <- ifc ] -- muxes for values (definitions) (emux_selss, emux_valss, emux_outss, esss) = @@ -444,7 +445,9 @@ aState' flags pps schedule_info apkg = do -- actionvalue method value references can be unconditionally converted subst :: AExpr -> Maybe AExpr subst (AMethValue vt modId methId) = - Just (ASPort vt (mkMethId modId methId Nothing MethodResult)) + Just (ASPort vt (mkMethId modId methId Nothing (MethodResult Nothing))) + subst (ATupleSel vt (AMethValue _ modId methId) idx) = + Just (ASPort vt (mkMethId modId methId Nothing (MethodResult (Just idx)))) -- substitute AMOsc, AMGate, AMReset references with their port subst (AMGate gt modId clkId) = Just (mkOutputGatePort vmi_map modId clkId) @@ -455,7 +458,15 @@ aState' flags pps schedule_info apkg = do let ino = do mult <- M.lookup (modId, methId) omMultMap -- send unused calls of multi-ported methods to port 0 toMaybe (mult > 1) 0 - in Just (ASPort vt (mkMethId modId methId ino MethodResult)) + in Just (ASPort vt (mkMethId modId methId ino (MethodResult Nothing))) + me' -> me' + subst e@(ATupleSel vt (AMethCall _ modId methId es) idx) = + case (M.lookup e substs) of + Nothing -> + let ino = do mult <- M.lookup (modId, methId) omMultMap + -- send unused calls of multi-ported methods to port 0 + toMaybe (mult > 1) 0 + in Just (ASPort vt (mkMethId modId methId ino (MethodResult (Just idx)))) me' -> me' -- AMethValue, AMGate and AMethCall should cover it subst e = Nothing @@ -658,7 +669,7 @@ genModVars vs omMultMap = allmvars -- and whether it's an action method) -- ( m@(Method { vf_name = methId, vf_inputs = argIds, vf_mult = mult }), - (argTypes, en_type, val_type) ) + (argTypes, en_type, val_types) ) <- zip (vFields vmodinfo) methType, -- -- for each part of the method, produce a triple of @@ -674,9 +685,8 @@ genModVars vs omMultMap = allmvars Nothing -> [] (Just t) -> [(MethodEnable, t, True)]) ++ -- value triple - (case (val_type) of - Nothing -> [] - (Just t) -> [(MethodResult, t, False)]), + [(MethodResult mn, t, False) + | (mn, t) <- zip (methResultNums val_types) val_types ], -- uniquifiers for multiple ports -- (if only one copy, then the list just contains 0) ino <- map (toMaybe (mult > 1)) [ 0 .. (getMultUse (modId, methId) - 1) `max` 0 ], @@ -709,25 +719,38 @@ isForeign (ATaskAction { }) = True isForeign _ = False --- Create an output ADef from the Interface method +-- Create output ADefs from the Interface method -- consider only value method returns and outputs of ActionValue methods -- note that expressions are named according to the information on -- the VFieldInfo -outputDefToADef :: Bool -> [PProp] -> AIFace -> [ADef] -outputDefToADef fmod pps ai@(AIDef{}) = if convert then [newdef] else [] - where def = aif_value ai - resName = mkNamedOutput (aif_fieldinfo ai) - newdef = def{ adef_objid = resName } - convert = not (fmod && isRdyId (aif_name ai)) -outputDefToADef _ pps ai@(AIActionValue{}) = [newdef] - where def = aif_value ai - resName = mkNamedOutput (aif_fieldinfo ai) - newdef = def{ adef_objid = resName } -outputDefToADef _ _ a@(AIAction{}) = [] -outputDefToADef _ _ a@(AIClock{}) = [] -outputDefToADef _ _ a@(AIReset{}) = [] -outputDefToADef _ _ a@(AIInout{}) = [] - +outputDefToADefs :: Bool -> [PProp] -> AIFace -> [ADef] +outputDefToADefs fmod pps (AIDef{aif_name=name, aif_value=def, aif_fieldinfo=fi}) = if convert then newdefs else [] + where resNames= mkNamedOutputs fi + newdefs = outputADefToADefs def resNames + convert = not (fmod && isRdyId name) +outputDefToADefs _ pps (AIActionValue{aif_name=name, aif_value=def, aif_fieldinfo=fi}) = newdefs + where resNames= mkNamedOutputs fi + newdefs = outputADefToADefs def resNames +outputDefToADefs _ _ a@(AIAction{}) = [] +outputDefToADefs _ _ a@(AIClock{}) = [] +outputDefToADefs _ _ a@(AIReset{}) = [] +outputDefToADefs _ _ a@(AIInout{}) = [] + +outputADefToADefs :: ADef -> [Id] -> [ADef] +outputADefToADefs (ADef { adef_type = ATTuple ts, adef_expr = ATuple _ es }) resNames = + zipWith3 (\t e resName -> ADef { adef_objid = resName, + adef_type = t, + adef_expr = e, + adef_props = [] }) + ts es resNames +outputADefToADefs (ADef { adef_type = t, adef_expr = e }) [resName] = + [ADef { adef_objid = resName, + adef_type = t, + adef_expr = e, + adef_props = [] }] +outputADefToADefs (ADef { adef_type = ATBit 0}) [] = [] +outputADefToADefs def resNames = + internalError $ "outputADefToADefs: unexpected ADef resNames: " ++ ppReadable (def, resNames) getVInst :: AId -> [AVInst] -> AVInst getVInst i as = head ( [ a | a <- as, i == (avi_vname a) ] ++ @@ -756,7 +779,7 @@ mkSIMethodTuple (AIDef name args _ pred _ vfi _) = aspm_type = "value", aspm_mrdyid = Just rdy, aspm_menableid = Nothing, - aspm_mresultid = Just res, + aspm_resultids = res, aspm_inputs = map fst args, aspm_assocrules = [] } ] @@ -767,7 +790,7 @@ mkSIMethodTuple (AIAction args _ pred name rs vfi) = aspm_type = "action", aspm_mrdyid = Just rdy, aspm_menableid = Just ena, - aspm_mresultid = Nothing, + aspm_resultids = [], aspm_inputs = map fst args, aspm_assocrules = map aRuleName rs } ] @@ -778,7 +801,7 @@ mkSIMethodTuple (AIActionValue args _ pred name rs _ vfi) = aspm_type = "actionvalue", aspm_mrdyid = Just rdy, aspm_menableid = Just ena, - aspm_mresultid = Just res, + aspm_resultids = res, aspm_inputs = map fst args, aspm_assocrules = map aRuleName rs } ] @@ -808,8 +831,8 @@ mkSignalInfoMethod aifaces = merged mergePorts [a] = [a] mergePorts [a, b] = [res] where res = case (isRdyId (aspm_name a), isRdyId (aspm_name b)) of - (True, False) -> b { aspm_mrdyid = (aspm_mresultid a) } - (False, True) -> a { aspm_mrdyid = (aspm_mresultid b) } + (True, False) -> b { aspm_mrdyid = listToMaybe (aspm_resultids a) } + (False, True) -> a { aspm_mrdyid = listToMaybe (aspm_resultids b) } _ -> internalError( "mergePorts" ++ ppReadable (a,b) ) mergePorts x = internalError( "mergePorts2:" ++ ppReadable x ) @@ -830,6 +853,7 @@ ratToBlobs mMap omMultMap rat = let -- True if there are 2 or more uses of the method, -- which means we need to do some sort of muxing + nonTrivial :: MethBlob -> Bool nonTrivial (_, (((AMethCall _ _ _ _, _) : _) : _)) = True nonTrivial _ = False @@ -1014,8 +1038,7 @@ mkEmuxs :: ([AExpr] -> [AExpr]) -> ([AExpr] -> AExpr) -> AId -> AId -> Maybe Integer -> MethPortBlob -> ([ADef], [ADef], [ADef], AExprSubst) mkEmuxs tl cnd rdb value_method_ids om o m ino emrs = - let meth_id = mkMethId o m ino MethodResult - + let -- Break each MethPortBlob into a list of the expressions for -- each argument, and then transpose the entire structure to -- make a list of, for each argument, a list of the different @@ -1031,8 +1054,16 @@ mkEmuxs tl cnd rdb value_method_ids om o m ino emrs = [1..] arg_blobs (sel_defs, val_defs, out_defs) = concatUnzip3 def_tuples + mkPortSubsts (e, _) = + case aType e of + ATTuple ats -> + [ (ATupleSel at e idx, + ASPort at $ mkMethId o m ino $ MethodResult (Just idx)) + | (idx, at) <- zip [1..] ats ] + at -> [ (e, ASPort at $ mkMethId o m ino $ MethodResult Nothing) ] + -- Replace the method call with the output port of the method - subst = [(e, ASPort (aType e) meth_id) | (e, _) <- emrs] + subst = concatMap mkPortSubsts emrs in -- traces ("mkEmuxs " ++ ppReadable emrs ++ ppReadable xs) $ (sel_defs, val_defs, out_defs, subst) diff --git a/src/comp/ASyntax.hs b/src/comp/ASyntax.hs index c60a6c0a0..b0bd445ad 100644 --- a/src/comp/ASyntax.hs +++ b/src/comp/ASyntax.hs @@ -61,14 +61,12 @@ module ASyntax( isUnsizedString, dropSize, unifyStringTypes, + isTupleType, getArrayElemType, getArraySize, - aIfaceName, - aIfaceNameString, aIfaceProps, - aIfaceResSize, aIfaceResType, - aIfaceResId, + aIfaceResIds, aIfaceArgs, aIfaceArgSize, aIfaceRules, @@ -97,6 +95,9 @@ module ASyntax( ppeAPackage, mkMethId, mkMethStr, + mkMethArgStr, + mkMethResStr, + methResultNums, isMethId, MethodPart(..), getParams, @@ -127,12 +128,12 @@ import Prim import ErrorUtil(internalError) import Backend import Pragma -import PreStrings(fsDollar, fsUnderscore, fsEnable) +import PreStrings(fsDollar, fsUnderscore, fsEnable, fs_res) import FStringCompat -- import Position(noPosition) import Position import Data.Maybe -import Util(itos, fromJustOrErr) +import Util(itos) import VModInfo import Wires import ProofObligation(ProofObligation, MsgFn) @@ -340,7 +341,7 @@ data ASPMethodInfo = ASPMethodInfo { aspm_type :: String, aspm_mrdyid :: Maybe AId, aspm_menableid :: Maybe AId, - aspm_mresultid :: Maybe AId, + aspm_resultids :: [AId], aspm_inputs :: [AId], aspm_assocrules :: [AId] } @@ -351,7 +352,7 @@ instance PPrint ASPMethodInfo where <+> text (aspm_type aspmi) <> equals <> braces ( pPrint d 0 (aspm_mrdyid aspmi) <+> pPrint d 0 (aspm_menableid aspmi) <+> - pPrint d 0 (aspm_mresultid aspmi) <+> + pPrint d 0 (aspm_resultids aspmi) $+$ pPrint d 0 (aspm_inputs aspmi) $+$ pPrint d 0 (aspm_assocrules aspmi) ) @@ -446,6 +447,10 @@ data AType = atr_length :: ASize, atr_elem_type :: AType } + -- Tuple type, for methods with multiple return values + | ATTuple { + att_elem_types :: [AType] + } -- abstract type, PrimAction, Interface, Clock, .. -- (can take size parameters as arguments) | ATAbstract { @@ -459,6 +464,7 @@ instance NFData AType where rnf (ATString msz) = rnf msz rnf ATReal = () rnf (ATArray len typ) = rnf2 len typ + rnf (ATTuple typs) = rnf typs rnf (ATAbstract aid args) = rnf2 aid args instance HasPosition AType where @@ -505,6 +511,10 @@ unifyStringTypes (t:ts) | isUnsizedString t = t helper t (t1:ts) | t /= t1 = dropSize t | otherwise = helper t ts +isTupleType :: AType -> Bool +isTupleType (ATTuple _) = True +isTupleType _ = False + type ASize = Integer getArrayElemType :: AType -> AType @@ -571,10 +581,10 @@ data AVInst = AVInst { -- XXX This list corresponds to vFields in the VModInfo, but cannot be -- XXX stored there, because VModInfo is created before types are known. -- There is a triple for each method in vFields of VModInfo. - -- The triple contains the types of each argument (in order) and maybe - -- the types of the EN and return value. + -- The triple contains the types of each argument (in order), maybe + -- the type of the EN, and the return values. -- NOTE: These are the output language types (i.e. ATBit n) - avi_meth_types :: [([AType], Maybe AType, Maybe AType)], + avi_meth_types :: [([AType], Maybe AType, [AType])], -- This field maps source-language types to their corresponding ports avi_port_types :: M.Map VName IType, avi_vmi :: VModInfo, -- Verilog names, conflict info, etc. @@ -672,11 +682,12 @@ getIfcInoutPorts :: AVInst -> [(AId, (AId, AType, VPort))] getIfcInoutPorts avi = let vmi = avi_vmi avi - res_types = map (\ (_,_,mr) -> mr) (avi_meth_types avi) + res_types = map (\ (_,_,rs) -> rs) (avi_meth_types avi) ifc_inouts = [(id,vn,ty) - | (Inout id vn _ _, mr) <- zip (vFields vmi) res_types, - let ty = fromJustOrErr ("ASyntax.unknown inout " ++ - ppReadable id) mr] + | (Inout id vn _ _, rs) <- zip (vFields vmi) res_types, + let ty = case rs of + [r] -> r + _ -> error ("ASyntax.unknown inout " ++ ppReadable id)] mkInoutPort ty vname = (mkOutputWireId (avi_vname avi) vname, @@ -817,17 +828,6 @@ instance NFData AIFace where rnf (AIReset name rst finfo) = rnf3 name rst finfo rnf (AIInout name inout finfo) = rnf3 name inout finfo -aIfaceName :: AIFace -> AId -aIfaceName (AIDef { aif_value = (ADef i _ _ _)}) = i -- XXX use aif_name -aIfaceName (AIAction { aif_name = i}) = i -aIfaceName (AIActionValue { aif_name = i}) = i -aIfaceName (AIClock { aif_name = i}) = i -aIfaceName (AIReset { aif_name = i}) = i -aIfaceName (AIInout { aif_name = i}) = i - -aIfaceNameString :: AIFace -> String -aIfaceNameString i = getIdString (aIfaceName i) - aiface_vname :: AIFace -> String aiface_vname i = getIdString (vf_name (aif_fieldinfo i)) @@ -838,13 +838,7 @@ aIfaceProps (AIAction { aif_props = p }) = p aIfaceProps (AIActionValue { aif_props = p }) = p aIfaceProps _ = emptyWireProps --- result size -aIfaceResSize :: AIFace -> Integer -aIfaceResSize (AIAction { }) = 0 -aIfaceResSize (AIDef {aif_value = (ADef _ (ATBit n) _ _) }) = n -aIfaceResSize (AIActionValue {aif_value = (ADef _ (ATBit n) _ _) }) = n -aIfaceResSize x = internalError ("aIfaceResSize: " ++ show x) - +-- The result type of an interface method, which may be a tuple for multiple output ports. aIfaceResType :: AIFace -> AType -- XXX should be ATAction? aIfaceResType (AIAction { }) = ATBit 0 @@ -853,10 +847,10 @@ aIfaceResType (AIActionValue { aif_value = (ADef _ t _ _)}) = t -- should not need type of clock or reset aIfaceResType x = internalError ("aIfaceResType: " ++ show x) -aIfaceResId :: AIFace -> [AId] -aIfaceResId (AIDef {aif_value = (ADef i _ _ _) }) = [i] -aIfaceResId (AIActionValue {aif_value = (ADef i _ _ _) }) = [i] -aIfaceResId _ = [] +aIfaceResIds :: AIFace -> [AId] +aIfaceResIds (AIDef {aif_name=id}) = [id] +aIfaceResIds (AIActionValue {aif_name=id}) = [id] +aIfaceResIds _ = [] aIfaceArgs :: AIFace -> [AInput] aIfaceArgs (AIClock {}) = [] @@ -904,7 +898,7 @@ addRdyToARule rdyId r0@(ARule { arule_id = ri, arule_pred = e }) = (d, r) aIfaceSchedNames :: AIFace -> [ARuleId] aIfaceSchedNames (AIAction { aif_body = rs}) = map arule_id rs aIfaceSchedNames (AIActionValue { aif_body = rs}) = map arule_id rs -aIfaceSchedNames (AIDef { aif_value = d }) = [adef_objid d] +aIfaceSchedNames (AIDef { aif_name = i }) = [i] aIfaceSchedNames _ = [] aIfacePred :: AIFace -> APred @@ -1054,6 +1048,16 @@ data AExpr ae_objid :: AId, ameth_id :: AMethodId } + | ATuple { + ae_type :: AType, + ae_elems :: [AExpr] + } + -- selection from an ATTuple + | ATupleSel { + ae_type :: AType, + ae_exp :: AExpr, + ae_index :: Integer + } -- calls a combinatorial function expressed via module instantiation -- XXX this can be created not only via "noinline" in BSV, -- XXX but also "foreign" in Classic syntax; consider renaming? @@ -1152,6 +1156,8 @@ instance NFData AExpr where rnf (APrim oid typ prim args) = rnf4 oid typ prim args rnf (AMethCall typ oid mid args) = rnf4 typ oid mid args rnf (AMethValue typ oid mid) = rnf3 typ oid mid + rnf (ATuple typ elems) = rnf2 typ elems + rnf (ATupleSel typ expr index) = rnf3 typ expr index rnf (ANoInlineFunCall typ oid fun args) = rnf4 typ oid fun args rnf (AFunCall typ oid fname isC args) = rnf5 typ oid fname isC args rnf (ATaskValue typ oid fname isC cookie) = rnf5 typ oid fname isC cookie @@ -1177,6 +1183,12 @@ instance Eq AExpr where AMethValue t aid mid == AMethValue t' aid' mid' = (t == t') && (mid == mid') && (aid == aid') + ATuple t aexprs == ATuple t' aexprs' = + (t == t') && (aexprs == aexprs') + + ATupleSel t aexpr index == ATupleSel t' aexpr' index' = + (t == t') && (index == index') && (aexpr == aexpr') + ANoInlineFunCall t aid af aexprs == ANoInlineFunCall t' aid' af' aexprs' = (t == t') && (af == af') && (aexprs == aexprs') && (aid == aid') @@ -1222,6 +1234,9 @@ instance HasPosition AExpr where getPosition APrim{ ae_objid = p } = getPosition p getPosition AMethCall{ ae_objid = p } = getPosition p getPosition AMethValue{ ae_objid = p } = getPosition p + getPosition ATuple{ ae_elems = e : _ } = getPosition e + getPosition ATuple{ ae_elems = [] } = noPosition -- Is there something better? + getPosition ATupleSel{ ae_exp = e } = getPosition e getPosition ANoInlineFunCall{ ae_objid = p } = getPosition p getPosition AFunCall{ ae_objid = p } = getPosition p getPosition ATaskValue{ ae_objid = p } = getPosition p @@ -1434,7 +1449,7 @@ instance PPrint AIFace where pPrint d p ai@(AIDef {} ) = (text "--AIDef" <+> pPrint d p (aif_name ai)) $+$ foldr (($+$) . ppV d) empty (aif_inputs ai) $+$ - pPrint d 0 (aif_value ai) $+$ + pPrint d p (aif_value ai) $+$ pPred d p (aif_pred ai) $+$ pPrint d 0 (aif_props ai) $+$ pPrint d 0 (aif_fieldinfo ai) $+$ @@ -1563,6 +1578,8 @@ instance PPrint AExpr where pPrint d 1 i <> sep (text "." <> ppMethId d m : map (pPrint d 1) es) pPrint d p (AMethValue _ i m) = pparen (p>0) $ pPrint d 1 i <> text "." <> ppMethId d m + pPrint d p (ATuple _ es) = parens (commaSep (map (pPrint d 0) es)) + pPrint d p (ATupleSel _ e idx) = pPrint d 1 e <> text "[" <> pPrint d 0 idx <> text "]" pPrint d p (ASPort _ i) = pPrint d p i pPrint d p (ASParam _ i) = pPrint d p i pPrint d p (ASDef _ i) = pPrint d p i @@ -1592,6 +1609,8 @@ instance PPrint AType where pPrint d p (ATString (Just n)) = text ("String (" ++ (itos n) ++ " chars)") pPrint d p (ATArray sz ty) = text "Array" <+> text (itos sz) <+> pPrint d 0 ty + pPrint d p (ATTuple ts) = + text "Tuple" <+> parens (commaSep (map (pPrint d 0) ts)) pPrint d p (ATAbstract i ns) = sep (text "ABSTRACT: " : pPrint d 0 i : map (pPrint d 0) ns) binOp :: PrimOp -> Bool @@ -1855,6 +1874,8 @@ instance PPrintExpand AExpr where where docArgs = map (pPrintExpand m d defContext) es pPrintExpand m d ec (AMethValue _ i meth) = pPrint d 1 i <> text "." <> ppMethId d meth + pPrintExpand m d ec (ATuple _ es) = parens (commaSep (map (pPrintExpand m d defContext) es)) + pPrintExpand m d ec (ATupleSel _ e idx) = (pparen (useParen ec) $ pPrintExpand m d defContext e) <> text ("[" ++ itos idx ++ "]") pPrintExpand m d ec (ASPort _ i) = pPrint d (getP ec) i pPrintExpand m d ec (ASParam _ i) = pPrint d (getP ec) i pPrintExpand m d ec (ASDef _ i) | isIdWillFire i && (lookupLevel m) > 0 || @@ -1885,19 +1906,24 @@ defLookup d ped = M.findWithDefault err d (defmap ped) -- # Some standardized methods for making (default) method strings -- ############################################################################# data MethodPart = - MethodArg Integer | -- argument 1, 2, ... input - MethodResult | -- return value output - MethodEnable -- enable signal input + MethodArg Integer | -- argument 1, 2, ... input + MethodResult (Maybe Integer) | -- return value: Nothing for a single result, + -- Just 1, 2, ... when split across ports + MethodEnable -- enable signal input deriving (Eq) -- The method syntax is as follows: -- Arguments are $_ starting from 1 -- (e.g. the_fifo$enq_1) --- Return values are $ (e.g. the_fifo$first) +-- Return values are $_RES_ when the result is split across +-- multiple output ports (e.g. the_fifo$first_RES_1), or just $ +-- when the method has a single result (e.g. the_fifo$first) -- Enable signals are $EN_ (e.g. the_fifo$EN_enq) -- Multi-ported methods are $__ +-- or $__RES_ -- The portnum is only omitted if the method has one or -- and infinite number of ports (like a register) +-- XXX these should probably just be a data type rather than Ids mkMethId :: Id -> Id -> Maybe Integer -> MethodPart -> Id mkMethId o m ino mp = -- trace ("POS O: " ++ (show (getIdPosition o)) ++ " " ++ @@ -1922,13 +1948,8 @@ mkMethStr obj m m_port mp = fsUnderscore, mkNumFString port] base = case mp of - MethodArg n -> - if (n == 0) - then internalError "mkMethStr" - else concatFString [meth_port, - fsUnderscore, - mkNumFString n] - MethodResult -> meth_port + MethodArg n -> mkMethArgStr meth_port n + MethodResult mn -> mkMethResStr meth_port mn MethodEnable -> -- XXX are we overloading fsEnable? concatFString [fsEnable, meth_port] @@ -1937,6 +1958,27 @@ mkMethStr obj m m_port mp = fsDollar, base] +mkMethArgStr :: FString -> Integer -> FString +mkMethArgStr meth_port n = + if (n == 0) + then internalError "mkMethArgStr" + else concatFString [meth_port, fsUnderscore, mkNumFString n] + +mkMethResStr :: FString -> Maybe Integer -> FString +-- a single result gets no _RES_ suffix +mkMethResStr meth_port Nothing = meth_port +mkMethResStr meth_port (Just n) = + if (n == 0) + then internalError "mkMethResStr" + else concatFString [meth_port, fsUnderscore, fs_res, mkNumFString n] + +-- The result numbers for a method with the given list of results: Nothing +-- (no _RES_ suffix) for a single result, Just 1, Just 2, ... when split across +-- multiple output ports. +methResultNums :: [a] -> [Maybe Integer] +methResultNums [_] = [Nothing] +methResultNums xs = zipWith (\ _ n -> Just n) xs [1..] + -- ############################################################################# -- # -- ############################################################################# diff --git a/src/comp/ASyntaxUtil.hs b/src/comp/ASyntaxUtil.hs index 561672e45..a12b6580d 100644 --- a/src/comp/ASyntaxUtil.hs +++ b/src/comp/ASyntaxUtil.hs @@ -72,6 +72,8 @@ instance AVars AExpr where aVars (ANoInlineFunCall _ _ _ es) = concatMap aVars es aVars (AFunCall _ _ _ _ es) = concatMap aVars es aVars (AMethCall _ _ _ es) = concatMap aVars es + aVars (ATuple _ es) = concatMap aVars es + aVars (ATupleSel _ e _) = aVars e -- aVars (ATaskValue ...) = [] -- because the variables are really "used" -- by the action which sets it -- same for AMethValue @@ -117,6 +119,8 @@ aMethValues :: AExpr -> [(AId, AId, AType)] aMethValues e@(APrim {}) = concatMap aMethValues (ae_args e) aMethValues e@(AMethCall {}) = concatMap aMethValues (ae_args e) aMethValues (AMethValue ty obj meth) = [(obj,meth,ty)] +aMethValues (ATuple _ es) = concatMap aMethValues es +aMethValues (ATupleSel _ e _) = aMethValues e aMethValues e@(ANoInlineFunCall {}) = concatMap aMethValues (ae_args e) aMethValues e@(AFunCall {}) = concatMap aMethValues (ae_args e) aMethValues (ATaskValue {}) = [] @@ -137,6 +141,8 @@ aMethCalls :: AExpr -> [(AId, AId)] aMethCalls e@(APrim {}) = concatMap aMethCalls (ae_args e) aMethCalls (AMethCall _ obj meth es) = ((obj,meth) : concatMap aMethCalls es) aMethCalls (AMethValue _ obj meth) = [] +aMethCalls (ATuple _ es) = concatMap aMethCalls es +aMethCalls (ATupleSel _ e _) = aMethCalls e aMethCalls e@(ANoInlineFunCall {}) = concatMap aMethCalls (ae_args e) aMethCalls e@(AFunCall {}) = concatMap aMethCalls (ae_args e) aMethCalls (ATaskValue {}) = [] @@ -157,6 +163,8 @@ aTaskValues :: AExpr -> [(AId, Integer, AType)] aTaskValues e@(APrim {}) = concatMap aTaskValues (ae_args e) aTaskValues e@(AMethCall {}) = concatMap aTaskValues (ae_args e) aTaskValues (AMethValue {}) = [] +aTaskValues (ATuple _ es) = concatMap aTaskValues es +aTaskValues (ATupleSel _ e _) = aTaskValues e aTaskValues e@(ANoInlineFunCall {}) = concatMap aTaskValues (ae_args e) aTaskValues e@(AFunCall {}) = concatMap aTaskValues (ae_args e) aTaskValues (ATaskValue ty f_id fun isC cookie) = [(f_id, cookie, ty)] @@ -180,6 +188,8 @@ exprForeignCalls e@(AFunCall {}) = else (concatMap exprForeignCalls (ae_args e)) exprForeignCalls e@(APrim {}) = concatMap exprForeignCalls (ae_args e) exprForeignCalls e@(AMethCall {}) = concatMap exprForeignCalls (ae_args e) +exprForeignCalls (ATuple _ es) = concatMap exprForeignCalls es +exprForeignCalls (ATupleSel _ e _) = exprForeignCalls e exprForeignCalls e@(ANoInlineFunCall {}) = concatMap exprForeignCalls (ae_args e) exprForeignCalls _ = [] @@ -227,6 +237,7 @@ instance ATypeC AType where aSize e = case aType e of ATBit s -> s + ATTuple ts -> sum (map aSize ts) ATString (Just s) -> 8*s -- 8 bits per character ATAbstract i [n] | i==idInout_ -> n ATArray sz t -> sz * (aSize t) @@ -455,6 +466,8 @@ aSubst m = mapAExprs xsub xsub x@(ASDef _ i) = M.findWithDefault x i m xsub (APrim aid t p es) = APrim aid t p (aSubst m es) xsub (AMethCall t i meth es) = AMethCall t i meth (aSubst m es) + xsub (ATuple t es) = ATuple t (aSubst m es) + xsub (ATupleSel t e n) = ATupleSel t (aSubst m e) n xsub (ANoInlineFunCall t i f es) = ANoInlineFunCall t i f (aSubst m es) xsub (AFunCall t i f isC es) = AFunCall t i f isC (aSubst m es) xsub (ASAny t me) = ASAny t (fmap (aSubst m) me) @@ -474,6 +487,12 @@ exprMap f e@(APrim i t o args) = exprMap f e@(AMethCall t i m args) = let e' = AMethCall t i m (map (exprMap f) args) in fromMaybe e' (f e) +exprMap f e@(ATuple t args) = + let e' = ATuple t (map (exprMap f) args) + in fromMaybe e' (f e) +exprMap f e@(ATupleSel t expr n) = + let e' = ATupleSel t (exprMap f expr) n + in fromMaybe e' (f e) exprMap f e@(ANoInlineFunCall t i fun args) = let e' = ANoInlineFunCall t i fun (map (exprMap f) args) in fromMaybe e' (f e) @@ -501,6 +520,18 @@ exprMapM f e@(AMethCall t i m args) = do Just e' -> return e' Nothing -> do args' <- mapM (exprMapM f) args return $ AMethCall t i m args' +exprMapM f e@(ATuple t elems) = do + me <- f e + case me of + Just e' -> return e' + Nothing -> do elems' <- mapM (exprMapM f) elems + return $ ATuple t elems' +exprMapM f e@(ATupleSel t expr n) = do + me <- f e + case me of + Just e' -> return e' + Nothing -> do expr' <- exprMapM f expr + return $ ATupleSel t expr' n exprMapM f e@(ANoInlineFunCall t i fun args) = do me <- f e case me of @@ -527,6 +558,12 @@ exprFold f v e@(APrim i t o args) = exprFold f v e@(AMethCall t i m args) = let v' = foldr (flip (exprFold f)) v args in f e v' +exprFold f v e@(ATuple t elems) = + let v' = foldr (flip (exprFold f)) v elems + in f e v' +exprFold f v e@(ATupleSel t expr n) = + let v' = exprFold f v expr + in f e v' exprFold f v e@(ANoInlineFunCall t i fun args) = let v' = foldr (flip (exprFold f)) v args in f e v' @@ -612,6 +649,10 @@ aIdFnToAExprFn fn (AMethCall ty aid mid args) = AMethCall ty (fn aid) mid (mapAExprs (aIdFnToAExprFn fn) args) aIdFnToAExprFn fn (AMethValue ty aid mid) = AMethValue ty (fn aid) mid +aIdFnToAExprFn fn (ATuple ty exprs) = + ATuple ty (mapAExprs (aIdFnToAExprFn fn) exprs) +aIdFnToAExprFn fn (ATupleSel ty expr n) = + ATupleSel ty (aIdFnToAExprFn fn expr) n aIdFnToAExprFn fn (ANoInlineFunCall ty aid fun args) = ANoInlineFunCall ty (fn aid) fun (mapAExprs (aIdFnToAExprFn fn) args) aIdFnToAExprFn fn (AFunCall ty aid fun isC args) = diff --git a/src/comp/ATaskSplice.hs b/src/comp/ATaskSplice.hs index 42d131c4d..8b821fcd0 100644 --- a/src/comp/ATaskSplice.hs +++ b/src/comp/ATaskSplice.hs @@ -1,7 +1,6 @@ module ATaskSplice(aTaskSplice) where import ASyntax import ASyntaxUtil -import Data.Maybe import Id import qualified Data.Map as M import ErrorUtil(internalError) @@ -14,9 +13,9 @@ aTaskSplice :: APackage -> APackage aTaskSplice apkg = mapAActions (spliceAction spliceMap) apkg where spliceMap = M.fromList [ (n, (id, t)) | ADef id t (ATaskValue { ae_cookie = n }) _ <- defs ] defs = (apkg_local_defs apkg) ++ - (mapMaybe av_ret_def (apkg_interface apkg)) - av_ret_def act@(AIActionValue {}) = Just (aif_value act) - av_ret_def _ = Nothing + (concatMap av_ret_def (apkg_interface apkg)) + av_ret_def act@(AIActionValue {}) = [aif_value act] + av_ret_def _ = [] spliceAction :: SpliceMap -> AAction -> AAction spliceAction spliceMap a@(ATaskAction { ataskact_temp = Nothing }) = diff --git a/src/comp/AUses.hs b/src/comp/AUses.hs index 557271206..cfe6961ba 100644 --- a/src/comp/AUses.hs +++ b/src/comp/AUses.hs @@ -846,6 +846,8 @@ eDomain e@(AMethCall _ i mi es) = do let this_use = singleMethodExprUse i (unQualId mi) e ucTrue es_uses <- mapM eDomain es mergeExprUsesM (this_use : es_uses) +eDomain (ATuple _ es) = mapM eDomain es >>= mergeExprUsesM +eDomain (ATupleSel _ e _) = eDomain e eDomain e@(AFunCall { ae_objid = i, ae_args = es }) = do let this_use = singleFFuncExprUse i e ucTrue es_uses <- mapM eDomain es diff --git a/src/comp/AVeriQuirks.hs b/src/comp/AVeriQuirks.hs index 72e843309..859bcc876 100644 --- a/src/comp/AVeriQuirks.hs +++ b/src/comp/AVeriQuirks.hs @@ -320,6 +320,12 @@ aQExp top (APrim aid t p es) = mapM (aQExp False) es >>= return . APrim ai aQExp top (AMethCall t i m es) = mapM (aQExp False) es >>= return . AMethCall t i m aQExp top (ANoInlineFunCall t i f es) = mapM (aQExp False) es >>= return . ANoInlineFunCall t i f aQExp top (AFunCall t i f isC es) = mapM (aQExp False) es >>= return . AFunCall t i f isC +aQExp top (ATuple t es) = do + es' <- mapM (aQExp False) es + return (ATuple t es') +aQExp top (ATupleSel t e n) = do + e' <- aQExp False e + return (ATupleSel t e' n) aQExp top e@(AMethValue {}) = return e aQExp top e@(ASInt _ _ _) = return e aQExp top e@(ASReal _ _ _) = return e @@ -408,6 +414,7 @@ aSInt t i = ASInt defaultAId t (ilHex i) mkDefS :: AExpr -> QQState AExpr mkDefS e@(AMethCall _ o m []) = return e -- XXX shouldn't exist mkDefS e@(AMethValue _ o m) = return e -- XXX shouldn't exist +mkDefS e@(ATupleSel _ _ _) = return e -- XXX shouldn't exist mkDefS e@(ASDef {}) = return e mkDefS e@(ASPort {}) = return e mkDefS e@(ASParam {}) = return e diff --git a/src/comp/AVerilog.hs b/src/comp/AVerilog.hs index 155495c48..438d735a8 100644 --- a/src/comp/AVerilog.hs +++ b/src/comp/AVerilog.hs @@ -474,8 +474,8 @@ groupPorts si as = -- (function to be folded over the method port info) findMethod :: ASPMethodInfo -> ([(AId,String,[VArg])],[(Id,VArg)]) -> ([(AId,String,[VArg])],[(Id,VArg)]) - findMethod (ASPMethodInfo i ty mr me mv args _) (ms, ports) = - let is = (catMaybes [mr, me, mv]) ++ args + findMethod (ASPMethodInfo i ty mr me vs args _) (ms, ports) = + let is = (catMaybes [mr, me]) ++ vs ++ args (ps, remaining) = findIds is ports in ((i,ty,ps):ms, remaining) @@ -574,10 +574,10 @@ groupMethodDefs vDef si ds = mkForMethod :: ASPMethodInfo -> ([VMItem], [VMItem], [VMItem], M.Map AId ADef) -> ([VMItem], [VMItem], [VMItem], M.Map AId ADef) - mkForMethod (ASPMethodInfo i ty mr _ mv _ rs) (odecls, idecls, gs, defs) = + mkForMethod (ASPMethodInfo i ty mr _ vs _ rs) (odecls, idecls, gs, defs) = let -- get the output defs - output_ids = catMaybes [mv, mr] + output_ids = vs ++ maybeToList mr (output_defs, other_defs) = findADefs output_ids defs -- get the rule defs rule_sched_ids = concatMap getRuleSignals rs diff --git a/src/comp/AVerilogUtil.hs b/src/comp/AVerilogUtil.hs index 36b06f395..c8f245233 100644 --- a/src/comp/AVerilogUtil.hs +++ b/src/comp/AVerilogUtil.hs @@ -862,7 +862,7 @@ vState flags rewire_map avinst = mkEnId m m_port = vMethId v_inst_name m m_port MethodEnable port_rename_table - mkResId m m_port = vMethId v_inst_name m m_port MethodResult port_rename_table + mkResId m k m_port = vMethId v_inst_name m m_port (MethodResult k) port_rename_table -- add the multiplicity to Verilog port names -- (if there are not multiple ports, no uniquifier is added) @@ -886,7 +886,7 @@ vState flags rewire_map avinst = inps = [ (mkVId (portid s ino), mkArgId m k ino, vSize argType) - | (meth@(Method m _ _ mult ps mo me), + | (meth@(Method m _ _ mult ps outs me), (argTypes,_,_)) <- zip (vFields vi) mts, -- let multu = getMethodMultUse m, @@ -908,7 +908,7 @@ vState flags rewire_map avinst = mkVId (portid s ino), mkEnId m ino, inhigh ) - | (Method m _ _ mult ss mo me@(Just (VName s,vps))) + | (Method m _ _ mult ss outs me@(Just (VName s,vps))) <- vFields vi, let inhigh = VPinhigh `elem` vps, -- let multu = getMethodMultUse m, @@ -922,9 +922,10 @@ vState flags rewire_map avinst = meth_return_vals = nub [ (mkVId (portid s ino), - mkResId m ino) - | ((Method m _ _ mult ss mo@(Just (VName s, vps)) me), (_,_,Just retType)) + mkResId m k ino) + | ((Method m _ _ mult ss outs me), (_,_,retTypes)) <- zip (vFields vi) mts, + ((VName s, vps), retType, k) <- zip3 outs retTypes (methResultNums outs), isNotZeroSized retType, -- let multu = getMethodMultUse m, ino <- if mult > 1 then map Just [0..mult-1] else [Nothing] diff --git a/src/comp/BackendNamingConventions.hs b/src/comp/BackendNamingConventions.hs index 7aec08133..ae1aae952 100644 --- a/src/comp/BackendNamingConventions.hs +++ b/src/comp/BackendNamingConventions.hs @@ -96,8 +96,8 @@ rwireHasId = mkId noPosition (mkFString rwireHasStr) rwireSetEnId, rwireSetArgId, rwireGetResId, rwireHasResId :: Id -> Id rwireSetEnId i = mkMethId i rwireSetId Nothing MethodEnable rwireSetArgId i = mkMethId i rwireSetId Nothing (MethodArg 1) -rwireGetResId i = mkMethId i rwireGetId Nothing MethodResult -rwireHasResId i = mkMethId i rwireHasId Nothing MethodResult +rwireGetResId i = mkMethId i rwireGetId Nothing (MethodResult Nothing) +rwireHasResId i = mkMethId i rwireHasId Nothing (MethodResult Nothing) -- ============================== -- Primitive CReg @@ -134,7 +134,7 @@ cregReadId n = mkId noPosition (mkFString (cregReadStr n)) cregWriteId n = mkId noPosition (mkFString (cregWriteStr n)) cregReadResId, cregWriteEnId, cregWriteArgId :: Id -> Int -> Id -cregReadResId i n = mkMethId i (cregReadId n) Nothing MethodResult +cregReadResId i n = mkMethId i (cregReadId n) Nothing (MethodResult Nothing) cregWriteEnId i n = mkMethId i (cregWriteId n) Nothing MethodEnable cregWriteArgId i n = mkMethId i (cregWriteId n) Nothing (MethodArg 1) @@ -351,7 +351,7 @@ regWriteId pos = mkId pos (mkFString regWriteStr) -- XXX no position? regReadResId, regWriteEnId, regWriteArgId :: Id -> Id -regReadResId i = mkMethId i (regReadId noPosition) Nothing MethodResult +regReadResId i = mkMethId i (regReadId noPosition) Nothing (MethodResult Nothing) regWriteEnId i = mkMethId i (regWriteId noPosition) Nothing MethodEnable regWriteArgId i = mkMethId i (regWriteId noPosition) Nothing (MethodArg 1) @@ -378,17 +378,17 @@ cregToReg old_avi = updVPort new_vn (_, ps) = (new_vn, ps) (new_vFields, new_meth_types) = - let convField (Method nm c r m [] (Just res) Nothing, ts) + let convField (Method nm c r m [] [res] Nothing, ts) | (nm == cregReadId 0) = let nm' = regReadId (getPosition nm) res' = updVPort qoutPortName res - in Just (Method nm' c r m [] (Just res') Nothing, ts) - convField (Method nm c r m [arg] Nothing (Just en), ts) + in Just (Method nm' c r m [] [res'] Nothing, ts) + convField (Method nm c r m [arg] [] (Just en), ts) | (nm == cregWriteId 0) = let nm' = regWriteId (getPosition nm) arg' = updVPort dinPortName arg en' = updVPort enPortName en - in Just (Method nm' c r m [arg'] Nothing (Just en'), ts) + in Just (Method nm' c r m [arg'] [] (Just en'), ts) convField _ = Nothing in unzip $ mapMaybe convField $ @@ -530,11 +530,11 @@ createMapForVMod :: AId -> VFieldInfo -> [(FString,FString)] createMapForVMod _ (Clock _) = [] createMapForVMod _ (Reset _) = [] createMapForVMod _ (Inout {}) = [] -createMapForVMod inst_id (Method meth_id _ _ mult ins mo me) = -- trace (ppReadable result) $ +createMapForVMod inst_id (Method meth_id _ _ mult ins outs me) = -- trace (ppReadable result) $ result where result = zip meths_fstr ports_fstr - (fmeths,fports) = createMapForOneMeth meth_id mult ins me mo + (fmeths,fports) = createMapForOneMeth meth_id mult ins outs me inst_fstr = getIdFString inst_id addInstId fs = concatFString [inst_fstr, fsDollar, fs] meths_fstr = map addInstId fmeths @@ -545,8 +545,8 @@ createMapForVMod inst_id (Method meth_id _ _ mult ins mo me) = -- trace (ppReada -- For a single method, create two lists: -- * The Bluespec names for the arguments and RDY/EN -- (for example, ["set_1","set"] or ["get"]) --- The first items in the list are the arguments, and the last is --- the return value or the enable (depending on the type of method). +-- The first items in the list are the arguments, followed by +-- the return value(s) and/or the enable (depending on the type of method). -- * The Verilog port names corresponding to the Bluespec names -- (for example, ["D_IN","EN"] or ["Q_OUT"]) -- If the method has multiplicity > 1, then the first list @@ -559,37 +559,35 @@ createMapForVMod inst_id (Method meth_id _ _ mult ins mo me) = -- trace (ppReada -- mkMethId in ASyntax -- the two lists should be the same length (this is checked) createMapForOneMeth :: Id -> Integer -> - [VPort] -> Maybe VPort -> Maybe VPort -> + [VPort] -> [VPort] -> Maybe VPort -> ([FString],[FString]) -createMapForOneMeth meth_id mult ins me mo = if check then +createMapForOneMeth meth_id mult ins outs me = if check then -- trace (ppReadable (method_names, verilog_names)) $ (method_names, verilog_names) else err where check = length method_names == length verilog_names err = internalError ("createMapForOneMeth " ++ - ppReadable (meth_id, mult, ins, me, mo)) + ppReadable (meth_id, mult, ins, me, outs)) meth_fstr = getIdFString meth_id meth_mult = if mult <= 1 then [meth_fstr] else [ concatFString [meth_fstr, fsUnderscore, mkNumFString n] | n <- [0 .. mult-1] ] - -- for method "x", make the names "x_1, x_2, .." for the ports - -- make the names x__n for multi-ported methods - method_input_names = [ addNum meth_n arg_n | + -- for method "x", make the names "x_ARG_1, x_ARG_2, .." for the ports + -- make the names x__ARG_n for multi-ported methods + method_input_names = [ mkMethArgStr meth_n (toInteger arg_n) | meth_n <- meth_mult, arg_n <- [1 .. length ins]] - addNum fs n = - concatFString [fs, fsUnderscore, (mkNumFString (toInteger n))] - -- the Verilog port names for the above verilog_input_names = map getFStringForVerilogPair ins - -- names for the output port - (method_output_names, verilog_output_name) = - case (mo) of - Nothing -> ([], []) - Just p -> (meth_mult, [getFStringForVerilogPair p]) + -- names for the output ports + method_output_names = [ mkMethResStr meth_n out_n | + meth_n <- meth_mult, out_n <- methResultNums outs] + + -- the Verilog port names for the above + verilog_output_names = map getFStringForVerilogPair outs -- names for the enable (method_enable_names, verilog_enable_name) = @@ -608,14 +606,14 @@ createMapForOneMeth meth_id mult ins me mo = if check then verilog_names_pre_mult = verilog_input_names ++ verilog_enable_name ++ - verilog_output_name + verilog_output_names -- handle the multiplicity for verilog names here -- note how we go from 1..mult instead of 0..mult-1 -- as the method side does verilog_names = if (mult <= 1) then verilog_names_pre_mult - else [addNum fs n | -- PORT_N + else [concatFString [fs, fsUnderscore, (mkNumFString (toInteger n))] | -- PORT_N fs <- verilog_names_pre_mult, n <- [1..mult]] diff --git a/src/comp/BinData.hs b/src/comp/BinData.hs index 357ff0682..81fcef9dc 100644 --- a/src/comp/BinData.hs +++ b/src/comp/BinData.hs @@ -999,6 +999,7 @@ instance Bin AType where writeBytes (ATReal) = do putI 2; writeBytes (ATArray sz t) = do putI 3; toBin sz; toBin t writeBytes (ATAbstract i szs) = do putI 4; toBin i; toBin szs + writeBytes (ATTuple ts) = do putI 5; toBin ts readBytes = do i <- getI case i of @@ -1007,6 +1008,7 @@ instance Bin AType where 2 -> do return ATReal 3 -> do sz <- fromBin; t <- fromBin; return (ATArray sz t) 4 -> do i <- fromBin; szs <- fromBin; return (ATAbstract i szs) + 5 -> do ts <- fromBin; return (ATTuple ts) n -> internalError $ "GenABin.Bin(AType).readBytes: " ++ show n -- ---------- @@ -1036,6 +1038,8 @@ instance Bin AExpr where writeBytes (AMGate t obj clk) = section "AExpr" $ do putI 14; toBin t; toBin obj; toBin clk writeBytes (ASInout t iot) = section "AExpr" $ do putI 15; toBin t; toBin iot writeBytes (ASReal i t val) = section "AExpr" $ do putI 16; toBin i; toBin t; toBin val + writeBytes (ATupleSel t e idx) = section "AExpr" $ do putI 17; toBin t; toBin e; toBin idx + writeBytes (ATuple t es) = section "AExpr" $ do putI 18; toBin t; toBin es readBytes = do i <- getI case i of @@ -1069,6 +1073,10 @@ instance Bin AExpr where 15 -> do t <- fromBin; iot <- fromBin; return (ASInout t iot) 16 -> do { i <- fromBin; t <- fromBin; val <- fromBin; return (ASReal i t val) } + 17 -> do { t <- fromBin; e <- fromBin; idx <- fromBin; + return (ATupleSel t e idx) } + 18 -> do { t <- fromBin; es <- fromBin; + return (ATuple t es) } n -> internalError $ "GenABin.Bin(IExpr).readBytes: " ++ show n -- toBin e = Out [AExp e] () -- fromBin = readShared diff --git a/src/comp/CSyntax.hs b/src/comp/CSyntax.hs index 91be040d4..9098c5a1b 100644 --- a/src/comp/CSyntax.hs +++ b/src/comp/CSyntax.hs @@ -1311,9 +1311,11 @@ instance PPrint CExpr where f (Inout i (VName p) mc mr) = t "inout_field " <> ppVarId d i <+> t p <+> mfi "clocked_by" mc <+> mfi "reset_by" mr - f (Method i mc mr n ps mo me) = + f (Method i mc mr n ps os me) = ppVarId d i <> g n <+> t "=" <+> t (unwords (map h ps)) <+> - mfi "clocked_by" mc <+> mfi "reset_by" mr <+> mfp "output" mo <+> mfp "enable" me + mfi "clocked_by" mc <+> mfi "reset_by" mr <+> + (if null os then empty else t"output" <+> t (unwords (map h os))) <+> + mfp "enable" me g 1 = t"" g n = t("[" ++ itos n ++ "]") h (s,[]) = show s diff --git a/src/comp/CType.hs b/src/comp/CType.hs index d914decbe..657fad091 100644 --- a/src/comp/CType.hs +++ b/src/comp/CType.hs @@ -457,14 +457,20 @@ getActionValueArg t = internalError ("getActionValueArg: " ++ ppReadable t) -- These are used during foreign function processing to determine if arguments -- and return values are polymorphic or of a known size. isTypePolyBit :: Type -> Bool +isTypePolyBit (TAp (TCon (TyCon i _ _)) (TAp (TCon (TyCon i' _ _)) arg)) + | (i == idActionValue) || (i == idActionValue_), (i' == idBit) = isTVar arg isTypePolyBit (TAp (TCon (TyCon i _ _)) arg) | (i == idBit) || (i == idActionValue) || (i == idActionValue_) = isTVar arg isTypePolyBit _ = False +-- Note that this is only used for foreign functions, so it does not currently handle tuples of Bits bitWidth :: Type -> Integer +bitWidth (TAp (TCon (TyCon i _ _)) (TAp (TCon (TyCon i' _ _)) arg)) + | ((i == idActionValue) || (i == idActionValue_)) && + (i' == idBit) && + (isTNum arg) = getTNum arg bitWidth (TAp (TCon (TyCon i _ _)) arg) - | ((i == idBit) || (i == idActionValue) || (i == idActionValue_)) && - (isTNum arg) = getTNum arg + | (i == idBit) && (isTNum arg) = getTNum arg bitWidth t = internalError $ "bitWidth: not a Bit type of known width -- " ++ (show t) diff --git a/src/comp/CVPrint.hs b/src/comp/CVPrint.hs index bd4aa74e5..3c7dc29ff 100644 --- a/src/comp/CVPrint.hs +++ b/src/comp/CVPrint.hs @@ -850,7 +850,7 @@ ppVeriMethod d _ (Inout i (VName s) mclk mrst) = (case mrst of Nothing -> empty Just i -> t"reset_by (" <> pvpId d i <> t")") -ppVeriMethod d mr (Method i mc mreset n pts mo me) = +ppVeriMethod d mr (Method i mc mreset n pts os me) = let f _ _ Nothing = empty f before after (Just (VName vn, prs)) = (case prs of @@ -859,7 +859,10 @@ ppVeriMethod d mr (Method i mc mreset n pts mo me) = (t (before ++ vn ++ after)) in t"method " <> - (f "" " " mo) <> + (case os of + [] -> empty + [o] -> f "" " " (Just o) + _ -> t"(" <> sepList (map (f "" " " . Just) os) (t",") <> t")") <> (pvpId d i <> (if n == 1 then empty else (t"[" <> (pp d n) <> t"]")) <> (t"(" <> sepList (map (f "" "" . Just) pts) (t",") <> t")") <> diff --git a/src/comp/DisjointTest.hs b/src/comp/DisjointTest.hs index 88d177c79..896c3ac11 100644 --- a/src/comp/DisjointTest.hs +++ b/src/comp/DisjointTest.hs @@ -11,12 +11,13 @@ module DisjointTest( import qualified Data.Set as S import qualified Data.Map as M import Control.Monad(foldM {- , when -}) +import Data.List (genericIndex) import Util(ordPair,uniquePairs) -import Error(ErrorHandle) +import Error(ErrorHandle, internalError) import Pretty -import PPrint(PPrint(..)) +import PPrint(PPrint(..), ppReadable) import Flags import ASyntax @@ -24,7 +25,7 @@ import ASyntaxUtil(AExprs(..), aAnd) import Pragma import VModInfo(VModInfo) -import AExpr2Util(getMethodOutputPort) +import AExpr2Util(getMethodOutputPorts) --import Debug.Trace(trace) import qualified AExpr2STP as STP @@ -270,9 +271,26 @@ buildSupportMap adefs avis rs = --trace ("XXX support map:" ++ ppReadable res) $ findSupport e@(ASDef _ i) = [DDef def i] where def = M.findWithDefault (err i) i idToDef findSupport e@(APrim { ae_args = es}) = findAExprs findSupport es - findSupport e@(AMethCall {ae_args = es}) = findAExprs findSupport es ++ [DMethod (ae_objid e) vlogport] - where vlogport = getMethodOutputPort portMap (ae_objid e) (ameth_id e) - findSupport e@(AMethValue {}) = [DMethod (ae_objid e) (ameth_id e)] + findSupport e@(AMethCall {ae_args = es}) = + case getMethodOutputPorts portMap (ae_objid e) (ameth_id e) of + [vlogport] -> findAExprs findSupport es ++ [DMethod (ae_objid e) vlogport] + ports -> internalError ("buildSupportMap: unexpected output ports: " + ++ ppReadable (ae_objid e, ameth_id e, ports)) + findSupport e@(AMethValue {}) = + case getMethodOutputPorts portMap (ae_objid e) (ameth_id e) of + [vlogport] -> [DMethod (ae_objid e) vlogport] + ports -> internalError ("buildSupportMap: unexpected output ports: " + ++ ppReadable (ae_objid e, ameth_id e, ports)) + findSupport (ATupleSel _ e@(AMethCall {ae_args = es}) idx) = + findAExprs findSupport es ++ [DMethod (ae_objid e) vlogport] + where + ports = getMethodOutputPorts portMap (ae_objid e) (ameth_id e) + vlogport = genericIndex ports (idx - 1) + findSupport (ATupleSel _ e@(AMethValue {}) idx) = + [DMethod (ae_objid e) vlogport] + where + ports = getMethodOutputPorts portMap (ae_objid e) (ameth_id e) + vlogport = genericIndex ports (idx - 1) findSupport e@(ANoInlineFunCall{ ae_args = es}) = findAExprs findSupport es findSupport e@(ATaskValue {ae_objid=id}) = [DTask id] findSupport e@(ASPort {ae_objid = id}) = [DLeaf id] diff --git a/src/comp/GenABin.hs b/src/comp/GenABin.hs index 6cc685e29..c2c855fd5 100644 --- a/src/comp/GenABin.hs +++ b/src/comp/GenABin.hs @@ -34,7 +34,7 @@ import qualified Data.ByteString as B -- .ba file tag -- change this whenever the .ba format changes -- See also GenBin.header header :: [Byte] -header = B.unpack $ TE.encodeUtf8 $ T.pack "bsc-ba-20260427-1" +header = B.unpack $ TE.encodeUtf8 $ T.pack "bsc-ba-20260616-1" genABinFile :: ErrorHandle -> String -> ABin -> IO () genABinFile errh fn abin = diff --git a/src/comp/GenBin.hs b/src/comp/GenBin.hs index 364cb599b..f2fc430e9 100644 --- a/src/comp/GenBin.hs +++ b/src/comp/GenBin.hs @@ -27,7 +27,7 @@ doTrace = elem "-trace-genbin" progArgs -- .bo file tag -- change this whenever the .bo format changes -- See also GenABin.header header :: [Byte] -header = B.unpack $ TE.encodeUtf8 $ T.pack "bsc-bo-20260427-1" +header = B.unpack $ TE.encodeUtf8 $ T.pack "bsc-bo-20260616-1" genBinFile :: ErrorHandle -> String -> CSignature -> CSignature -> IPackage a -> IO () diff --git a/src/comp/GenWrap.hs b/src/comp/GenWrap.hs index 997e962e5..42bf42d73 100644 --- a/src/comp/GenWrap.hs +++ b/src/comp/GenWrap.hs @@ -684,11 +684,11 @@ fixCModuleVerilog n (ss,ts,ps) in [mStmtSPTO vp e] saveArgTypes _ = [] let saveFieldTypes finf (Method { vf_inputs = inps, - vf_output = mo }) = do + vf_outputs = outs }) = do let rt = ret_type finf isAV <- isActionValue rt output_type <- if isAV then getAVType "fixCModVer" rt else return rt - let output_stmt = maybeToList (fmap ((flip mStmtSPT) rt) mo) + let output_stmt = map ((flip mStmtSPT) rt) outs -- we let the type-checker error on mismatches return (output_stmt ++ (zipWith mStmtSPT inps (arg_types finf))) saveFieldTypes finf (Inout { vf_inout = vn }) = do @@ -796,7 +796,7 @@ procType (n, ns, as, ts, ctx) ty = do if isAV then do av_t <- getAVType "procType" ty return (n+1, newId:ns, newSVar:as, - (ty, (TAp tActionValue_ (cTVarNum newId))):ts, + (ty, (TAp tActionValue_ (TAp tBit (cTVarNum newId)))):ts, (bitsCtx av_t newSVar):ctx) else do isInout <- isInoutType ty @@ -1112,10 +1112,13 @@ genTo pps ty mk = localPrefix = joinStrings_ currentPre localPrefix1 prefix = stringLiteralAt noPosition localPrefix arg_names = mkList (getPosition f) [stringLiteralAt (getPosition i) (getIdString i) | i <- aIds] - fnp = mkTypeProxyExpr $ TAp (cTCon idStrArg) $ cTStr (fieldPathName prefixes f)(getIdPosition f) + localResult1 = fromMaybe (getIdBaseString f) (lookupResultIfcPragma ciPrags) + localResult = joinStrings_ currentPre localResult1 + result = stringLiteralAt noPosition localResult + fnp = mkTypeProxyExpr $ TAp (cTCon idStrArg) $ cTStr (fieldPathName prefixes f) (getIdPosition f) -- XXX idEmpty is a horrible way to know no more selection is required let ec = if f == idEmpty then sel else CSelect sel (setInternal f) - let e = CApply (CVar idToWrapField) [fnp, prefix, arg_names, ec] + let e = CApply (CVar idToWrapField) [fnp, prefix, arg_names, result, ec] return [CLValue (binId prefixes f) [CClause [] [] e] []] -- -------------------- @@ -1637,10 +1640,10 @@ fixupVeriField _ _ f@(Reset { }) = f fixupVeriField _ _ f@(Inout { }) = f fixupVeriField pps vportprops m@(Method { }) = m { vf_inputs = inputs', - vf_output = output', + vf_outputs = outputs', vf_enable = enable'' } where inputs' = map fixup (vf_inputs m) - output' = fmap fixup (vf_output m) + outputs' = map fixup (vf_outputs m) enable' = fmap fixup (vf_enable m) fixup = fixupPort vportprops alwaysEnabled = isAlwaysEn pps (vf_name m) @@ -2044,10 +2047,8 @@ genNewMethodIfcPragmas ifcp pragmas fieldId newFieldId = ar = if (isAlwaysReadyIfc joinedPrags) then [PIAlwaysRdy ] else [] ae = if (isAlwaysEnabledIfc joinedPrags) then [PIAlwaysEnabled ] else [] -- The result names used the prefix plus the given of generated name - mResName = lookupResultIfcPragma pragmas - resultName = case mResName of - Just str -> joinStrings_ currentPre str - Nothing -> joinStrings_ currentPre methodStr + localResult1 = fromMaybe (getIdString fieldId) (lookupResultIfcPragma pragmas) + resultName = joinStrings_ currentPre localResult1 -- resName = (PIResultName resultName) -- The ready name @@ -2203,14 +2204,11 @@ mkFieldSavePortTypeStmts v ifcId = concatMapM $ meth noPrefixes ifcId _ -> do -- Compute the local prefix and result name for this field in the flattened interface -- from the current prefixes and pragmas from the field definition. - let methodStr = getIdBaseString f - currentPre = ifcp_renamePrefixes prefixes -- the current rename prefix + let currentPre = ifcp_renamePrefixes prefixes -- the current rename prefix localPrefix1 = fromMaybe (getIdBaseString f) (lookupPrefixIfcPragma ciPrags) localPrefix = joinStrings_ currentPre localPrefix1 - mResName = lookupResultIfcPragma ciPrags - resultName = case mResName of - Just str -> joinStrings_ currentPre str - Nothing -> joinStrings_ currentPre methodStr + localResult1 = fromMaybe (getIdBaseString f) (lookupResultIfcPragma ciPrags) + localResult = joinStrings_ currentPre localResult1 -- Arguments to saveFieldPortTypes: proxies for the field name as a type level string and the field type, -- and the values for the prefix, arg_names, and result pragmas. @@ -2218,7 +2216,7 @@ mkFieldSavePortTypeStmts v ifcId = concatMapM $ meth noPrefixes ifcId proxy = mkTypeProxyExpr $ foldr arrow r as prefix = stringLiteralAt noPosition localPrefix arg_names = mkList (getPosition f) [stringLiteralAt (getPosition i) (getIdString i) | i <- aIds] - result = stringLiteralAt noPosition resultName + result = stringLiteralAt noPosition localResult return [ CSExpr Nothing $ cVApply idLiftModule $ diff --git a/src/comp/IExpand.hs b/src/comp/IExpand.hs index 4e45159ed..807e5e352 100644 --- a/src/comp/IExpand.hs +++ b/src/comp/IExpand.hs @@ -318,7 +318,7 @@ iExpand errh flags symt alldefs is_noinlined_func pps def@(IDef mi _ _ _) = do in -- return the expression that should replace the heap pointer, -- and maybe a Def, if the expression is a def reference - if simple e || isActionType t then + if simple e || isActionType t || isPairType t then -- inline the expression, no def is created for this heap ptr (e', Nothing) else @@ -1043,11 +1043,11 @@ iExpandField modId implicitCond clkRst (i, bi, e, t) = do showTopProgress ("Elaborating method " ++ quote (pfpString i)) setIfcSchedNameScopeProgress (Just (IEP_Method i False)) (_, P p e') <- evalUH e - let (ins, eb) = case e' of - ICon _ (ICMethod _ ins eb) -> (ins, eb) + let (ins, outs, eb) = case e' of + ICon _ (ICMethod _ ins outs eb) -> (ins, outs, eb) _ -> internalError ("iExpandField: expected ICMethod: " ++ ppReadable e') (its, ((IDef i1 t1 e1 _), ws1, fi1), ((IDef wi wt we _), ws2, fi2)) - <- iExpandMethod modId 1 [] (pConj implicitCond p) clkRst (i, bi, ins, eb) + <- iExpandMethod modId 1 [] (pConj implicitCond p) clkRst (i, bi, ins, outs, eb) let wp1 = wsToProps ws1 -- default clock domain forced in by iExpandField let wp2 = wsToProps ws2 setIfcSchedNameScopeProgress Nothing @@ -1056,10 +1056,10 @@ iExpandField modId implicitCond clkRst (i, bi, e, t) = do -- expand a method iExpandMethod :: Id -> Integer -> [Id] -> HPred -> - (HClock, HReset) -> (Id, BetterInfo.BetterInfo, [String], HExpr) -> + (HClock, HReset) -> (Id, BetterInfo.BetterInfo, [String], [String], HExpr) -> G ([(Id, IType)], (HDef, HWireSet, VFieldInfo), (HDef, HWireSet, VFieldInfo)) -iExpandMethod modId n args implicitCond clkRst@(curClk, _) (i, bi, ins, e) = do +iExpandMethod modId n args implicitCond clkRst@(curClk, _) (i, bi, ins, outs, e) = do when doDebug $ traceM ("iExpandMethod " ++ ppString i ++ " " ++ ppReadable e) (_, P p e') <- evalUH e case e' of @@ -1069,23 +1069,24 @@ iExpandMethod modId n args implicitCond clkRst@(curClk, _) (i, bi, ins, e) = do -- a GenWrap-added context that wasn't satisfied, and GenWrap -- should only be adding Bits) errG (reportNonSynthTypeInMethod modId i e') - ILam li ty eb -> iExpandMethodLam modId n args implicitCond clkRst (i, bi, ins, eb) li ty p - _ -> iExpandMethod' implicitCond curClk (i, bi, e') p + ILam li ty eb -> iExpandMethodLam modId n args implicitCond clkRst (i, bi, ins, outs, eb) li ty p + _ -> iExpandMethod' implicitCond curClk (i, bi, outs, e') p iExpandMethodLam :: Id -> Integer -> [Id] -> HPred -> - (HClock, HReset) -> (Id, BetterInfo.BetterInfo, [String], HExpr) -> + (HClock, HReset) -> (Id, BetterInfo.BetterInfo, [String], [String], HExpr) -> Id -> IType -> Pred HeapData -> G ([(Id, IType)], (HDef, HWireSet, VFieldInfo), (HDef, HWireSet, VFieldInfo)) -iExpandMethodLam modId n args implicitCond clkRst (i, bi, ins, eb) li ty p = do - -- traceM ("iExpandMethodLam " ++ ppString i ++ " " ++ show ins) +iExpandMethodLam modId n args implicitCond clkRst (i, bi, ins, outs, eb) li ty p = do + --traceM ("iExpandMethodLam " ++ ppString i ++ " " ++ show (ins, outs)) + if null ins then internalError "iExpandMethodLam: no inputs" else return () let i' :: Id i' = mkId (getPosition i) $ mkFString $ head ins -- substitute argument with a modvar and replace with body eb' :: HExpr eb' = eSubst li (ICon i' (ICMethArg ty)) eb (its, (d, ws1, wf1), (wd, ws2, wf2)) <- - iExpandMethod modId (n+1) (i':args) (pConj implicitCond p) clkRst (i, bi, tail ins, eb') + iExpandMethod modId (n+1) (i':args) (pConj implicitCond p) clkRst (i, bi, tail ins, outs, eb') let inps :: [VPort] inps = vf_inputs wf1 let wf1' :: VFieldInfo @@ -1094,11 +1095,11 @@ iExpandMethodLam modId n args implicitCond clkRst (i, bi, ins, eb) li ty p = do _ -> internalError "iExpandMethodLam: unexpected wf1" return ((i', ty) : its, (d, ws1, wf1'), (wd, ws2, wf2)) -iExpandMethod' :: HPred -> HClock -> (Id, BetterInfo.BetterInfo, HExpr) -> +iExpandMethod' :: HPred -> HClock -> (Id, BetterInfo.BetterInfo, [String], HExpr) -> Pred HeapData -> G ([(Id, IType)], (HDef, HWireSet, VFieldInfo), (HDef, HWireSet, VFieldInfo)) -iExpandMethod' implicitCond curClk (i, bi, e0) p0 = do +iExpandMethod' implicitCond curClk (i, bi, outs, e0) p0 = do norm <- getTypeNormalizerC -- want the result type, not a type including arguments let methType :: IType @@ -1142,7 +1143,7 @@ iExpandMethod' implicitCond curClk (i, bi, e0) p0 = do IAps f@(ICon _ (ICTuple {})) ts [e1, e2] | isActionType methType -> let pos = getIdPosition i - vt = actionValue_BitN methType + vt = getAV_Type methType v = icUndetAt pos vt UNotUsed in (IAps f ts [v, icNoActions], ws) _ -> internalError "iExpandMethod: fixupActionWireSet" @@ -1158,8 +1159,8 @@ iExpandMethod' implicitCond curClk (i, bi, e0) p0 = do rdyId = mkRdyId i let enablePort :: Maybe VPort enablePort = toMaybe (isActionType methType) (BetterInfo.mi_enable bi) - let outputPort :: Maybe VPort - outputPort = toMaybe (isValueType methType) (BetterInfo.mi_result bi) + let outputPorts :: [VPort] + outputPorts = map (id_to_vPort . mkId (getPosition i) . mkFString) outs let rdyPort :: VPort rdyPort = BetterInfo.mi_ready bi @@ -1171,12 +1172,12 @@ iExpandMethod' implicitCond curClk (i, bi, e0) p0 = do Method { vf_name = i, vf_clock = methClock, vf_reset = methReset, vf_mult = 1, vf_inputs = [], - vf_output = outputPort, vf_enable = enablePort }), + vf_outputs = outputPorts, vf_enable = enablePort }), ((IDef rdyId itBit1 readySignal []), final_ws, Method { vf_name = rdyId, vf_clock = methClock, vf_reset = methReset, vf_mult = 1, vf_inputs = [], - vf_output = Just rdyPort, vf_enable = Nothing })) + vf_outputs = [rdyPort], vf_enable = Nothing })) -- deduce clock name for VFieldInfo -- type required to control ancestry-checking with action methods @@ -2561,20 +2562,16 @@ walkNF e = -- XXX is adding the clock to the wire set redundant? clk@(ICon i (ICClock { iClock = c })) : _ -> upd (pConj p0 p) (IAps f ts es') (wsAddClock c ws) - -- if the outer selector is avValue_ or avAction_ - -- and the inner is a method call - [(IAps sel@(ICon i_sel2 (ICSel { })) ts_2 es_2)] - | (i_sel == idAVValue_ || i_sel == idAVAction_) -> do - case es_2 of - st@(ICon i (ICStateVar { iVar = v })) : _ -> - handleMethod i_sel2 v - _ -> internalError ("walkNF: selector should be a method call") - - -- the inner selector can wind up on the heap - -- because of "move" in evalHeap - [e_ref@(IRefT t ptr ref)] | (isitActionValue_ t) || (isitAction t) - -> do (P p' e', ws) <- walkNF e_ref - upd (pConj p0 p') (IAps f ts [e']) ws + -- We can be selecting the avValue or avAction from an ActionValue method, + -- or a tuple member out of the result of calling a method with multiple outputs, + -- and need to recurse. + [e] | (i_sel == idAVValue_ || + i_sel == idAVAction_ || + i_sel == idPrimFst || + i_sel == idPrimSnd) -> do + do (P p' e', ws) <- walkNF e + upd (pConj p0 p') (IAps f ts [e']) ws + _ -> do when doDebug $ traceM "not stvar or foreign\n" when doDebug $ traceM (show u ++ "\n") when doDebug $ traceM (show es' ++ "\n") @@ -2589,6 +2586,11 @@ walkNF e = (P p' e', ws) <- walkNF e upd (pConjs [p0, p, p']) e' ws + IAps f@(ICon _ (ICTuple {})) ts [e1, e2] -> do + (P pe1 e1', ws1) <- walkNF e1 + (P pe2 e2', ws2) <- walkNF e2 + upd (pConj pe1 pe2) (IAps f ts [e1', e2']) (wsJoin ws1 ws2) + -- Any other application is not in NF (which is unexpected?) IAps f ts es -> do _ <- internalError ("walkNF fall-through: " ++ ppReadable (f,ts,es)) @@ -3167,10 +3169,16 @@ conAp' i (ICPrim _ PrimIsRawUndefined) _ (T t : E e : as) = do _ -> -- do traceM ("IsRawUndefined: False") return (P p iFalse) -conAp' i (ICPrim _ PrimMethod) _ [T t, E eInNames, E meth] = do +conAp' i (ICPrim _ PrimMethod) _ [T t, E eInNames, E eOutNames, E meth] = do (inNames, _) <- evalStringList eInNames + (outNames, _) <- evalStringList eOutNames P p meth' <- eval1 meth - return $ P p $ ICon (dummyId noPosition) $ ICMethod {iConType = t, iInputNames = inNames, iMethod = meth'} + return $ P p $ ICon (dummyId noPosition) $ ICMethod { + iConType = t, + iInputNames = inNames, + iOutputNames = outNames, + iMethod = meth' + } -- XXX is this still needed? conAp' i (ICUndet { iConType = t }) e as | t == itClock = @@ -3894,7 +3902,7 @@ conAp' _ (ICPrim _ op) fe@(ICon prim_id _) as | strictPrim op = do when doTrans $ traceM ("conAp: iTransform fallthrough: " ++ ppReadable (op, mkAp fe as')) errh <- getErrHandle case (iTransExpr errh (mkAp fe as')) of - (e', True) -> do + (e', True) | isBitType (iGetType e') -> do -- we used to evaluate further here, but that shouldn't -- be necessary (and probably indicates a bug elsewhere) when (doDebug || doTrans) $ traceM ("conAp: iTransform result: " ++ ppReadable e') @@ -4876,6 +4884,11 @@ doSel sel s tys ty n as ee (p, e) = -- canonical applications are strict (e.g. method call applications) _ | isCanon e -> bldApUH' "Sel" sel (map T tys ++ (E ee : as)) + -- tuple section from a multi-output method result + _ | s == idPrimFst || s == idPrimSnd -> do + (_, P p e') <- evalUH e + addPredG p $ bldApUH' "Sel PrimFst/Snd" sel (map T tys ++ (E e' : as)) + -- otherwise fail _ -> internalError ("doSel: " ++ ppReadable (sel, e, as)) diff --git a/src/comp/IExpandUtils.hs b/src/comp/IExpandUtils.hs index 79c9a1425..330b742ef 100644 --- a/src/comp/IExpandUtils.hs +++ b/src/comp/IExpandUtils.hs @@ -362,19 +362,24 @@ isPrimType (ITCon i _ _) = i == idPrimAction || -- i == idInteger i == idFmt || -- also not really a primitive i == idClock || - i == idReset + i == idReset || + i == idPrimUnit +-- ActionValue_ must be applied to (a tuple of) Bit +isPrimType (ITAp (ITCon i _ _) t) + | i == idActionValue_ = t == itPrimUnit || isBitTupleType t -- Primitive constructor applied to numeric type(s) -- We normalize types so no unresolved numeric types should escape elaboration. isPrimType (ITAp a (ITNum _)) = isPrimTAp a -- Primitive arrays isPrimType (ITAp (ITCon i _ _) elem_ty) | i == idPrimArray = isPrimType elem_ty +-- Tuples of bits +isPrimType t | isBitTupleType t = True isPrimType _ = False -- Primitive type applications isPrimTAp :: IType -> Bool isPrimTAp (ITCon _ _ (TIstruct SInterface{} _)) = True -isPrimTAp (ITCon i _ _) = i == idActionValue_ || - i == idBit || +isPrimTAp (ITCon i _ _) = i == idBit || i == idInout_ -- Again, no unresolved numeric types should escape elaboration. isPrimTAp (ITAp a (ITNum _)) = isPrimTAp a @@ -2069,8 +2074,8 @@ chkIfcPortNames errh args ifcs (ClockInfo ci co _ _) (ResetInfo ri ro) = ifc_port_names = [ (n, i) - | IEFace {ief_fieldinfo = Method i _ _ _ ins out en} <- ifcs, - (VName n, _) <- ins ++ maybeToList out ++ maybeToList en ] + | IEFace {ief_fieldinfo = Method i _ _ _ ins outs en} <- ifcs, + (VName n, _) <- ins ++ outs ++ maybeToList en ] ifc_inout_names = [ (n, i) | IEFace {ief_fieldinfo = Inout i (VName n) _ _} <- ifcs ] ifc_clock_names = diff --git a/src/comp/IInlineFmt.hs b/src/comp/IInlineFmt.hs index 54c117277..347e07a50 100644 --- a/src/comp/IInlineFmt.hs +++ b/src/comp/IInlineFmt.hs @@ -354,12 +354,13 @@ createValueExprs x = [createValueExpr x] -- ############################################################################# createValueExpr :: IExpr a -> IExpr a -createValueExpr (IAps (ICon c (ICSel {})) [ITNum s] [e@(IAps (ICon _ (ICForeign {})) _ _)]) | c == idAVAction_ +createValueExpr (IAps (ICon c (ICSel {})) [ITAp b (ITNum s)] [e@(IAps (ICon _ (ICForeign {})) _ _)]) + | c == idAVAction_, b == itBit = x - where x = (IAps (ICon idAVValue_ (ICSel {iConType = tt , selNo = 0, numSel = 2 })) [ITNum s] [e]) + where x = (IAps (ICon idAVValue_ (ICSel {iConType = tt , selNo = 0, numSel = 2 })) [ITAp itBit $ ITNum s] [e]) v0 = head tmpVarIds - tt = ITForAll v0 IKNum (ITAp (ITAp (ITCon (idArrow noPosition) (IKFun IKStar (IKFun IKStar IKStar)) TIabstract) (ITAp (ITCon idActionValue_ (IKFun IKNum IKStar) (TIstruct SStruct [idAVValue_,idAVAction_])) (ITVar v0))) - (ITAp itBit (ITVar v0)) ) + tt = ITForAll v0 IKStar (ITAp (ITAp (ITCon (idArrow noPosition) (IKFun IKStar (IKFun IKStar IKStar)) TIabstract) (ITAp (ITCon idActionValue_ (IKFun IKStar IKStar) (TIstruct SStruct [idAVValue_,idAVAction_])) (ITVar v0))) + (ITVar v0) ) createValueExpr (IAps cc@(ICon i (ICPrim _ PrimIf)) ts [cond, e0, e1]) = x where x = (IAps cc [rt] [cond, e0', e1']) @@ -370,11 +371,12 @@ createValueExpr x = internalError ("createValueExpr: " ++ ppReadable x) createActionExpr :: IExpr a -> IExpr a -createActionExpr (IAps (ICon c (ICSel {})) [ITNum s] [e@(IAps (ICon _ (ICForeign {})) _ _)]) | c == idAVValue_ +createActionExpr (IAps (ICon c (ICSel {})) [ITAp b (ITNum s)] [e@(IAps (ICon _ (ICForeign {})) _ _)]) + | c == idAVValue_, b == itBit = x - where x = (IAps (ICon idAVAction_ (ICSel {iConType = tt , selNo = 1, numSel = 2 })) [ITNum s] [e]) + where x = (IAps (ICon idAVAction_ (ICSel {iConType = tt , selNo = 1, numSel = 2 })) [ITAp itBit $ ITNum s] [e]) v0 = head tmpVarIds - tt = ITForAll v0 IKNum (ITAp (ITAp (ITCon (idArrow noPosition) (IKFun IKStar (IKFun IKStar IKStar)) TIabstract) (ITAp (ITCon idActionValue_ (IKFun IKNum IKStar) (TIstruct SStruct [idAVValue_,idAVAction_])) (ITVar v0))) + tt = ITForAll v0 IKStar (ITAp (ITAp (ITCon (idArrow noPosition) (IKFun IKStar (IKFun IKStar IKStar)) TIabstract) (ITAp (ITCon idActionValue_ (IKFun IKStar IKStar) (TIstruct SStruct [idAVValue_,idAVAction_])) (ITVar v0))) itAction ) createActionExpr (IAps cc@(ICon i (ICPrim _ PrimIf)) ts [cond, e0, e1]) = x @@ -386,14 +388,16 @@ createActionExpr x = joinActions [] allStrings :: IExpr a -> Bool -allStrings (IAps (ICon c (ICSel {})) [ITNum s] [(IAps (ICon _ (ICForeign {})) _ [e])]) | c == idAVAction_ && iGetType e == itString +allStrings (IAps (ICon c (ICSel {})) [ITAp b (ITNum s)] [(IAps (ICon _ (ICForeign {})) _ [e])]) + | c == idAVAction_ && b == itBit && iGetType e == itString = True allStrings (IAps (ICon i (ICPrim _ PrimIf)) _ [_, e0, e1]) = allStrings e0 && allStrings e1 allStrings _ = False createStringExpr :: IExpr a -> IExpr a -createStringExpr (IAps (ICon c (ICSel {})) [ITNum s] [(IAps (ICon _ (ICForeign {})) _ [e])]) | c == idAVAction_ +createStringExpr (IAps (ICon c (ICSel {})) [ITAp b (ITNum s)] [(IAps (ICon _ (ICForeign {})) _ [e])]) + | c == idAVAction_, b == itBit = e createStringExpr (IAps cc@(ICon i (ICPrim _ PrimIf)) ts [cond, e0, e1]) = x diff --git a/src/comp/ISplitIf.hs b/src/comp/ISplitIf.hs index 93fd3c942..07ef8351e 100644 --- a/src/comp/ISplitIf.hs +++ b/src/comp/ISplitIf.hs @@ -445,7 +445,7 @@ iSplitIface flags ieface@(IEFace i xargs (Just (e,t)) Nothing wp fi) in (smap, IEFace i xargs Nothing (Just irules_opt) wp fi) else case e of (IAps (ICon av (ICTuple {fieldIds = [_val_id,_act_id]})) - [ITNum _] [val_,act_]) + [_] [val_,act_]) | (av == idActionValue_) -> let irule = IRule i [] (getIdString i) wp iTrue act_ Nothing [] irules = IRules [] [irule] -- no sps @@ -457,9 +457,9 @@ iSplitIface flags ieface@(IEFace i xargs (Just (e,t)) Nothing wp fi) iSplitIface _ _ = internalError ("iSplitIface: no expression or unexpected rule") mkExpression :: IExpr a -> IType -> Maybe (IExpr a, IType) -mkExpression val_ ty = if (0==(getAV_Size ty)) +mkExpression val_ ty = if (isEmptyType (getAV_Type ty)) then Nothing - else (Just (val_,(actionValue_BitN ty))) + else (Just (val_,(getAV_Type ty))) check_meth_rules :: (PrimOp -> Bool) -> IEFace a -> Maybe (IExpr a) diff --git a/src/comp/ISyntax.hs b/src/comp/ISyntax.hs index 09ea35e2f..dd0260966 100644 --- a/src/comp/ISyntax.hs +++ b/src/comp/ISyntax.hs @@ -820,7 +820,7 @@ data IConInfo a = -- only exists before expansion | ICSchedPragmas { iConType :: IType, iPragmas :: [CSchedulePragma] } - | ICMethod { iConType :: IType, iInputNames :: [String], iMethod :: IExpr a } + | ICMethod { iConType :: IType, iInputNames :: [String], iOutputNames :: [String], iMethod :: IExpr a } | ICClock { iConType :: IType, iClock :: IClock a } | ICReset { iConType :: IType, iReset :: IReset a } -- iReset has effective type itBit1 | ICInout { iConType :: IType, iInout :: IInout a } @@ -915,8 +915,8 @@ cmpC c1 c2 = ICIFace { ifcTyId = ti1, ifcIds = is1 } -> compare (ti1, is1) (ifcTyId c2, ifcIds c2) ICRuleAssert { iAsserts = asserts } -> compare asserts (iAsserts c2) ICSchedPragmas { iPragmas = pragmas } -> compare pragmas (iPragmas c2) - ICMethod { iInputNames = inames1, iMethod = meth1 } -> - compare (inames1, meth1) (iInputNames c2, iMethod c2) + ICMethod { iInputNames = inames1, iOutputNames = outnames1, iMethod = meth1 } -> + compare (inames1, outnames1, meth1) (iInputNames c2, iOutputNames c2, iMethod c2) -- the ICon Id is not sufficient for equality comparison for Clk/Rst ICClock { iClock = clock1 } -> compare clock1 (iClock c2) ICReset { iReset = reset1 } -> compare reset1 (iReset c2) @@ -1241,7 +1241,7 @@ instance NFData (IConInfo a) where rnf (ICIFace x1 x2 x3) = rnf3 x1 x2 x3 rnf (ICRuleAssert x1 x2) = rnf2 x1 x2 rnf (ICSchedPragmas x1 x2) = rnf2 x1 x2 - rnf (ICMethod x1 x2 x3) = rnf3 x1 x2 x3 + rnf (ICMethod x1 x2 x3 x4) = rnf4 x1 x2 x3 x4 rnf (ICClock x1 x2) = rnf2 x1 x2 rnf (ICReset x1 x2) = rnf2 x1 x2 rnf (ICInout x1 x2) = rnf2 x1 x2 @@ -1463,7 +1463,7 @@ showTypelessCI (ICValue {iConType = t, iValDef = e}) = "(ICValue)" showTypelessCI (ICIFace {iConType = t, ifcTyId = i, ifcIds = ids}) = "(ICIFace _ " ++ (show i) ++ " " ++ (show ids) ++ ")" showTypelessCI (ICRuleAssert {iConType = t, iAsserts = rps}) = "(ICRuleAssert _ " ++ (show rps) ++ ")" showTypelessCI (ICSchedPragmas {iConType = t, iPragmas = sps}) = "(ICSchedPragmas _ " ++ (show sps) ++ ")" -showTypelessCI (ICMethod {iConType = t, iInputNames = ins, iMethod = m }) = "(ICMethod " ++ (show ins) ++ " " ++ (ppReadable m) ++ ")" +showTypelessCI (ICMethod {iConType = t, iInputNames = ins, iOutputNames = outs, iMethod = m }) = "(ICMethod " ++ (show ins) ++ " " ++ (show outs) ++ " " ++ (ppReadable m) ++ ")" showTypelessCI (ICClock {iConType = t, iClock = clock}) = "(ICClock)" showTypelessCI (ICReset {iConType = t, iReset = reset}) = "(ICReset)" showTypelessCI (ICInout {iConType = t, iInout = inout}) = "(ICInout)" diff --git a/src/comp/ISyntaxUtil.hs b/src/comp/ISyntaxUtil.hs index a8f5d3476..bbe73dd93 100644 --- a/src/comp/ISyntaxUtil.hs +++ b/src/comp/ISyntaxUtil.hs @@ -121,18 +121,16 @@ isSimpleType t = t == itInteger || t == itChar isitAction :: IType -> Bool -isitAction (ITAp (ITCon i (IKFun IKNum IKStar) - (TIstruct SStruct [_,_] ) ) (ITNum x)) - | (i == idActionValue_) = (x == 0) -isitAction (ITAp (ITCon i (IKFun IKStar IKStar) _) t) - | (i == idActionValue) = t == itPrimUnit +isitAction (ITAp (ITCon i (IKFun IKStar IKStar) _ ) t) + | (i == idActionValue_) || (i == idActionValue) = isEmptyType t isitAction x = (x == itAction) --- note this returns false for x == - because ActionValue_ 0 is really an Action +-- note this returns false for x == () because ActionValue_ () is really an Action +-- Also handle ActionValue_ (Bit 0), which can be introduced by foreign functions. isitActionValue_ :: IType -> Bool -isitActionValue_ (ITAp (ITCon i (IKFun IKNum IKStar) - (TIstruct SStruct [_,_] ) ) (ITNum x)) - | x > 0 = (i == idActionValue_) +isitActionValue_ (ITAp (ITCon i (IKFun IKStar IKStar) + (TIstruct SStruct [_,_] ) ) t) = + (i == idActionValue_) && not (isEmptyType t) isitActionValue_ _ = False isitActionValue :: IType -> Bool @@ -150,11 +148,11 @@ getInout_Size t = internalError ("getInout_Size: type is not Inout_: " ++ ppReadable t) -getAV_Size :: IType -> Integer -getAV_Size (ITAp (ITCon i (IKFun IKNum IKStar) - (TIstruct SStruct [_,_] ) ) (ITNum x)) | - (i == idActionValue_) = x -getAV_Size t = internalError ("getAV_Size: type is not AV_: " ++ ppReadable t) +getAV_Type :: IType -> IType +getAV_Type (ITAp (ITCon i (IKFun IKStar IKStar) + (TIstruct SStruct [_,_] ) ) t) | + (i == idActionValue_) = t +getAV_Type t = internalError ("getAV_Type: type is not AV_: " ++ ppReadable t) getAVType :: IType -> Maybe IType getAVType (ITAp (ITCon i (IKFun IKStar IKStar) _) t) | i == idActionValue = Just t @@ -176,20 +174,28 @@ itList, itMaybe :: IType -> IType itList t = ITAp (ITCon idList (IKFun IKStar IKStar) tiList) t itMaybe t = ITAp (ITCon idMaybe (IKFun IKStar IKStar) tiMaybe) t +isPairType :: IType -> Bool +isPairType (ITAp (ITAp (ITCon i _ _) _) _) = i == idPrimPair +isPairType _ = False + +isEmptyType :: IType -> Bool +isEmptyType (ITCon i _ _) = i == idPrimUnit +isEmptyType (ITAp c (ITNum 0)) = c == itBit +isEmptyType t = False + isBitType :: IType -> Bool isBitType (ITAp c n) = c == itBit isBitType _ = False +isBitTupleType :: IType -> Bool +isBitTupleType (ITAp (ITAp (ITCon i _ _) t1) t2) | i == idPrimPair = + isBitType t1 && isBitTupleType t2 +isBitTupleType t = isBitType t + -- extension point for ActionValue methods isActionType :: IType -> Bool isActionType x = (x == itAction) || (isitActionValue_ x) || (isitAction x) --- extension point for ActionValue methods -isValueType :: IType -> Bool -isValueType x | (isitActionValue_ x) && (getAV_Size x > 0) = True -isValueType (ITAp t n) | t == itBit = True -isValueType _ = False - -- Constructors iMkLit :: IType -> Integer -> IExpr a iMkLit t i = ICon idIntLit (ICInt { iConType = t, iVal = ilDec i }) @@ -1093,10 +1099,6 @@ joinActions [] = icNoActions joinActions as = foldr1 ja as where ja a1 a2 = IAps icJoinActions [] [a1, a2] --- perhaps the position information should be transferred over XXX -actionValue_BitN :: IType -> IType -actionValue_BitN t = itBitN (getAV_Size t) - iStrToInt :: String -> Position -> IExpr a iStrToInt s pos = iMkLitAt pos itInteger i where i = foldl sumString 0 s diff --git a/src/comp/ITransform.hs b/src/comp/ITransform.hs index 4b76fce44..28f15f0aa 100644 --- a/src/comp/ITransform.hs +++ b/src/comp/ITransform.hs @@ -249,8 +249,8 @@ runCSE e@(IAps _ _ _) = do -- because "runCSE" is called from iTrExpr, which already recurses on the -- arguments, so runCSE will already have been called on the arguments. let t = iGetType e - -- Only CSE applications that are not actions - if not (isActionType t) then + -- Only CSE applications that are not actions or tuple method values + if not (isActionType t || isPairType t) then newExprT t e else return e diff --git a/src/comp/IfcBetterInfo.hs b/src/comp/IfcBetterInfo.hs index 8baded88b..a519d8877 100644 --- a/src/comp/IfcBetterInfo.hs +++ b/src/comp/IfcBetterInfo.hs @@ -25,7 +25,6 @@ import VModInfo -- and for recording the types of external method ports data BetterInfo = BetterMethodInfo { mi_id :: Id, -- method Id - mi_result :: VPort, -- possible rename for method result mi_ready :: VPort, -- for ready signal mi_enable :: VPort, -- for enable signal mi_prefix :: Id -- default prefix for arguments (which are not found in classic) @@ -49,7 +48,6 @@ matchMethodName id mn = qualEq id (mi_id mn) -- creates a basic method remaing noMethodInfo :: Id -> BetterInfo noMethodInfo fieldId = BetterMethodInfo {mi_id = fieldId, - mi_result = id_to_vPort fieldId, mi_ready = id_to_vPort $ mkRdyId fieldId, mi_enable = id_to_vPort $ mkEnableId fieldId, mi_prefix = fieldId @@ -58,8 +56,7 @@ noMethodInfo fieldId = BetterMethodInfo {mi_id = fieldId, instance PPrint BetterInfo where pPrint d i info = (text "methodNames") <> ppId d (mi_id info) <> equals <> braces - ( printMaybe d i "Result:" (mi_result info) <> - printMaybe d i "Ready:" (mi_ready info) <> + ( printMaybe d i "Ready:" (mi_ready info) <> printMaybe d i "Enable:" (mi_enable info) <> text "Prefix:" <> pPrint d i (mi_prefix info) ) @@ -93,10 +90,9 @@ fieldInfoToBetterInfo :: Flags -> SymTab -> (Id,Maybe FieldInfo) -> BetterInfo fieldInfoToBetterInfo flags symTab (fieldId, Nothing) = noMethodInfo fieldId fieldInfoToBetterInfo flags symTab (fieldId, Just fi) = BetterMethodInfo {mi_id = fieldId, - mi_result = maybe (id_to_vPort fieldId) (str_to_vPort) mres, mi_ready = maybe (id_to_vPort $ mkRdyId fieldId) str_to_vPort mrdy, mi_enable = maybe (id_to_vPort $ mkEnableId fieldId) str_to_vPort men, mi_prefix = maybe fieldId (setIdBaseString fieldId) mprefix } where prags = fi_pragmas fi - (mprefix,mres,mrdy,men,_,_,_) = getMethodPragmaInfo prags + (mprefix,_,mrdy,men,_,_,_) = getMethodPragmaInfo prags diff --git a/src/comp/LambdaCalc.hs b/src/comp/LambdaCalc.hs index 8a62f0fa8..bc55c1db7 100644 --- a/src/comp/LambdaCalc.hs +++ b/src/comp/LambdaCalc.hs @@ -915,6 +915,7 @@ convAType (ATString (Just width)) = stringType -- XXX ? convAType (ATReal) = realType convAType (ATArray sz t) = arrType sz (convAType t) convAType t | (t == mkATBool) = boolType +convAType (ATTuple ts) = internalError ("convAType: multi-output methods are not yet supported") convAType t@(ATAbstract {}) = internalError ("convAType: " ++ ppReadable t) -- ----- @@ -1026,7 +1027,11 @@ convStmt modId avmap (AStmtAction cset (ACall obj meth as)) = do Nothing -> -- no name because the value is unused -- but we still need to declare the correct type case (M.lookup (unQualId meth) meth_ty_map) of - Just t -> (convAType t, Nothing) + Just [t] -> (convAType t, Nothing) + Just [] -> (voidType, Nothing) + -- TODO: support multiple return values + Just ts -> error ("convStmt: multiple return values for method " ++ + ppReadable (obj, meth, ts)) Nothing -> (voidType, Nothing) -- we'll create new defs "act#", "guard#", and "state#" with a unique number @@ -1187,6 +1192,11 @@ convAExpr e@(AMethValue t obj meth) = -- these are handled by convStmts and are not expected here internalError("convAExpr: AMethValue: " ++ ppReadable e) +convAExpr (ATupleSel _ _ _) = + internalError "convAExpr: multi-output methods are not yet supported" +convAExpr (ATuple {}) = + internalError "convAExpr: multi-output methods are not yet supported" + convAExpr (ANoInlineFunCall t i (ANoInlineFun name _ _ _) as) = do let func_id = noinlineId i a_exprs <- mapM convAExpr as diff --git a/src/comp/LambdaCalcUtil.hs b/src/comp/LambdaCalcUtil.hs index 1ed84f5a5..01876d349 100644 --- a/src/comp/LambdaCalcUtil.hs +++ b/src/comp/LambdaCalcUtil.hs @@ -159,11 +159,11 @@ lookupDef defmap i = -- Digested AVInst info for each submodule instance -- * The module name -- * The numeric type arguments for polymorphic modules --- * A map from AV method names to their return value +-- * A map from AV method names to their return values -- -type InstMap = M.Map Id (String, [Integer], M.Map Id AType) +type InstMap = M.Map Id (String, [Integer], M.Map Id [AType]) -lookupMod :: InstMap -> Id -> (String, [Integer], M.Map Id AType) +lookupMod :: InstMap -> Id -> (String, [Integer], M.Map Id [AType]) lookupMod instmap obj = case (M.lookup obj instmap) of Nothing -> internalError ("lookupMod: " ++ ppReadable obj) @@ -1037,6 +1037,9 @@ updateAExprTypes _ (AMethCall t obj meth as) = do -- method return values are Bit type updateAExprTypes _ e@(AMethValue t obj meth) = return e +updateAExprTypes _ (ATupleSel _ _ _) = error "updateAExprTypes: multi-output methods not yet supported" +updateAExprTypes _ (ATuple _ _) = error "updateAExprTypes: multi-output methods not yet supported" + -- noinline function arguments and return values are Bit type updateAExprTypes _ (ANoInlineFunCall t i f as) = do as' <- mapM updateAExprTypes_Bits as @@ -1224,13 +1227,13 @@ inlineUndet = mapAExprs g -- ------------------------- -getSubModAVMethReturnTypes :: AVInst -> M.Map Id AType +getSubModAVMethReturnTypes :: AVInst -> M.Map Id [AType] getSubModAVMethReturnTypes avi = let meth_types = avi_meth_types avi vfis = vFields (avi_vmi avi) - mkPair vfi (_, Just _, Just ret_ty) = Just (vf_name vfi, ret_ty) + mkPair vfi (_, Just _, ret_tys) = Just (vf_name vfi, ret_tys) mkPair _ _ = Nothing pairs = catMaybes $ zipWith mkPair vfis meth_types diff --git a/src/comp/Parser/BSV/CVParser.lhs b/src/comp/Parser/BSV/CVParser.lhs index 1a3969117..311fa20f3 100644 --- a/src/comp/Parser/BSV/CVParser.lhs +++ b/src/comp/Parser/BSV/CVParser.lhs @@ -1462,7 +1462,9 @@ returns a single identifier formed by joining the components with underscores. > -- Bool indicates whether there's a separate Ready method for this one > pMethodVeriProt prefix = > do pos <- getPos +> -- TODO: Add syntax for specifiying multiple output ports > (optOPort, name) <- pMethodNameOptOPort "method output port or name" +> let oPorts = maybeToList optOPort > multi <- option 1 (pInBrackets pDecimal) > args <- (option [] (pInParens (pCommaSep pMethodArgVeriPort)) > "method arguments") @@ -1507,7 +1509,7 @@ returns a single identifier formed by joining the components with underscores. > Just (VeriPt p) -> > [(mkRdyId name, > V.Method (mkRdyId fullname) -> clk rst 0 [] (Just p) Nothing, +> clk rst 0 [] [p] Nothing, > False)] > Just _ -> internalError "pMethodVeriProt(4)" > return ((name, @@ -1516,7 +1518,7 @@ returns a single identifier formed by joining the components with underscores. > rst > multi > args -> optOPort +> oPorts > en, > not(null nullOrReady)) > : nullOrReady) @@ -4600,7 +4602,7 @@ a "module verilog": > let g (s,Nothing) = [(s,[])] > g (s,Just g) = [(s,[]),(g,[])] > f (Nothing, _) = [] -> f (Just i , cmg) = [V.Method i Nothing Nothing 1 (concat(map g cmg)) Nothing Nothing] +> f (Just i , cmg) = [V.Method i Nothing Nothing 1 (concat(map g cmg)) [] Nothing] > in concat . (map f) > pImperativeForeignModuleAt :: Position -> Attributes -> ImperativeFlags diff --git a/src/comp/Parser/BSV/CVParserImperative.lhs b/src/comp/Parser/BSV/CVParserImperative.lhs index 224ba6ad9..11b4682af 100644 --- a/src/comp/Parser/BSV/CVParserImperative.lhs +++ b/src/comp/Parser/BSV/CVParserImperative.lhs @@ -1473,9 +1473,9 @@ some of these restrictions could be lifted if we made the compiler more clever > Port (name, _) _ _ -> addInput pos name ioerrs > _ -> ioerrs > chkBVIPorts (ISBVI pos (BVI_method (_,inf@(Method {}),_))) ioerrs = ioerrs3 -> where ioerrs1 = case (vf_output inf) of -> Just (name, _) -> addOutputPort pos name ioerrs -> _ -> ioerrs +> where ioerrs1 = foldr (\(name, _) iers -> addOutputPort pos name iers) +> ioerrs +> (vf_outputs inf) > ioerrs2 = case (vf_enable inf) of > Just (name, _) -> addInput pos name ioerrs1 > _ -> ioerrs1 @@ -1704,13 +1704,13 @@ Extract each type of statement, making sure to preserve the order > CLValue si [CClause [] [] > (cVApply idPrimInoutUncast0 [(CSelect (CVar bviMname) i)])] [] > -- the following case will generate an error in chkBSVMethod below: -> mkBSVMethod (sn, Method n _ _ _ is Nothing Nothing, b) = -- ... mo me needsReady +> mkBSVMethod (sn, Method n _ _ _ is [] Nothing, b) = -- ... mo me needsReady > mkBasicDef (\ e -> e) n sn is b -> mkBSVMethod (sn, Method n _ _ _ is (Just _) Nothing, b) = -- ... mo me needsReady +> mkBSVMethod (sn, Method n _ _ _ is (_ : _) Nothing, b) = -- ... mo me needsReady > mkBasicDef (\ e -> cVApply idUnpack [e]) n sn is b -> mkBSVMethod (sn, Method n _ _ _ is Nothing (Just _), b) = -- ... mo me needsReady +> mkBSVMethod (sn, Method n _ _ _ is [] (Just _), b) = -- ... mo me needsReady > mkBasicDef (\ e -> cVApply idFromActionValue_ [e]) n sn is b -> mkBSVMethod (sn, Method n _ _ _ is (Just _) (Just _), b) = -- ... mo me needsReady +> mkBSVMethod (sn, Method n _ _ _ is (_ : _) (Just _), b) = -- ... mo me needsReady > mkBasicDef (\ e -> cVApply idFromActionValue_ [e]) n sn is b > mkBSVIfc (name,constr,ss) = @@ -1728,7 +1728,7 @@ Extract each type of statement, making sure to preserve the order > lastPos = getPosition (last stmts) > bviMname = idM lastPos -> chkBSVMethod (Method n _ _ _ _ Nothing Nothing) = -- mo me +> chkBSVMethod (Method n _ _ _ _ [] Nothing) = -- os me > cvtErr (getPosition n) (EForeignModOutputOrEnable (pvpReadable n)) > chkBSVMethod m = return () > theFamilies cs as fs = do diff --git a/src/comp/Parser/Classic/CParser.hs b/src/comp/Parser/Classic/CParser.hs index 97aa4e0da..fd7b585ac 100644 --- a/src/comp/Parser/Classic/CParser.hs +++ b/src/comp/Parser/Classic/CParser.hs @@ -148,7 +148,7 @@ pModule = l L_module `into` \ pos -> ||! literal (mkFString "const") .> VPconst ||! literal (mkFString "unused") .> VPunused ||! literal (mkFString "inhigh") .> VPinhigh - mkMethod i n vps mo me = Method i Nothing Nothing n vps Nothing Nothing + mkMethod i n vps mo me = Method i Nothing Nothing n vps [] Nothing pMStmt :: CParser CMStmt pMStmt = pModuleInterface diff --git a/src/comp/PreStrings.hs b/src/comp/PreStrings.hs index c4e2efbcf..e7a246220 100644 --- a/src/comp/PreStrings.hs +++ b/src/comp/PreStrings.hs @@ -206,6 +206,8 @@ fsMuxVal = mkFString "VAL" fsEnable = mkFString "EN_" fs_rdy = mkFString "RDY_" fs_rl = mkFString "RL_" +fs_arg = mkFString "ARG_" +fs_res = mkFString "RES_" fs_unnamed = mkFString "unnamed" s_unnamed = "unnamed" fs_T = mkFString "_T" diff --git a/src/comp/SAL.hs b/src/comp/SAL.hs index 52b7d8951..ad58492ac 100644 --- a/src/comp/SAL.hs +++ b/src/comp/SAL.hs @@ -503,6 +503,7 @@ boolToBitVar = SVar $ primCtx (SId "boolToBit") anyVar :: AType -> SExpr anyVar (ATBit width) = SVar $ bitCtx width (SId "undef") anyVar t | (t == mkATBool) = SVar $ primCtx (SId "undefBool") +anyVar (ATTuple ts) = internalError ("anyVar: multi-output methods are not yet supported") anyVar (ATString _) = SVar $ stringCtx (SId "undef") anyVar (ATReal) = SVar $ primCtx (SId "undefReal") anyVar (ATArray sz t) = arrBuild sz $ @@ -891,6 +892,7 @@ convARule defmap instmap mmap r@(ARule rId _ _ _ p as _ _) = convAIFace :: DefMap -> InstMap -> MethodOrderMap -> AIFace -> [SDefn] +-- TODO: support multiple method output ports convAIFace defmap instmap mmap (AIDef methId args _ p (ADef _ ret_t ret_e _) _ _) = let @@ -927,6 +929,7 @@ convAIFace defmap instmap mmap sLam (arg_infos ++ [(stateId, modType)]) $ body] +-- TODO: support multiple method output ports convAIFace defmap instmap mmap (AIActionValue args _ p methId rs (ADef _ def_t def_e _) _) = let @@ -1042,6 +1045,7 @@ convAType (ATString (Just width)) = stringType -- XXX ? convAType (ATReal) = realType convAType (ATArray sz t) = arrType sz (convAType t) convAType t | (t == mkATBool) = boolType +convAType (ATTuple ts) = internalError ("convAType: multi-output methods are not yet supported") convAType t@(ATAbstract {}) = internalError ("convAType: " ++ ppReadable t) -- ----- @@ -1156,7 +1160,11 @@ convStmt avmap (AStmtAction cset (ACall obj meth as)) = do Nothing -> -- no name because the value is unused -- but we still need to declare the correct type case (M.lookup (unQualId meth) meth_ty_map) of - Just t -> (convAType t, Nothing) + Just [t] -> (convAType t, Nothing) + Just [] -> (voidType, Nothing) + Just _ -> error ("convStmt: multiple return values for method " + ++ ppReadable meth ++ " on instance " + ++ ppReadable obj) Nothing -> (voidType, Nothing) -- we'll create new defs "act#" and "state#" with a unique number @@ -1292,6 +1300,9 @@ convAExpr e@(AMethValue t obj meth) = -- these are handled by convStmts and are not expected here internalError("convAExpr: AMethValue: " ++ ppReadable e) +convAExpr (ATupleSel _ _ _) = internalError "convAExpr: multi-output methods are not yet supported" +convAExpr (ATuple {}) = internalError "convAExpr: multi-output methods are not yet supported" + convAExpr (ANoInlineFunCall t _ (ANoInlineFun name _ _ _) as) = do let func_id = noinlineQId name a_exprs <- mapM convAExpr as diff --git a/src/comp/SignalNaming.hs b/src/comp/SignalNaming.hs index 1f2c73004..3d93e326c 100644 --- a/src/comp/SignalNaming.hs +++ b/src/comp/SignalNaming.hs @@ -10,6 +10,7 @@ import ErrorUtil(internalError) import PPrint import Id import PreIds +import Util(itos) -- remember to allow a few characters for __d3222 etc suffix signal_length_limit :: Int @@ -67,6 +68,12 @@ signalNameFromAExpr' (expr@AMethCall { }) = connectWith "_" (map signalNameFromAExpr' (ae_args expr)) signalNameFromAExpr' (expr@AMethValue { }) = ppString (ae_objid expr) ++ "_" ++ ppString (unQualId (ameth_id expr)) +signalNameFromAExpr' (expr@ATuple { }) = + "TUPLE_" ++ + connectWith "_" (map signalNameFromAExpr' (ae_elems expr)) +signalNameFromAExpr' (expr@ATupleSel { }) = + signalNameFromAExpr' (ae_exp expr) ++ + "_SEL_" ++ itos (ae_index expr) signalNameFromAExpr' (expr@ANoInlineFunCall { }) = -- use the identifier name (it is the user-known function name); -- the string in ANoInlineFun is the module name diff --git a/src/comp/SimCCBlock.hs b/src/comp/SimCCBlock.hs index 78ff83fe0..9619232e8 100644 --- a/src/comp/SimCCBlock.hs +++ b/src/comp/SimCCBlock.hs @@ -66,7 +66,7 @@ import Eval import ErrorUtil(internalError) import Data.Maybe -import Data.List(partition, intersperse, intercalate, nub, sortBy) +import Data.List(partition, intersperse, intercalate, nub, sortBy, genericDrop) import Data.List.Split(wordsBy) import Numeric(showHex) import Control.Monad(when) @@ -367,6 +367,7 @@ aTypeToCType :: AType -> (CCFragment -> CCFragment) aTypeToCType (ATBit size) = (`ofType` (bitsType size CTunsigned)) aTypeToCType (ATString _) = (`ofType` (classType "std::string")) aTypeToCType (ATReal) = (`ofType` doubleType) +aTypeToCType (ATTuple _) = userType "WideData" aTypeToCType (ATArray _ _) = internalError "Unexpected array" aTypeToCType (ATAbstract _ _) = internalError "Unexpected abstract type" @@ -522,6 +523,8 @@ adjustInstQuals id = -- check if an aexpr is just a var id, or other situation not to deal by wop hasWop :: AExpr -> Bool hasWop (APrim { aprim_prim = p }) = (p /= PrimIf) +hasWop (ATuple _ _) = True +hasWop (ATupleSel _ _ _) = True hasWop _ = False -- --------------------- @@ -638,8 +641,7 @@ getWDataTest = do return f isWideDef :: (AType, AId) -> Bool -isWideDef x@(ATBit sz, aid) | sz > 64 = True -isWideDef x = False +isWideDef (t, _) = wideDataType t mkUndetVal :: AType -> State ConvState CCExpr mkUndetVal ty = do @@ -874,6 +876,7 @@ mkPrimCall ret sz name args = mkArg expr = if (isConst expr) || (isStringType (aType expr)) || ((aType expr) == ATReal) || + (isTupleType (aType expr)) || ((aSize expr) > 64) then aExprToCExpr noRet expr else do cexpr <- aExprToCExpr noRet expr @@ -1068,6 +1071,16 @@ aExprToCExpr _ p@(APrim _ _ _ _) = aExprToCExpr _ (AMethCall _ id mid args) = do arg_list <- mapM (aExprToCExpr noRet) args return $ (aInstMethIdToC id mid) `cCall` arg_list +-- a tuple is laid out in wide data as a concatenation of its elements, +-- with the first element in the most-significant bits (Verilog {e1,...,en}) +aExprToCExpr ret e@(ATuple _ exprs) = + wideConcatPrim ret (aSize e) exprs +-- NB: idx is 1-based (see AConv and AState), so 'genericDrop idx' yields the +-- elements strictly below the selected one; sizeAfter is therefore the low bit +-- of element idx, and [aSize t + sizeAfter - 1 : sizeAfter] is its bit range. +aExprToCExpr ret (ATupleSel t e idx) = + wideExtractPrim ret (aSize t) e (aSize t + sizeAfter - 1) sizeAfter + where sizeAfter = sum $ map aSize $ genericDrop idx $ att_elem_types $ ae_type e aExprToCExpr _ e@(AMGate _ id clkid) = do gmap <- gets gate_map case (M.lookup e gmap) of @@ -1145,7 +1158,7 @@ simFnStmtToCStmt (SFSDef isPort (ty,aid) Nothing) = let w = aSize ty dst = if isPort then aPortIdToCLval aid else aDefIdToCLval aid typed_id = (aTypeToCType ty) dst - in if w > 64 -- for wide data, use (bits,false) constructor to avoid initialization penalty + in if w > 64 || isTupleType ty -- for wide data, use (bits,false) constructor to avoid initialization penalty then return $ construct typed_id [mkUInt32 w, mkBool False] else return $ decl typed_id simFnStmtToCStmt (SFSDef isPort (ty@(ATString (Just sz)),aid) (Just expr)) = @@ -1422,6 +1435,11 @@ mkPortInit ((ATBit n),_,vn) | n > 32 = [ assign (aPortIdToCLval (vName_to_id vn)) (mkUInt64 0) ] mkPortInit ((ATBit n),_,vn) = [ assign (aPortIdToCLval (vName_to_id vn)) (mkUInt32 0) ] +mkPortInit (t@(ATTuple _),_,vn) = + let p = aPortIdToC (vName_to_id vn) + in [ stmt $ p `cDot` "setSize" `cCall` [ mkUInt32 $ aSize t ] + , stmt $ p `cDot` "clear" `cCall` [] + ] mkPortInit p = internalError ("SimCCBlock.mkPortInit: " ++ ppReadable p) -- Create a call to the "set_reset_fn" for submodules with output resets @@ -1708,6 +1726,8 @@ mkCtorInit task_id_set (aty@(ATBit sz),aid) = let val = ASInt defaultAId aty (ilHex (aaaa sz)) in Just (aid,[val]) | otherwise = Nothing +mkCtorInit _ (aty@(ATTuple _),aid) = + Just (aid, [ aNat (aSize aty) ]) -- system tasks shouldn't be returning other types (like String), -- so no need to consult the task_id_set mkCtorInit _ _ = Nothing @@ -2142,11 +2162,11 @@ wideLocalDef (SFSDef _ (ty, aid) _) = if wideDataType ty else [] wideLocalDef _ = [] --- return True if this type is wider than 64 bits +-- return True if this type is represented as wide data +-- (i.e. it is larger than 64 bits, or it is a tuple) wideDataType :: AType -> Bool -wideDataType (ATBit sz) - | sz > 64 = True - | otherwise = False +wideDataType (ATBit sz) = sz > 64 +wideDataType (ATTuple _) = True wideDataType _ = False diff --git a/src/comp/SimCOpt.hs b/src/comp/SimCOpt.hs index c5d3d0afb..024c53d28 100644 --- a/src/comp/SimCOpt.hs +++ b/src/comp/SimCOpt.hs @@ -157,6 +157,7 @@ moveDefsOntoStack flags instmodmap (blocks,scheds) = let sizeOkToMove = case (M.lookup (sbid,aid) btype_map) of (Just ty) -> (ty == ATReal) || ((not (isStringType ty)) && + (not (isTupleType ty)) && ((aSize ty) <= 64)) Nothing -> False -- don't move AV task defs diff --git a/src/comp/SimExpand.hs b/src/comp/SimExpand.hs index a23885156..501fc3c25 100644 --- a/src/comp/SimExpand.hs +++ b/src/comp/SimExpand.hs @@ -1040,7 +1040,7 @@ combineCombSchedInfo use_map domain_id_map parent_abi parent_csi -- schedule graph and conflicts (even the methods not used by -- any parent rules), so we need to know which are the method Ids child_apkg = abmi_apkg child_abi - child_meth_set = S.fromList $ map aIfaceName (apkg_interface child_apkg) + child_meth_set = S.fromList $ map aif_name (apkg_interface child_apkg) -- combine each part of the CSI comb_sched_map = combineSchedMap inst parent_uses @@ -1669,7 +1669,7 @@ mkRdyMap abi = mkPair (AIClock {}) = [] mkPair (AIReset {}) = [] mkPair ifc = - let name = aIfaceName ifc + let name = aif_name ifc pred_e = aIfacePred ifc in if (isRdyId name) then [] -- Rdy methods don't have Rdy methods @@ -1974,6 +1974,8 @@ eDomain m e@(AMethCall _ i mi es) = mergeUses ([(i, unQualId mi)] : map (eDomain m) es) -- don't count the return value uses of actionvalue, only the action part eDomain m (AMethValue _ _ _) = [] +eDomain m (ATupleSel _ e _) = eDomain m e +eDomain m (ATuple _ es) = mergeUses $ map (eDomain m) es eDomain m (ANoInlineFunCall _ _ _ es) = mergeUses $ map (eDomain m) es eDomain m (AFunCall _ _ _ _ es) = mergeUses $ map (eDomain m) es eDomain _ e@(ASPort _ i) = [] @@ -2210,10 +2212,11 @@ makeMethodTemps apkg = (AIDef {}) -> (True,False) (AIActionValue {}) -> (False,True) otherwise -> (False,False) + v = aif_value aif in if is_def || is_av - then case process is_av (aif_value aif) (aif_name aif) seqNo of + then case process is_av v (aif_name aif) seqNo of (Just t@(ADef tid ty e props)) -> - let aid = adef_objid (aif_value aif) + let aid = adef_objid v -- unclear if propagating the props is correct new_def = (ADef aid ty (ASDef ty tid) props) aif' = aif { aif_value = new_def } diff --git a/src/comp/SimMakeCBlocks.hs b/src/comp/SimMakeCBlocks.hs index 9ce858b5e..153873dbb 100644 --- a/src/comp/SimMakeCBlocks.hs +++ b/src/comp/SimMakeCBlocks.hs @@ -119,7 +119,7 @@ simMakeCBlocks flags sim_system = -- methods on the top-level module top_methods = sp_interface top_pkg (top_ameths, top_vmeths) = partition aIfaceHasAction top_methods - top_vmeth_set = S.fromList $ concatMap aIfaceResId top_vmeths + top_vmeth_set = S.fromList $ concatMap aIfaceResIds top_vmeths top_ameth_set = S.fromList $ map aRuleName $ concatMap aIfaceRules top_ameths -- input clocks to the top-level module @@ -132,7 +132,7 @@ simMakeCBlocks flags sim_system = , let p_name = getModuleName p , let ms = sp_interface p , m <- ms - , let m_name = aIfaceName m + , let m_name = aif_name m , let m_rules = aIfaceRules m , let sub_actions = concatMap arule_actions m_rules , let sub_names = [ (o,m) | (ACall o m _) <- sub_actions ] @@ -208,6 +208,10 @@ getExprIds in_sched def_map known ((APrim _ _ _ args):es) = getExprIds in_sched def_map known (args ++ es) getExprIds in_sched def_map known ((AMethCall _ _ _ args):es) = getExprIds in_sched def_map known (args ++ es) +getExprIds in_sched def_map known ((ATuple _ elems):es) = + getExprIds in_sched def_map known (elems ++ es) +getExprIds in_sched def_map known ((ATupleSel _ e _):es) = + getExprIds in_sched def_map known (e:es) getExprIds in_sched def_map known ((ANoInlineFunCall _ _ _ args):es) = getExprIds in_sched def_map known (args ++ es) getExprIds in_sched def_map known ((AFunCall _ _ _ _ args):es) = @@ -323,7 +327,7 @@ onePackageToBlock flags name_map full_meth_map ss pkg = dms = [ M.singleton clk [(aid, fromJust m')] | m <- iface - , let aid = aIfaceName m + , let aid = aif_name m , let m' = cvtIFace modId (sp_pps pkg) def_map meth_map method_order_map reset_list m , isJust m' @@ -517,7 +521,7 @@ cvtIFace :: Id -> [PProp] -> DefMap -> MethMap -> MethodOrderMap -> [(ResetId, AReset)] -> AIFace -> Maybe SimCCFn cvtIFace modId pps def_map meth_map method_order_map reset_list m = - do let name = aIfaceName m + do let name = aif_name m inputs = aIfaceArgs m args = [ (t,i) | (i,t) <- inputs ] -- always_enabled methods need to forcibly check their ready signal @@ -527,7 +531,7 @@ cvtIFace modId pps def_map meth_map method_order_map reset_list m = if ((isAlwaysEn pps name) && (aIfaceHasAction m)) then -- we have to find the name of the port associated -- with the RDY method - let rdy_id = mkRdyId (aIfaceName m) + let rdy_id = mkRdyId (aif_name m) mport = do (_,_,Just (_,vn),_,_) <- M.lookup rdy_id meth_map return $ ASPort aTBool (vName_to_id vn) in case mport of @@ -1443,6 +1447,8 @@ tsortActionsAndDefs modId rId mmap ds acts reset_ids = -- function to substitute ASDef for AMethValue substAV (AMethValue ty obj meth) = ASDef ty (mkAVMethTmpId obj meth) + substAV (ATuple ts es) = ATuple ts (map substAV es) + substAV (ATupleSel t e i) = ATupleSel t (substAV e) i substAV (APrim i t o es) = (APrim i t o (map substAV es)) substAV (AMethCall t o m es) = (AMethCall t o m (map substAV es)) substAV (AFunCall t o f isC es) = (AFunCall t o f isC (map substAV es)) @@ -1620,6 +1626,10 @@ substGateReferences smap stmts = e { ae_args = map substInAExpr es } substInAExpr e@(AMethCall { ae_args = es }) = e { ae_args = map substInAExpr es } + substInAExpr e@(ATuple { ae_elems = es }) = + e { ae_elems = map substInAExpr es } + substInAExpr e@(ATupleSel { ae_exp = e1 }) = + e { ae_exp = substInAExpr e1 } substInAExpr e@(ANoInlineFunCall { ae_args = es }) = e { ae_args = map substInAExpr es } substInAExpr e@(AFunCall { ae_args = es }) = diff --git a/src/comp/SimPackage.hs b/src/comp/SimPackage.hs index f17e688d8..e8626a520 100644 --- a/src/comp/SimPackage.hs +++ b/src/comp/SimPackage.hs @@ -375,7 +375,7 @@ getSimPackageInputs spkg = getPortInfo :: [PProp] -> AIFace -> Maybe (AId, (Maybe VName, [(AType,AId,VName)], Maybe (AType,VName), Bool, [AId])) getPortInfo pps aif = - let name = aIfaceName aif + let name = aif_name aif vfi = aif_fieldinfo aif en = do e <- vf_enable vfi -- always enabled implies enabled when ready @@ -385,9 +385,14 @@ getPortInfo pps aif = ps = map fst (vf_inputs vfi) ins = [ (t,i,vn) | ((i,t),vn) <- zip args ps ] rt = aIfaceResType aif - ret = case (vf_output vfi) of - (Just (vn,_)) -> Just (rt,vn) - Nothing -> Nothing + -- A value method has at most one result. In Bluesim that whole value + -- is returned directly, so when the Verilog output is split across + -- several ports (vf_outputs) we keep just the first port, which carries + -- the entire value; the remaining ports are Verilog-only slicing + -- metadata and are not needed here. + ret = case vf_outputs vfi of + ((vn,_) : _) -> Just (rt, vn) + [] -> Nothing isAction = case aif of (AIAction {}) -> True (AIActionValue {}) -> True diff --git a/src/comp/SimPackageOpt.hs b/src/comp/SimPackageOpt.hs index 82f966c88..cb00c867a 100644 --- a/src/comp/SimPackageOpt.hs +++ b/src/comp/SimPackageOpt.hs @@ -138,6 +138,7 @@ inlineDefs pkg = isNotOk d | isUnsized (adef_type d) = True | (aSize d > 64) = True + | isTupleType (adef_type d) = True | isTaskOrForeignFunc d = True | isCase d = True | otherwise = False @@ -230,6 +231,10 @@ optimizeConcats pkg = -- recurse for other optConcat (APrim i t o as) = APrim i t o (map optConcat as) optConcat (AMethCall t o m as) = AMethCall t o m (map optConcat as) + -- XXX There is maybe an opportunity to optimize tuple construction here, + -- since that basically turns into a concat as well. + optConcat (ATuple t as) = ATuple t (map optConcat as) + optConcat (ATupleSel t e idx) = ATupleSel t (optConcat e) idx optConcat (AFunCall t i f isC as) = AFunCall t i f isC (map optConcat as) optConcat e = e in mapAExprs optConcat pkg @@ -316,9 +321,15 @@ convertASAny errh flags apkg = do cvtASAnyExpr (APrim aid ty op args) = do args' <- mapM cvtASAnyExpr args return $ APrim aid ty op args' - cvtASAnyExpr (AMethCall ty aid mid args) = + cvtASAnyExpr (AMethCall ty aid mid args) = do args' <- mapM cvtASAnyExpr args return $ AMethCall ty aid mid args' + cvtASAnyExpr (ATuple ty elems) = + do elems' <- mapM cvtASAnyExpr elems + return $ ATuple ty elems' + cvtASAnyExpr (ATupleSel ty exp idx) = + do exp' <- cvtASAnyExpr exp + return $ ATupleSel ty exp' idx cvtASAnyExpr (ANoInlineFunCall ty aid fun args) = do args' <- mapM cvtASAnyExpr args return $ ANoInlineFunCall ty aid fun args' diff --git a/src/comp/SystemCWrapper.hs b/src/comp/SystemCWrapper.hs index b7fd88344..75d694b05 100644 --- a/src/comp/SystemCWrapper.hs +++ b/src/comp/SystemCWrapper.hs @@ -8,7 +8,7 @@ import Pragma(isAlwaysRdy, isEnWhenRdy) import FileNameUtil(mkCxxName, mkHName) import ASyntax(AAbstractInput(..), AIFace(..), AExpr(..), AClock(..), - aIfaceArgs, aIfaceName, aIfaceProps) + aIfaceArgs, aif_name, aIfaceProps) import ASyntaxUtil import VModInfo(vName_to_id, VPathInfo(..)) import Wires @@ -38,7 +38,7 @@ checkSystemCIfc errh flags sim_system = do isBad m@(AIActionValue {}) = -- we allow ActionValue methods only -- if they have no arguments and no enable not ((null (aIfaceArgs m)) && - (isEnWhenRdy pps (aIfaceName m))) + (isEnWhenRdy pps (aif_name m))) isBad _ = False bad_methods = [ getIdBaseString (aif_name m) | m <- sp_interface top_pkg @@ -157,7 +157,7 @@ wrapSystemC flags sim_system = do ] -- utility functions for grouping methods by domain - meth_domains = M.fromList [ (aIfaceName aif, dom) + meth_domains = M.fromList [ (aif_name aif, dom) | aif <- (sp_interface top_pkg) , let wp = aIfaceProps aif , let dom = wpClockDomain wp diff --git a/src/comp/TCheck.hs b/src/comp/TCheck.hs index e6d0cd09c..20c627f23 100644 --- a/src/comp/TCheck.hs +++ b/src/comp/TCheck.hs @@ -710,43 +710,42 @@ tiExpr as td exp@(CmoduleVerilog name ui clks rsts args fields sch ps) = do -- matches the types. let -- XXX These errors should give more info - chkResType :: [VPort] -> Maybe VPort -> Maybe VPort -> Type -> - TI ([VPort], Maybe VPort, Maybe VPort) - chkResType ps me@(Just _) mo@Nothing t = - if (isActionWithoutValue t) then return (ps, me, mo) + chkResType :: [VPort] -> Maybe VPort -> [VPort] -> Type -> + TI ([VPort], Maybe VPort, [VPort]) + chkResType ps me@(Just _) [] t = + if (isActionWithoutValue t) then return (ps, me, []) else if (isActionWithValue t) then errMissingValue "ActionValue" t - else if (isBit t) + else if (isBitTuple t) then errUnexpectedEnable "value" t else errBadResType t - chkResType ps me@Nothing mo@(Just _) t = - if (isBit t) then return (ps, me, mo) + chkResType ps me@Nothing outs@(_:_) t = + if (isBitTuple t) then return (ps, me, outs) else if (isActionWithValue t) then errMissingEnable "ActionValue" t else if (isActionWithoutValue t) then errUnexpectedValue "Action" t else errBadResType t - chkResType ps me@(Just _) mo@(Just _) t = - if (isActionWithValue t) then return (ps, me, mo) + chkResType ps me@(Just _) outs@(_:_) t = + if (isActionWithValue t) then return (ps, me, outs) else if (isActionWithoutValue t) then errUnexpectedValue "Action" t - else if (isBit t) + else if (isBitTuple t) then errUnexpectedEnable "value" t else errBadResType t - chkResType ps Nothing Nothing t = do - -- must have more than 0 ports - when (null ps) $ - err (getPosition f, - EForeignModTooFewPorts (pfpString f)) + chkResType ps Nothing [] t = do -- update the Classic fieldinfo to BSV format let inputs = initOrErr "chkResType" ps let final_port = lastOrErr "chkResType" ps -- XXX kill PrimAction once imports in Prelude are converted over if (isActionWithoutValue t) || (isPrimAction t) - then return (inputs, Just final_port, Nothing) - else if (isBit t) - then return (inputs, Nothing, Just final_port) - else errBadResType t + then return (inputs, Just final_port, []) + else if (isBit t) + -- The Classic fieldinfo format can only have a single result port. + then return (inputs, Nothing, [final_port]) + else if (t == tPrimUnit) + then return (ps, Nothing, []) + else errBadResType t errBadResType t = err (getPosition f, @@ -808,9 +807,9 @@ tiExpr as td exp@(CmoduleVerilog name ui clks rsts args fields sch ps) = do else if (null argTypes) then return vfi else errInoutHasArgs - Method { vf_inputs = inputs, vf_enable = me, vf_output = mo } -> + Method { vf_inputs = inputs, vf_enable = me, vf_outputs = outputs } -> do -- updates inputs, me and mo when processing Classic format - (inputs', me', mo') <- chkResType inputs me mo resType + (inputs', me', outputs') <- chkResType inputs me outputs resType -- check if any actions are SB with themselves when (((isActionWithValue resType) || (isActionWithoutValue resType) || @@ -818,7 +817,7 @@ tiExpr as td exp@(CmoduleVerilog name ui clks rsts args fields sch ps) = do (f `elem` self_sbs)) (errActionSelfSB f) chkArgs inputs' argTypes - return (vfi { vf_inputs = inputs', vf_enable = me', vf_output = mo' }) + return (vfi { vf_inputs = inputs', vf_enable = me', vf_outputs = outputs' }) -- paramResults <- mapM tiParam es qsses <- mapM tiArg args -- let (pses, tys) = unzip paramResults @@ -902,7 +901,7 @@ tiExpr as td exp@(CForeignFuncC link_id wrap_cqt) = do when (isTypeString av_arg) $ err (getPosition pos, EForeignFuncStringRes) (ctxs, prim_sz) <- findBitSize av_arg - let prim_t = TAp tActionValue_ prim_sz + let prim_t = TAp tActionValue_ $ TAp tBit prim_sz return (ctxs, prim_t, cexpr) -- anything else must be bitifiable else do let cexpr = \e -> cVApply idUnpack [e] @@ -1524,7 +1523,7 @@ finishSWriteAV as td v f es paramResults eq_ps = let (pss, es') = unzip pses -- v <- newTVar "XXX" KNum f - let tav = TAp tActionValue_ v + let tav = TAp tActionValue_ (TAp tBit v) let taskty = foldr fn tav tys -- XXX: quantifying in IConv instead so free type vars are caught correctly @@ -1586,7 +1585,7 @@ taskCheckFOpen as td f [filen] = (vp,filentc) <- tiExpr as tString filen -- let avfile = (TAp (tActionValueAt (getPosition f)) tFile) - tav32 = TAp (tActionValue_At (getPosition f)) t32 + tav32 = TAp (tActionValue_At (getPosition f)) bit32 fty = tString `fn` tav32 applied = (CTaskApplyT f fty [filentc]) let t = cVApply (setIdPosition (getPosition f) idFromActionValue_) [applied] @@ -1602,7 +1601,7 @@ taskCheckFOpen as td f [filen,mode] = -- -- let avfile = (TAp (tActionValueAt (getPosition f)) tFile) - tav32 = TAp (tActionValue_At (getPosition f)) t32 + tav32 = TAp (tActionValue_At (getPosition f)) bit32 fty = tString `fn` tString `fn` tav32 applied = (CTaskApplyT f fty [filentc,modetc]) let t = cVApply (setIdPosition (getPosition f) idFromActionValue_) [applied] diff --git a/src/comp/TopUtils.hs b/src/comp/TopUtils.hs index 0dcfe23b6..aa271cd9d 100644 --- a/src/comp/TopUtils.hs +++ b/src/comp/TopUtils.hs @@ -31,7 +31,7 @@ import IdPrint import ISyntax(IPackage(..), IModule(..), IStateVar(..), IRules(..)) import ASyntax(APackage(..), ASPackage(..), ARule(..), - aIfaceName) + aif_name) import SystemVerilogTokens(SV_Token(..)) import Version(bluespec, bscVersionStr) @@ -276,7 +276,7 @@ instance Stats APackage where (showLen (apkg_rules apkg) "rules" <> if v then text "" <+>pPrint PDReadable 0 [ i | ARule { arule_id = i } <- apkg_rules apkg ] else text "") $+$ (showLen (apkg_interface apkg) "interface methods" <> - if v then text "" <+> pPrint PDReadable 0 (map aIfaceName (apkg_interface apkg)) else text "") + if v then text "" <+> pPrint PDReadable 0 (map aif_name (apkg_interface apkg)) else text "") )) instance Stats ASPackage where diff --git a/src/comp/Type.hs b/src/comp/Type.hs index d526e6c75..70167ce01 100644 --- a/src/comp/Type.hs +++ b/src/comp/Type.hs @@ -60,13 +60,13 @@ tPrimPair = TCon (TyCon idPrimPair (Just (Kfun KStar (Kfun KStar KStar))) (TIstr tAction, tActionValue, tActionValue_, tAction_:: Type tAction = TCon (TyCon idAction (Just KStar) (TItype 0 (TAp tActionValue tPrimUnit))) tActionValue = TCon (TyCon idActionValue (Just (Kfun KStar KStar)) (TIstruct SStruct [id__value, id__action])) -tActionValue_ = TCon (TyCon idActionValue_ (Just (Kfun KNum KStar)) (TIstruct SStruct [id__value, id__action])) -tAction_ = TAp tActionValue_ (tOfSize 0 noPosition) +tActionValue_ = TCon (TyCon idActionValue_ (Just (Kfun KStar KStar)) (TIstruct SStruct [id__value, id__action])) +tAction_ = TAp tActionValue_ tPrimUnit tActionAt, tActionValueAt, tActionValue_At :: Position -> Type tActionAt pos = TCon (TyCon (idActionAt pos) (Just KStar) (TItype 0 (TAp (tActionValueAt pos) (tPrimUnitAt pos)))) tActionValueAt pos = TCon (TyCon (idActionValueAt pos) (Just (Kfun KStar KStar)) (TIstruct SStruct [id__value_at pos, id__action_at pos])) -tActionValue_At pos = TCon (TyCon (idActionValue_At pos) (Just (Kfun KNum KStar)) (TIstruct SStruct [id__value_at pos, id__action_at pos])) +tActionValue_At pos = TCon (TyCon (idActionValue_At pos) (Just (Kfun KStar KStar)) (TIstruct SStruct [id__value_at pos, id__action_at pos])) tPrimAction, tRules :: Type tPrimAction = TCon (TyCon idPrimAction (Just KStar) TIabstract) @@ -162,13 +162,21 @@ getAVType :: Type -> Type getAVType (TAp av t) | av == tActionValue = t getAVType t = internalError("getAVType not ActionValue: " ++ ppReadable t) +-- Note that we consider ActionValue_ (Bit 0) to be an action without a value, +-- as this is still created by foreign verilog module imports. +-- XXX should rework this to just yield ActionValue_ () for empty types. isActionWithoutValue :: Type -> Bool -isActionWithoutValue (TAp av (TCon (TyNum 0 _))) = av == tActionValue_ +isActionWithoutValue (TAp av (TAp (TCon (TyCon i _ _)) (TCon (TyNum 0 _)))) = + av == tActionValue_ && i == idBit +isActionWithoutValue (TAp av (TCon (TyCon i _ _))) = + av == tActionValue_ && i == idPrimUnit isActionWithoutValue _ = False isActionWithValue :: Type -> Bool -isActionWithValue (TAp av (TCon (TyNum n _))) = (av == tActionValue_) && (n > 0) isActionWithValue (TAp av (TVar _)) = av == tActionValue_ +isActionWithValue (TAp av (TAp (TCon (TyCon i _ _)) (TCon (TyNum 0 _)))) + | av == tActionValue_ && i == idBit = False +isActionWithValue (TAp av t) = (av == tActionValue_) && isBitTuple t isActionWithValue _ = False isClock, isReset, isInout, isInout_ :: Type -> Bool @@ -198,4 +206,9 @@ isChar t = t == tChar isReal t = t == tReal isFmt t = t == tFmt +isBitTuple :: Type -> Bool +isBitTuple (TAp (TAp (TCon (TyCon i _ _)) t1) t2) | i == idPrimPair = + isBit t1 && isBitTuple t2 +isBitTuple t = isBit t + -- ------------------------- diff --git a/src/comp/VIOProps.hs b/src/comp/VIOProps.hs index f9c88fdc5..8180646c3 100644 --- a/src/comp/VIOProps.hs +++ b/src/comp/VIOProps.hs @@ -10,7 +10,7 @@ import Flags import PPrint import ErrorUtil(internalError) import Id -import PreIds(idPrimAction, idInout_) +import PreIds(idPrimAction, idInout_, idPrimUnit) import VModInfo(vArgs, vFields, VName(..), VeriPortProp(..), VArgInfo(..), VFieldInfo(..), VPort) import Prim @@ -151,9 +151,13 @@ getIOProps flags ppp@(ASPackage _ _ _ os is ios vs _ ds io_ds fs _ _ _) = -- create the method name map let nmap = M.fromList $ createVerilogNameMapForAVInst flags v, - -- for each method that has an output port - vfi@(Method { vf_output = Just (vname,pprops) }) - <- vFields (avi_vmi v), + -- for each method (not clocks or resets) + vfi@(Method {}) <- vFields (avi_vmi v), + -- for each method output port + (methOutPart, (vname, pprops)) + <- zip (map MethodResult (methResultNums (vf_outputs vfi))) + (vf_outputs vfi), + -- for each port copy ino <- if (vf_mult vfi > 1) then map Just [0 .. vf_mult vfi] @@ -162,7 +166,7 @@ getIOProps flags ppp@(ASPackage _ _ _ os is ios vs _ ds io_ds fs _ _ _) = let meth_id = mkMethId (avi_vname v) (vf_name vfi) ino - MethodResult, + methOutPart, -- convert to Verilog signal name let veri_id = xLateIdUsingFStringMap nmap meth_id ] @@ -194,7 +198,8 @@ getIOProps flags ppp@(ASPackage _ _ _ os is ios vs _ ds io_ds fs _ _ _) = -- return empty-list here; but the internal check -- is nice to have (if it's not too expensive). internalError ("getOVProp: could not find method " ++ - ppString i) + ppString i ++ " in wireMap_out:\n" ++ + ppReadable wireMap_out) -- ---------- -- construct the VeriPortProp list for an input @@ -400,5 +405,6 @@ size :: AType -> Integer size (ATBit n) = n size (ATAbstract a _) | a == idPrimAction = 1 size (ATAbstract a [n]) | a == idInout_ = n +size (ATAbstract a _) | a == idPrimUnit = 0 size (ATString _ ) = 0 size t = internalError ("getIOProps.size: " ++ show t) diff --git a/src/comp/VModInfo.hs b/src/comp/VModInfo.hs index 6964602a1..ab96eb1b9 100644 --- a/src/comp/VModInfo.hs +++ b/src/comp/VModInfo.hs @@ -23,7 +23,7 @@ module VModInfo(VModInfo, mkVModInfo, getIfcIdPosition, str_to_vPort,getVPortString, mkNamedEnable, - mkNamedOutput, + mkNamedOutputs, mkNamedReady, mkNamedInout, extractNames @@ -274,7 +274,7 @@ data VFieldInfo = Method { vf_name :: Id, -- method name -- optional because the method may be independent of a reset signal vf_mult :: Integer, -- multiplicity vf_inputs :: [VPort], - vf_output :: Maybe VPort, + vf_outputs:: [VPort], vf_enable :: Maybe VPort } | Clock { vf_name :: Id } -- output clock name -- connection information is in the ClockInfo @@ -300,11 +300,12 @@ instance NFData VFieldInfo where instance PPrint VFieldInfo where pPrint d p (Method n c r m i o e) = - text "method " <> pout o <> pPrint d p n <> pmult m <> + text "method " <> pouts o <> pPrint d p n <> pmult m <> pins i <> pena e <+> ppMClk d c <+> ppMRst d r <> text ";" - where pout Nothing = empty - pout (Just po) = pPrint d p po + where pouts [] = empty + pouts [po] = pPrint d p po + pouts o = text "(" <> sepList (map (pPrint d p) o) (text ",") <> text ")" pmult 1 = empty pmult n = text "[" <> pPrint d p n <> text "]" pins [] = empty @@ -685,17 +686,16 @@ mkNamedEnable vfi = if (newStr == "") then baseid else setIdBaseString baseid ne where baseid = mkEnableId (vf_name vfi) newStr = maybe "" getVPortString (vf_enable vfi) -mkNamedOutput :: VFieldInfo -> Id -mkNamedOutput vfi = if (newStr == "") then baseid else setIdBaseString baseid newStr +mkNamedOutputs :: VFieldInfo -> [Id] +mkNamedOutputs vfi = map (setIdBaseString baseid) newStrs where baseid = (vf_name vfi) - newStr = maybe "" getVPortString (vf_output vfi) + newStrs = map getVPortString (vf_outputs vfi) -- VFieldInfo does not have a ready field, so we just use the default construction for the ready signal. -- in aState we merge method and RDY_method to do the right thing. mkNamedReady :: VFieldInfo -> Id mkNamedReady vfi = baseid -- if (newStr == "") then baseid else setIdBaseString baseid newStr where baseid = mkRdyId (vf_name vfi) - -- newStr = maybe "" getVPortString (vf_output vfi) mkNamedInout :: VFieldInfo -> Id mkNamedInout vfi = setIdBaseString baseid newStr @@ -705,8 +705,8 @@ mkNamedInout vfi = setIdBaseString baseid newStr --------------------------- Name extraction from VFieldInfo -- extract possible port Ids from a VField Info -- return value is result, ready, enable -extractNames :: VFieldInfo -> (Id, Id, Id ) +extractNames :: VFieldInfo -> ([Id], Id, Id ) extractNames vfi = (result, ready, enable) - where result = mkNamedOutput vfi + where result = mkNamedOutputs vfi ready = mkNamedReady vfi enable = mkNamedEnable vfi diff --git a/src/comp/bluetcl.hs b/src/comp/bluetcl.hs index b457ca703..93f745e55 100644 --- a/src/comp/bluetcl.hs +++ b/src/comp/bluetcl.hs @@ -1118,7 +1118,7 @@ tclModule ["methods",modname] = do let apkg = abemi_apkg abmi pps = abemi_pps abmi ifc = apkg_interface apkg - ifc_map = [ (aIfaceName aif, rawIfcFieldFromAIFace pps aif) + ifc_map = [ (aif_name aif, rawIfcFieldFromAIFace pps aif) | aif <- ifc ] let tifc = getModuleIfc abmi fs <- getIfcHierarchy Nothing ifc_map tifc @@ -1639,7 +1639,7 @@ tclRule ["full",modname,rule] = Nothing -> Nothing Just (ARule i ps _ _ rPred _ _ _) -> Just (ps, getPosition i, aAnds [ifPred, rPred]) - cvtIfc (AIDef _ _ _ ifPred (ADef dId _ _ _) _ _) = + cvtIfc (AIDef dId _ _ ifPred _ _ _) = if (dId == rId) then Just ([], getPosition dId, ifPred) else Nothing @@ -1960,7 +1960,7 @@ instance ExpandInfoHelper BModView where -- flattened ifc names let ifc_names = map pfpString $ filter (not . isRdyId) $ - map (aIfaceName) (apkg_interface apkg) + map (aif_name) (apkg_interface apkg) -- rules let rule_names = map (pfpString . arule_id) (apkg_rules apkg) -- schedule @@ -3283,7 +3283,7 @@ data RawIfcField = (Maybe Id) (Maybe Id) -- associated clk and rst [(Maybe Id, AType)] -- arguments [VPort] -- argument ports - (Maybe (VPort, AType)) -- return value + [(VPort, AType)] -- return values (Maybe VPort) -- enable signal -- Note: no ready signal at this stage | RawClock Id @@ -3301,26 +3301,32 @@ rawIfcFieldName (RawInout i _ _ _ _) = i rawIfcFieldFromAIFace :: [PProp] -> AIFace -> RawIfcField rawIfcFieldFromAIFace _ (AIDef i args _ _ def - (Method _ clk rst mult ins mo@(Just out) Nothing) _) = - let -- include the type in the "mo" - mo' = Just (out, adef_type def) - in RawMethod i mult clk rst (mapFst Just args) ins mo' Nothing + (Method _ clk rst mult ins outs Nothing) _) = + let -- include the type in the "outs" + outs' = zip outs $ + case adef_type def of + ATTuple ts -> ts + t -> [t] + in RawMethod i mult clk rst (mapFst Just args) ins outs' Nothing rawIfcFieldFromAIFace pps (AIAction args _ _ i _ - (Method _ clk rst mult ins Nothing me@(Just _))) = + (Method _ clk rst mult ins [] me@(Just _))) = let -- filter out inhigh enable ports -- XXX is there a better way to do this? me' = if (isAlwaysEn pps i) then Nothing else me - in RawMethod i mult clk rst (mapFst Just args) ins Nothing me' + in RawMethod i mult clk rst (mapFst Just args) ins [] me' rawIfcFieldFromAIFace pps (AIActionValue args _ _ i _ def - (Method _ clk rst mult ins mo@(Just out) me@(Just _))) = + (Method _ clk rst mult ins outs me@(Just _))) = let -- filter out inhigh enable ports -- XXX is there a better way to do this? me' = if (isAlwaysEn pps i) then Nothing else me - -- include the type in the "mo" - mo' = Just (out, adef_type def) - in RawMethod i mult clk rst (mapFst Just args) ins mo' me' + -- include the type in the "outs" + outs' = zip outs $ + case adef_type def of + ATTuple ts -> ts + t -> [t] + in RawMethod i mult clk rst (mapFst Just args) ins outs' me' rawIfcFieldFromAIFace _ (AIClock i _ (Clock _)) = RawClock i rawIfcFieldFromAIFace _ (AIReset i _ (Reset _)) = RawReset i rawIfcFieldFromAIFace _ (AIInout i (AInout e) (Inout _ vn mclk mrst)) = @@ -3329,23 +3335,20 @@ rawIfcFieldFromAIFace _ aif = internalError ("rawIfcFieldFromAIFace: unexpected AIFace combo: " ++ ppReadable aif) -rawIfcFieldFromAVInst :: ([AType], Maybe AType, Maybe AType) -> +rawIfcFieldFromAVInst :: ([AType], Maybe AType, [AType]) -> VFieldInfo -> RawIfcField -rawIfcFieldFromAVInst (arg_tys,_,mo_type) (Method i clk rst mult ins mo me) = +rawIfcFieldFromAVInst (arg_tys,_,out_tys) (Method i clk rst mult ins outs me) = let -- XXX AVInst doesn't record argument names args = zip (repeat Nothing) arg_tys - -- add the return bit-type to the mo - mo' = case (mo, mo_type) of - (Just o, Just o_type) -> Just (o, o_type) - (Nothing, Nothing) -> Nothing - _ -> internalError ("rawIfcFieldFromAVInst: unexpected mo: " ++ - ppReadable (mo, mo_type)) - in RawMethod i mult clk rst args ins mo' me + -- add the return bit-type to the outs + outs' = zip outs out_tys + in RawMethod i mult clk rst args ins outs' me rawIfcFieldFromAVInst _ (Clock i) = RawClock i rawIfcFieldFromAVInst _ (Reset i) = RawReset i -rawIfcFieldFromAVInst (_,_,mt) (Inout i vn mclk mrst) = - let t = fromJustOrErr ("getIfc: no type for Inout") mt - in RawInout i t vn mclk mrst +rawIfcFieldFromAVInst (_,_,[t]) (Inout i vn mclk mrst) = RawInout i t vn mclk mrst +rawIfcFieldFromAVInst _ vfi = + internalError ("rawIfcFieldFromAVInst: unexpected VFieldInfo: " ++ + ppReadable vfi) -- --------------- @@ -3495,7 +3498,7 @@ data PortIfcInfo = PIMethod Id Id (Maybe Id) (Maybe Id) -- associated clk and rst [(Maybe Id, AType, (String, IType))] -- arguments - (Maybe (String, AType, IType)) -- return value + [(String, AType, IType)] -- return values (Maybe (String, IType)) -- enable signal (Maybe (String, IType)) -- ready signal | PIClock Id Id (Maybe ((String, IType), Maybe (String, IType))) @@ -3528,7 +3531,7 @@ getModPortInfo apkg pps tifc = do -- interface hierarchy let -- map from flattened ifc name to its raw info - ifc_map = [ (aIfaceName aif, rawIfcFieldFromAIFace pps aif) + ifc_map = [ (aif_name aif, rawIfcFieldFromAIFace pps aif) | aif <- ifc ] ifc_hier <- getIfcHierarchy Nothing ifc_map tifc @@ -3642,8 +3645,8 @@ getSubmodPortInfo mtifc avi = do concatMap getIfcHier ifc_hier) adjustPrimFields :: Maybe Type -> AVInst -> - ([VFieldInfo], [([AType], Maybe AType, Maybe AType)]) -> - ([VFieldInfo], [([AType], Maybe AType, Maybe AType)]) + ([VFieldInfo], [([AType], Maybe AType, [AType])]) -> + ([VFieldInfo], [([AType], Maybe AType, [AType])]) adjustPrimFields Nothing _ vfts = vfts adjustPrimFields (Just tifc) avi vfts = if (leftCon tifc == Just idReg) @@ -3687,8 +3690,8 @@ adjustPrimFields (Just tifc) avi vfts = else vfts -- This is a no-op but it does add some error checking -adjustRegAlignedFields :: ([VFieldInfo], [([AType], Maybe AType, Maybe AType)]) -> - ([VFieldInfo], [([AType], Maybe AType, Maybe AType)]) +adjustRegAlignedFields :: ([VFieldInfo], [([AType], Maybe AType, [AType])]) -> + ([VFieldInfo], [([AType], Maybe AType, [AType])]) adjustRegAlignedFields (vfi, fts) = let renameField vf@(Method {vf_name = i }) | (i `qualEq` id_read noPosition) = vf @@ -3698,8 +3701,8 @@ adjustRegAlignedFields (vfi, fts) = in (map renameField vfi, fts) -adjustRegFields :: ([VFieldInfo], [([AType], Maybe AType, Maybe AType)]) -> - ([VFieldInfo], [([AType], Maybe AType, Maybe AType)]) +adjustRegFields :: ([VFieldInfo], [([AType], Maybe AType, [AType])]) -> + ([VFieldInfo], [([AType], Maybe AType, [AType])]) adjustRegFields (vfi, fts) = let renameField vf@(Method {vf_name = i }) | (i `qualEq` idPreludeRead) = vf { vf_name = id_read noPosition } @@ -3708,8 +3711,8 @@ adjustRegFields (vfi, fts) = ppReadable (vf_name vf)) in (map renameField vfi, fts) -adjustFIFOFields :: ([VFieldInfo], [([AType], Maybe AType, Maybe AType)]) -> - ([VFieldInfo], [([AType], Maybe AType, Maybe AType)]) +adjustFIFOFields :: ([VFieldInfo], [([AType], Maybe AType, [AType])]) -> + ([VFieldInfo], [([AType], Maybe AType, [AType])]) adjustFIFOFields (vfi, fts) = let enq_rdy = mkRdyId idEnq deq_rdy = mkRdyId idDeq @@ -3721,8 +3724,8 @@ adjustFIFOFields (vfi, fts) = renameField vft = [vft] in unzip $ concatMap renameField $ zip vfi fts -adjustFIFO0Fields :: ([VFieldInfo], [([AType], Maybe AType, Maybe AType)]) -> - ([VFieldInfo], [([AType], Maybe AType, Maybe AType)]) +adjustFIFO0Fields :: ([VFieldInfo], [([AType], Maybe AType, [AType])]) -> + ([VFieldInfo], [([AType], Maybe AType, [AType])]) adjustFIFO0Fields (vfi, fts) = let (clk, rst) = case vfi of @@ -3730,12 +3733,12 @@ adjustFIFO0Fields (vfi, fts) = (_:d@(Method _ c r _ _ _ _):_) -> (c, r) _ -> internalError ("adjustFIFO0Fields: vfi = " ++ ppReadable vfi) - first_vfi = Method idFirst clk rst 1 [] Nothing Nothing - first_fts = ([], Nothing, Nothing) + first_vfi = Method idFirst clk rst 1 [] [] Nothing + first_fts = ([], Nothing, []) in (first_vfi:vfi, first_fts:fts) -adjustSyncRegFields :: ([VFieldInfo], [([AType], Maybe AType, Maybe AType)]) -> - ([VFieldInfo], [([AType], Maybe AType, Maybe AType)]) +adjustSyncRegFields :: ([VFieldInfo], [([AType], Maybe AType, [AType])]) -> + ([VFieldInfo], [([AType], Maybe AType, [AType])]) adjustSyncRegFields (vfi, fts) = let renameField vf@(Method {vf_name = i }) -- XXX these are qualified Clock, not Prelude @@ -3747,28 +3750,28 @@ adjustSyncRegFields (vfi, fts) = ppReadable (vf_name vf)) in (map renameField vfi, fts) -adjustRWireFields :: ([VFieldInfo], [([AType], Maybe AType, Maybe AType)]) -> - ([VFieldInfo], [([AType], Maybe AType, Maybe AType)]) +adjustRWireFields :: ([VFieldInfo], [([AType], Maybe AType, [AType])]) -> + ([VFieldInfo], [([AType], Maybe AType, [AType])]) adjustRWireFields (vfi, fts) = let renameField vf@(Method {vf_name = i }) | (i `qualEq` idWHas) = vf { vf_name = unQualId $ mkRdyId idWGet } renameField vf = vf in (map renameField vfi, fts) -adjustRWire0Fields :: ([VFieldInfo], [([AType], Maybe AType, Maybe AType)]) -> - ([VFieldInfo], [([AType], Maybe AType, Maybe AType)]) +adjustRWire0Fields :: ([VFieldInfo], [([AType], Maybe AType, [AType])]) -> + ([VFieldInfo], [([AType], Maybe AType, [AType])]) adjustRWire0Fields (vfi, fts) = let (clk, rst) = case vfi of ((Method _ c r _ _ _ _):_) -> (c, r) _ -> internalError ("adjustRWire0Fields: vfi = " ++ ppReadable vfi) - wget_vfi = Method (unQualId idWGet) clk rst 1 [] Nothing Nothing - wget_fts = ([], Nothing, Nothing) + wget_vfi = Method (unQualId idWGet) clk rst 1 [] [] Nothing + wget_fts = ([], Nothing, []) in (wget_vfi:vfi, wget_fts:fts) -adjustWireFields :: ([VFieldInfo], [([AType], Maybe AType, Maybe AType)]) -> - ([VFieldInfo], [([AType], Maybe AType, Maybe AType)]) +adjustWireFields :: ([VFieldInfo], [([AType], Maybe AType, [AType])]) -> + ([VFieldInfo], [([AType], Maybe AType, [AType])]) adjustWireFields (vfi, fts) = let readId = id_read noPosition writeId = id_write noPosition @@ -3781,8 +3784,8 @@ adjustWireFields (vfi, fts) = in (map renameField vfi, fts) adjustPulseWireFields :: - ([VFieldInfo], [([AType], Maybe AType, Maybe AType)]) -> - ([VFieldInfo], [([AType], Maybe AType, Maybe AType)]) + ([VFieldInfo], [([AType], Maybe AType, [AType])]) -> + ([VFieldInfo], [([AType], Maybe AType, [AType])]) adjustPulseWireFields (vfi, fts) = let renameField vf@(Method {vf_name = i }) | (i `qualEq` idWSet) = vf { vf_name = unQualId idSend } @@ -3793,8 +3796,8 @@ adjustPulseWireFields (vfi, fts) = in (map renameField vfi, fts) adjustBypassWireFields :: - ([VFieldInfo], [([AType], Maybe AType, Maybe AType)]) -> - ([VFieldInfo], [([AType], Maybe AType, Maybe AType)]) + ([VFieldInfo], [([AType], Maybe AType, [AType])]) -> + ([VFieldInfo], [([AType], Maybe AType, [AType])]) adjustBypassWireFields (vfi, fts) = let renameField vf@(Method {vf_name = i }) | (i `qualEq` idWGet) = vf { vf_name = id_read noPosition } @@ -3882,19 +3885,19 @@ getPortsIfc ptmap out_clkinfo out_rstinfo (SubIfc fId fs) = then [] else [PISubIfc fId fs'] getPortsIfc ptmap _ _ - (Field fId (RawMethod i mult mclk mrst args ins mo me) mrdy_inf) = - getPortsIfcMethod ptmap fId i mult mclk mrst args ins mo me mr + (Field fId (RawMethod i mult mclk mrst args ins outs me) mrdy_inf) = + getPortsIfcMethod ptmap fId i mult mclk mrst args ins outs me mr where mr = case (mrdy_inf) of Nothing -> Nothing - (Just (RawMethod ri m _ _ [] [] (Just (vp@(vn,_), t)) Nothing)) + (Just (RawMethod ri m _ _ [] [] [(vp@(vn,_), t)] Nothing)) | ((m == 0) || (m == 1)) -> if (t == aTBool) then Just vp else internalError ("getPortsIfc: Rdy wrong size: " ++ ppReadable (ri,t)) - (Just (RawMethod ri m _ _ as is mout men)) -> + (Just (RawMethod ri m _ _ as is os men)) -> internalError ("getPortsIfc: not Rdy: " ++ - ppReadable (ri, m, as, is, mout, men)) + ppReadable (ri, m, as, is, os, men)) (Just d) -> internalError ("getPortsIfc: not Rdy: " ++ ppReadable (rawIfcFieldName d)) getPortsIfc _ out_clkinfo _ (Field fId (RawClock i) Nothing) = @@ -3911,10 +3914,10 @@ getPortsIfc _ _ _ (Field fId rf (Just rdy_rf)) = getPortsIfcMethod :: M.Map VName IType -> Id -> Id -> Integer -> Maybe Id -> Maybe Id -> - [(Maybe Id, AType)] -> [VPort] -> Maybe (VPort, AType) -> + [(Maybe Id, AType)] -> [VPort] -> [(VPort, AType)] -> Maybe VPort -> Maybe VPort -> [PortIfcInfo] -getPortsIfcMethod ptmap fId methId mult mClk mRst args ins mOut mEn mRdy = +getPortsIfcMethod ptmap fId methId mult mClk mRst args ins outs mEn mRdy = let -- get the port-type pair for an argument getPortsArg (mi, bit_type) (vn, _) = @@ -3922,8 +3925,7 @@ getPortsIfcMethod ptmap fId methId mult mClk mRst args ins mOut mEn mRdy = then [] else [(mi, bit_type, getVNameType ptmap vn)] -- get the port-type pair for the output - getPortsOut Nothing = Nothing - getPortsOut (Just ((vn, _), bit_type)) = + getPortsOut ((vn, _), bit_type) = if (isSizeZero bit_type) then Nothing else @@ -3946,7 +3948,7 @@ getPortsIfcMethod ptmap fId methId mult mClk mRst args ins mOut mEn mRdy = -- the default result (multiplicity of 1) def_res = PIMethod fId methId mClk mRst (concat (zipWith getPortsArg args ins)) - (getPortsOut mOut) (getPortsEn mEn) (getPortsRdy mRdy) + (mapMaybe getPortsOut outs) (getPortsEn mEn) (getPortsRdy mRdy) -- the result if multiplicity > 1 mkMulRes n = @@ -3955,7 +3957,7 @@ getPortsIfcMethod ptmap fId methId mult mClk mRst args ins mOut mEn mRdy = in PIMethod (dupId s fId) -- XXX handle mults differently? (dupId s methId) mClk mRst (concat (zipWith getPortsArg args ins')) - (getPortsOut (dupMVPortType s mOut)) + (mapMaybe (getPortsOut . dupMVPortType s) outs) (getPortsEn (dupMVPort s mEn)) (getPortsRdy (dupMVPort s mRdy)) @@ -3964,9 +3966,8 @@ getPortsIfcMethod ptmap fId methId mult mClk mRst args ins mOut mEn mRdy = dupVPort suf (vn, ps) = (dupVName suf vn, ps) dupMVPort :: String -> Maybe VPort -> Maybe VPort dupMVPort suf mvp = mvp >>= Just . dupVPort suf - dupMVPortType :: String -> Maybe (VPort, AType) -> Maybe (VPort, AType) - dupMVPortType suf mvpt = - mvpt >>= (\ (vp, t) -> Just (dupVPort suf vp, t) ) + dupMVPortType :: String -> (VPort, AType) -> (VPort, AType) + dupMVPortType suf (vp, t) = (dupVPort suf vp, t) in if (mult == 1) || (mult == 0) then [def_res] @@ -4029,13 +4030,6 @@ dispMPortWithType s mport = Nothing -> [] Just (p, _) -> [tagStr s p] -dispMPortWithTypes :: String -> Maybe (String, AType, IType) -> [HTclObj] -dispMPortWithTypes s mport = - case mport of - Nothing -> [] - Just (p, _, _) -> -- XXX we have the opportunity to display the size - [tagStr s p] - -- display AType dispSize :: AType -> [HTclObj] dispSize (ATBit sz) = [tagInt "size" (fromInteger sz)] @@ -4085,16 +4079,23 @@ dispMethodArgs as = dispSize bit_type in TLst (map dispArg as) +dispMethodResults :: [(String, AType, IType)] -> HTclObj +dispMethodResults outs = + let dispOut (port, bit_type, _) = + TLst $ [tagStr "port" port] ++ + dispSize bit_type + in TLst (map dispOut outs) + dispIfc :: PortIfcInfo -> HTclObj -dispIfc (PIMethod fId i mClk mRst ins mOut mEn mRdy) = +dispIfc (PIMethod fId i mClk mRst ins outs mEn mRdy) = TLst $ [TStr "method", TStr (getIdBaseString fId), TStr (pfpString i), dispClockedBy mClk, dispResetBy mRst, - tag "args" [dispMethodArgs ins]] ++ - dispMPortWithTypes "result" mOut ++ + tag "args" [dispMethodArgs ins], + tag "results" [dispMethodResults outs]] ++ dispMPortWithType "enable" mEn ++ dispMPortWithType "ready" mRdy dispIfc (PIClock fId i Nothing) = @@ -4124,6 +4125,9 @@ dispIfc (PISubIfc fId fs) = dispPortType :: (String, IType) -> HTclObj dispPortType (p,t) = TLst [TStr p, TStr (pfpString t)] +dispPortTypes :: (String, AType, IType) -> HTclObj +dispPortTypes (p,at,t) = dispPortType (p,t) + dispMPortType :: Maybe (String, IType) -> [HTclObj] dispMPortType Nothing = [] dispMPortType (Just pt) = [dispPortType pt] @@ -4144,9 +4148,10 @@ dispPortsModArg (PAInout _ _ pt _ _) = [dispPortType pt] dispPortsIfc :: PortIfcInfo -> [HTclObj] -dispPortsIfc (PIMethod _ _ _ _ ins mOut mEn mRdy) = +dispPortsIfc (PIMethod _ _ _ _ ins outs mEn mRdy) = (map (dispPortType . thd) ins) ++ - dispMPortTypes mOut ++ dispMPortType mEn ++ dispMPortType mRdy + (map dispPortTypes outs) ++ + dispMPortType mEn ++ dispMPortType mRdy dispPortsIfc (PIClock _ _ Nothing) = [] dispPortsIfc (PIClock _ _ (Just (osc, mgate))) = [dispPortType osc] ++ dispMPortType mgate @@ -4217,7 +4222,7 @@ get_method_to_signal_map vmod = do case f of Method {} -> return () _ -> mzero -- failure, as in the guard function - port <- (vf_inputs f) ++ (maybeToList $ vf_output f) ++ (maybeToList $ vf_enable f) + port <- (vf_inputs f) ++ (vf_outputs f) ++ (maybeToList $ vf_enable f) count <- case (vf_mult f) of 1 -> return Nothing k -> map Just [1..k] diff --git a/src/comp/showrules.hs b/src/comp/showrules.hs index fbb92ebb7..531d94410 100644 --- a/src/comp/showrules.hs +++ b/src/comp/showrules.hs @@ -455,7 +455,7 @@ mkMorphState opts instmap hiermap abmis_by_name top_mod = let methmap = M.fromList [ ((inst,name),rules) | (inst,abmi) <- user_modules , aif <- apkg_interface (abmi_apkg abmi) - , let name = aIfaceName aif + , let name = aif_name aif , let rules = aIfaceRules aif , not (null rules) ] diff --git a/testsuite/bsc.bluetcl/commands/module.tcl.bluetcl-bh-out.expected b/testsuite/bsc.bluetcl/commands/module.tcl.bluetcl-bh-out.expected index b572a8ea5..784ac49b5 100644 --- a/testsuite/bsc.bluetcl/commands/module.tcl.bluetcl-bh-out.expected +++ b/testsuite/bsc.bluetcl/commands/module.tcl.bluetcl-bh-out.expected @@ -115,19 +115,19 @@ ios1_1 {Prelude.Inout Test.Bar} ---------- module ports mkT Command: module ports mkT -interface {{interface r {{method _write r__write {clock default_clock} {reset no_reset} {args {{{name r__write_1} {port r__write_1} {size 1}}}} {enable EN_r__write} {ready RDY_r__write}} {method _read r__read {clock no_clock} {reset no_reset} {args {}} {result r__read} {ready RDY_r__read}}}} {inout b b {port b} {clock default_clock} {reset default_reset}}} +interface {{interface r {{method _write r__write {clock default_clock} {reset no_reset} {args {{{name r__write_1} {port r__write_1} {size 1}}}} {results {}} {enable EN_r__write} {ready RDY_r__write}} {method _read r__read {clock no_clock} {reset no_reset} {args {}} {results {{{port r__read} {size 1}}}} {ready RDY_r__read}}}} {inout b b {port b} {clock default_clock} {reset default_reset}}} args {{inout i {port i} {clock default_clock} {reset default_reset} {size 2}} {clock default_clock {osc CLK}} {reset default_reset {port RST_N} {clock default_clock}}} --------- module ports mkM Command: module ports mkM -interface {{method _write _write {clock default_clock} {reset default_reset} {args {{{name _write_1} {port _write_1} {size 1}}}} {enable EN__write} {ready RDY__write}} {method _read _read {clock default_clock} {reset default_reset} {args {}} {result _read} {ready RDY__read}}} +interface {{method _write _write {clock default_clock} {reset default_reset} {args {{{name _write_1} {port _write_1} {size 1}}}} {results {}} {enable EN__write} {ready RDY__write}} {method _read _read {clock default_clock} {reset default_reset} {args {}} {results {{{port _read} {size 1}}}} {ready RDY__read}}} args {{clock default_clock {osc CLK}} {reset default_reset {port RST_N} {clock default_clock}}} --------- module ports mkIfcWithVec Command: module ports mkIfcWithVec -interface {{interface vec1 {{interface 0 {{method _write vec1_0__write {clock clks1_1} {reset no_reset} {args {{{name vec1_0__write_1} {port vec1_0__write_1} {size 1}}}} {enable EN_vec1_0__write} {ready RDY_vec1_0__write}} {method _read vec1_0__read {clock no_clock} {reset no_reset} {args {}} {result vec1_0__read} {ready RDY_vec1_0__read}}}} {interface 1 {{method _write vec1_1__write {clock clks1_1} {reset no_reset} {args {{{name vec1_1__write_1} {port vec1_1__write_1} {size 1}}}} {enable EN_vec1_1__write} {ready RDY_vec1_1__write}} {method _read vec1_1__read {clock no_clock} {reset no_reset} {args {}} {result vec1_1__read} {ready RDY_vec1_1__read}}}}}} {interface vec2 {{interface 0 {{interface 0 {{method _write vec2_0_0__write {clock clks1_1} {reset no_reset} {args {{{name vec2_0_0__write_1} {port vec2_0_0__write_1} {size 1}}}} {enable EN_vec2_0_0__write} {ready RDY_vec2_0_0__write}} {method _read vec2_0_0__read {clock no_clock} {reset no_reset} {args {}} {result vec2_0_0__read} {ready RDY_vec2_0_0__read}}}} {interface 1 {{method _write vec2_0_1__write {clock clks1_1} {reset no_reset} {args {{{name vec2_0_1__write_1} {port vec2_0_1__write_1} {size 1}}}} {enable EN_vec2_0_1__write} {ready RDY_vec2_0_1__write}} {method _read vec2_0_1__read {clock no_clock} {reset no_reset} {args {}} {result vec2_0_1__read} {ready RDY_vec2_0_1__read}}}}}} {interface 1 {{interface 0 {{method _write vec2_1_0__write {clock clks1_1} {reset no_reset} {args {{{name vec2_1_0__write_1} {port vec2_1_0__write_1} {size 1}}}} {enable EN_vec2_1_0__write} {ready RDY_vec2_1_0__write}} {method _read vec2_1_0__read {clock no_clock} {reset no_reset} {args {}} {result vec2_1_0__read} {ready RDY_vec2_1_0__read}}}} {interface 1 {{method _write vec2_1_1__write {clock clks1_1} {reset no_reset} {args {{{name vec2_1_1__write_1} {port vec2_1_1__write_1} {size 1}}}} {enable EN_vec2_1_1__write} {ready RDY_vec2_1_1__write}} {method _read vec2_1_1__read {clock no_clock} {reset no_reset} {args {}} {result vec2_1_1__read} {ready RDY_vec2_1_1__read}}}}}}}} {interface vec3 {{interface 0 {{interface 0 {{interface 0 {{method _write vec3_0_0_0__write {clock clks1_1} {reset no_reset} {args {{{name vec3_0_0_0__write_1} {port vec3_0_0_0__write_1} {size 1}}}} {enable EN_vec3_0_0_0__write} {ready RDY_vec3_0_0_0__write}} {method _read vec3_0_0_0__read {clock no_clock} {reset no_reset} {args {}} {result vec3_0_0_0__read} {ready RDY_vec3_0_0_0__read}}}} {interface 1 {{method _write vec3_0_0_1__write {clock clks1_1} {reset no_reset} {args {{{name vec3_0_0_1__write_1} {port vec3_0_0_1__write_1} {size 1}}}} {enable EN_vec3_0_0_1__write} {ready RDY_vec3_0_0_1__write}} {method _read vec3_0_0_1__read {clock no_clock} {reset no_reset} {args {}} {result vec3_0_0_1__read} {ready RDY_vec3_0_0_1__read}}}}}} {interface 1 {{interface 0 {{method _write vec3_0_1_0__write {clock clks1_1} {reset no_reset} {args {{{name vec3_0_1_0__write_1} {port vec3_0_1_0__write_1} {size 1}}}} {enable EN_vec3_0_1_0__write} {ready RDY_vec3_0_1_0__write}} {method _read vec3_0_1_0__read {clock no_clock} {reset no_reset} {args {}} {result vec3_0_1_0__read} {ready RDY_vec3_0_1_0__read}}}} {interface 1 {{method _write vec3_0_1_1__write {clock clks1_1} {reset no_reset} {args {{{name vec3_0_1_1__write_1} {port vec3_0_1_1__write_1} {size 1}}}} {enable EN_vec3_0_1_1__write} {ready RDY_vec3_0_1_1__write}} {method _read vec3_0_1_1__read {clock no_clock} {reset no_reset} {args {}} {result vec3_0_1_1__read} {ready RDY_vec3_0_1_1__read}}}}}}}} {interface 1 {{interface 0 {{interface 0 {{method _write vec3_1_0_0__write {clock clks1_1} {reset no_reset} {args {{{name vec3_1_0_0__write_1} {port vec3_1_0_0__write_1} {size 1}}}} {enable EN_vec3_1_0_0__write} {ready RDY_vec3_1_0_0__write}} {method _read vec3_1_0_0__read {clock no_clock} {reset no_reset} {args {}} {result vec3_1_0_0__read} {ready RDY_vec3_1_0_0__read}}}} {interface 1 {{method _write vec3_1_0_1__write {clock clks1_1} {reset no_reset} {args {{{name vec3_1_0_1__write_1} {port vec3_1_0_1__write_1} {size 1}}}} {enable EN_vec3_1_0_1__write} {ready RDY_vec3_1_0_1__write}} {method _read vec3_1_0_1__read {clock no_clock} {reset no_reset} {args {}} {result vec3_1_0_1__read} {ready RDY_vec3_1_0_1__read}}}}}} {interface 1 {{interface 0 {{method _write vec3_1_1_0__write {clock clks1_1} {reset no_reset} {args {{{name vec3_1_1_0__write_1} {port vec3_1_1_0__write_1} {size 1}}}} {enable EN_vec3_1_1_0__write} {ready RDY_vec3_1_1_0__write}} {method _read vec3_1_1_0__read {clock no_clock} {reset no_reset} {args {}} {result vec3_1_1_0__read} {ready RDY_vec3_1_1_0__read}}}} {interface 1 {{method _write vec3_1_1_1__write {clock clks1_1} {reset no_reset} {args {{{name vec3_1_1_1__write_1} {port vec3_1_1_1__write_1} {size 1}}}} {enable EN_vec3_1_1_1__write} {ready RDY_vec3_1_1_1__write}} {method _read vec3_1_1_1__read {clock no_clock} {reset no_reset} {args {}} {result vec3_1_1_1__read} {ready RDY_vec3_1_1_1__read}}}}}}}}}} {method data1 data1 {clock no_clock} {reset no_reset} {args {}} {result data1} {ready RDY_data1}} {method data2 data2 {clock no_clock} {reset no_reset} {args {}} {result data2} {ready RDY_data2}} {method data3 data3 {clock no_clock} {reset no_reset} {args {}} {result data3} {ready RDY_data3}} {interface clks1 {{interface 0 {{clock {} clks1_0 {osc CLK_clks1_0} {gate CLK_GATE_clks1_0}}}} {interface 1 {{clock {} clks1_1 {osc CLK_clks1_1} {gate CLK_GATE_clks1_1}}}}}} {interface rsts1 {{interface 0 {{reset {} rsts1_0 {port RST_N_rsts1_0} {clock default_clock}}}} {interface 1 {{reset {} rsts1_1 {port RST_N_rsts1_1} {clock default_clock}}}}}} {interface ios1 {{interface 0 {{inout {} ios1_0 {port ios1_0} {clock clks1_1} {reset rsts1_1}}}} {interface 1 {{inout {} ios1_1 {port ios1_1} {clock clks1_1} {reset rsts1_1}}}}}}} +interface {{interface vec1 {{interface 0 {{method _write vec1_0__write {clock clks1_1} {reset no_reset} {args {{{name vec1_0__write_1} {port vec1_0__write_1} {size 1}}}} {results {}} {enable EN_vec1_0__write} {ready RDY_vec1_0__write}} {method _read vec1_0__read {clock no_clock} {reset no_reset} {args {}} {results {{{port vec1_0__read} {size 1}}}} {ready RDY_vec1_0__read}}}} {interface 1 {{method _write vec1_1__write {clock clks1_1} {reset no_reset} {args {{{name vec1_1__write_1} {port vec1_1__write_1} {size 1}}}} {results {}} {enable EN_vec1_1__write} {ready RDY_vec1_1__write}} {method _read vec1_1__read {clock no_clock} {reset no_reset} {args {}} {results {{{port vec1_1__read} {size 1}}}} {ready RDY_vec1_1__read}}}}}} {interface vec2 {{interface 0 {{interface 0 {{method _write vec2_0_0__write {clock clks1_1} {reset no_reset} {args {{{name vec2_0_0__write_1} {port vec2_0_0__write_1} {size 1}}}} {results {}} {enable EN_vec2_0_0__write} {ready RDY_vec2_0_0__write}} {method _read vec2_0_0__read {clock no_clock} {reset no_reset} {args {}} {results {{{port vec2_0_0__read} {size 1}}}} {ready RDY_vec2_0_0__read}}}} {interface 1 {{method _write vec2_0_1__write {clock clks1_1} {reset no_reset} {args {{{name vec2_0_1__write_1} {port vec2_0_1__write_1} {size 1}}}} {results {}} {enable EN_vec2_0_1__write} {ready RDY_vec2_0_1__write}} {method _read vec2_0_1__read {clock no_clock} {reset no_reset} {args {}} {results {{{port vec2_0_1__read} {size 1}}}} {ready RDY_vec2_0_1__read}}}}}} {interface 1 {{interface 0 {{method _write vec2_1_0__write {clock clks1_1} {reset no_reset} {args {{{name vec2_1_0__write_1} {port vec2_1_0__write_1} {size 1}}}} {results {}} {enable EN_vec2_1_0__write} {ready RDY_vec2_1_0__write}} {method _read vec2_1_0__read {clock no_clock} {reset no_reset} {args {}} {results {{{port vec2_1_0__read} {size 1}}}} {ready RDY_vec2_1_0__read}}}} {interface 1 {{method _write vec2_1_1__write {clock clks1_1} {reset no_reset} {args {{{name vec2_1_1__write_1} {port vec2_1_1__write_1} {size 1}}}} {results {}} {enable EN_vec2_1_1__write} {ready RDY_vec2_1_1__write}} {method _read vec2_1_1__read {clock no_clock} {reset no_reset} {args {}} {results {{{port vec2_1_1__read} {size 1}}}} {ready RDY_vec2_1_1__read}}}}}}}} {interface vec3 {{interface 0 {{interface 0 {{interface 0 {{method _write vec3_0_0_0__write {clock clks1_1} {reset no_reset} {args {{{name vec3_0_0_0__write_1} {port vec3_0_0_0__write_1} {size 1}}}} {results {}} {enable EN_vec3_0_0_0__write} {ready RDY_vec3_0_0_0__write}} {method _read vec3_0_0_0__read {clock no_clock} {reset no_reset} {args {}} {results {{{port vec3_0_0_0__read} {size 1}}}} {ready RDY_vec3_0_0_0__read}}}} {interface 1 {{method _write vec3_0_0_1__write {clock clks1_1} {reset no_reset} {args {{{name vec3_0_0_1__write_1} {port vec3_0_0_1__write_1} {size 1}}}} {results {}} {enable EN_vec3_0_0_1__write} {ready RDY_vec3_0_0_1__write}} {method _read vec3_0_0_1__read {clock no_clock} {reset no_reset} {args {}} {results {{{port vec3_0_0_1__read} {size 1}}}} {ready RDY_vec3_0_0_1__read}}}}}} {interface 1 {{interface 0 {{method _write vec3_0_1_0__write {clock clks1_1} {reset no_reset} {args {{{name vec3_0_1_0__write_1} {port vec3_0_1_0__write_1} {size 1}}}} {results {}} {enable EN_vec3_0_1_0__write} {ready RDY_vec3_0_1_0__write}} {method _read vec3_0_1_0__read {clock no_clock} {reset no_reset} {args {}} {results {{{port vec3_0_1_0__read} {size 1}}}} {ready RDY_vec3_0_1_0__read}}}} {interface 1 {{method _write vec3_0_1_1__write {clock clks1_1} {reset no_reset} {args {{{name vec3_0_1_1__write_1} {port vec3_0_1_1__write_1} {size 1}}}} {results {}} {enable EN_vec3_0_1_1__write} {ready RDY_vec3_0_1_1__write}} {method _read vec3_0_1_1__read {clock no_clock} {reset no_reset} {args {}} {results {{{port vec3_0_1_1__read} {size 1}}}} {ready RDY_vec3_0_1_1__read}}}}}}}} {interface 1 {{interface 0 {{interface 0 {{method _write vec3_1_0_0__write {clock clks1_1} {reset no_reset} {args {{{name vec3_1_0_0__write_1} {port vec3_1_0_0__write_1} {size 1}}}} {results {}} {enable EN_vec3_1_0_0__write} {ready RDY_vec3_1_0_0__write}} {method _read vec3_1_0_0__read {clock no_clock} {reset no_reset} {args {}} {results {{{port vec3_1_0_0__read} {size 1}}}} {ready RDY_vec3_1_0_0__read}}}} {interface 1 {{method _write vec3_1_0_1__write {clock clks1_1} {reset no_reset} {args {{{name vec3_1_0_1__write_1} {port vec3_1_0_1__write_1} {size 1}}}} {results {}} {enable EN_vec3_1_0_1__write} {ready RDY_vec3_1_0_1__write}} {method _read vec3_1_0_1__read {clock no_clock} {reset no_reset} {args {}} {results {{{port vec3_1_0_1__read} {size 1}}}} {ready RDY_vec3_1_0_1__read}}}}}} {interface 1 {{interface 0 {{method _write vec3_1_1_0__write {clock clks1_1} {reset no_reset} {args {{{name vec3_1_1_0__write_1} {port vec3_1_1_0__write_1} {size 1}}}} {results {}} {enable EN_vec3_1_1_0__write} {ready RDY_vec3_1_1_0__write}} {method _read vec3_1_1_0__read {clock no_clock} {reset no_reset} {args {}} {results {{{port vec3_1_1_0__read} {size 1}}}} {ready RDY_vec3_1_1_0__read}}}} {interface 1 {{method _write vec3_1_1_1__write {clock clks1_1} {reset no_reset} {args {{{name vec3_1_1_1__write_1} {port vec3_1_1_1__write_1} {size 1}}}} {results {}} {enable EN_vec3_1_1_1__write} {ready RDY_vec3_1_1_1__write}} {method _read vec3_1_1_1__read {clock no_clock} {reset no_reset} {args {}} {results {{{port vec3_1_1_1__read} {size 1}}}} {ready RDY_vec3_1_1_1__read}}}}}}}}}} {method data1 data1 {clock no_clock} {reset no_reset} {args {}} {results {{{port data1} {size 2}}}} {ready RDY_data1}} {method data2 data2 {clock no_clock} {reset no_reset} {args {}} {results {{{port data2} {size 4}}}} {ready RDY_data2}} {method data3 data3 {clock no_clock} {reset no_reset} {args {}} {results {{{port data3} {size 8}}}} {ready RDY_data3}} {interface clks1 {{interface 0 {{clock {} clks1_0 {osc CLK_clks1_0} {gate CLK_GATE_clks1_0}}}} {interface 1 {{clock {} clks1_1 {osc CLK_clks1_1} {gate CLK_GATE_clks1_1}}}}}} {interface rsts1 {{interface 0 {{reset {} rsts1_0 {port RST_N_rsts1_0} {clock default_clock}}}} {interface 1 {{reset {} rsts1_1 {port RST_N_rsts1_1} {clock default_clock}}}}}} {interface ios1 {{interface 0 {{inout {} ios1_0 {port ios1_0} {clock clks1_1} {reset rsts1_1}}}} {interface 1 {{inout {} ios1_1 {port ios1_1} {clock clks1_1} {reset rsts1_1}}}}}}} args {{inout io {port io} {clock default_clock} {reset default_reset} {size 2}} {clock default_clock {osc CLK}} {reset default_reset {port RST_N} {clock default_clock}}} --------- ---------- diff --git a/testsuite/bsc.bluetcl/commands/module.tcl.bluetcl-out.expected b/testsuite/bsc.bluetcl/commands/module.tcl.bluetcl-out.expected index d02606a21..32af9b611 100644 --- a/testsuite/bsc.bluetcl/commands/module.tcl.bluetcl-out.expected +++ b/testsuite/bsc.bluetcl/commands/module.tcl.bluetcl-out.expected @@ -115,19 +115,19 @@ ios1_1 Inout#(Test::Bar) ---------- module ports mkT Command: module ports mkT -interface {{interface r {{method _write r__write {clock default_clock} {reset no_reset} {args {{{name r__write_1} {port r__write_1} {size 1}}}} {enable EN_r__write} {ready RDY_r__write}} {method _read r__read {clock no_clock} {reset no_reset} {args {}} {result r__read} {ready RDY_r__read}}}} {inout b b {port b} {clock default_clock} {reset default_reset}}} +interface {{interface r {{method _write r__write {clock default_clock} {reset no_reset} {args {{{name r__write_1} {port r__write_1} {size 1}}}} {results {}} {enable EN_r__write} {ready RDY_r__write}} {method _read r__read {clock no_clock} {reset no_reset} {args {}} {results {{{port r__read} {size 1}}}} {ready RDY_r__read}}}} {inout b b {port b} {clock default_clock} {reset default_reset}}} args {{inout i {port i} {clock default_clock} {reset default_reset} {size 2}} {clock default_clock {osc CLK}} {reset default_reset {port RST_N} {clock default_clock}}} --------- module ports mkM Command: module ports mkM -interface {{method _write _write {clock default_clock} {reset default_reset} {args {{{name _write_1} {port _write_1} {size 1}}}} {enable EN__write} {ready RDY__write}} {method _read _read {clock default_clock} {reset default_reset} {args {}} {result _read} {ready RDY__read}}} +interface {{method _write _write {clock default_clock} {reset default_reset} {args {{{name _write_1} {port _write_1} {size 1}}}} {results {}} {enable EN__write} {ready RDY__write}} {method _read _read {clock default_clock} {reset default_reset} {args {}} {results {{{port _read} {size 1}}}} {ready RDY__read}}} args {{clock default_clock {osc CLK}} {reset default_reset {port RST_N} {clock default_clock}}} --------- module ports mkIfcWithVec Command: module ports mkIfcWithVec -interface {{interface vec1 {{interface 0 {{method _write vec1_0__write {clock clks1_1} {reset no_reset} {args {{{name vec1_0__write_1} {port vec1_0__write_1} {size 1}}}} {enable EN_vec1_0__write} {ready RDY_vec1_0__write}} {method _read vec1_0__read {clock no_clock} {reset no_reset} {args {}} {result vec1_0__read} {ready RDY_vec1_0__read}}}} {interface 1 {{method _write vec1_1__write {clock clks1_1} {reset no_reset} {args {{{name vec1_1__write_1} {port vec1_1__write_1} {size 1}}}} {enable EN_vec1_1__write} {ready RDY_vec1_1__write}} {method _read vec1_1__read {clock no_clock} {reset no_reset} {args {}} {result vec1_1__read} {ready RDY_vec1_1__read}}}}}} {interface vec2 {{interface 0 {{interface 0 {{method _write vec2_0_0__write {clock clks1_1} {reset no_reset} {args {{{name vec2_0_0__write_1} {port vec2_0_0__write_1} {size 1}}}} {enable EN_vec2_0_0__write} {ready RDY_vec2_0_0__write}} {method _read vec2_0_0__read {clock no_clock} {reset no_reset} {args {}} {result vec2_0_0__read} {ready RDY_vec2_0_0__read}}}} {interface 1 {{method _write vec2_0_1__write {clock clks1_1} {reset no_reset} {args {{{name vec2_0_1__write_1} {port vec2_0_1__write_1} {size 1}}}} {enable EN_vec2_0_1__write} {ready RDY_vec2_0_1__write}} {method _read vec2_0_1__read {clock no_clock} {reset no_reset} {args {}} {result vec2_0_1__read} {ready RDY_vec2_0_1__read}}}}}} {interface 1 {{interface 0 {{method _write vec2_1_0__write {clock clks1_1} {reset no_reset} {args {{{name vec2_1_0__write_1} {port vec2_1_0__write_1} {size 1}}}} {enable EN_vec2_1_0__write} {ready RDY_vec2_1_0__write}} {method _read vec2_1_0__read {clock no_clock} {reset no_reset} {args {}} {result vec2_1_0__read} {ready RDY_vec2_1_0__read}}}} {interface 1 {{method _write vec2_1_1__write {clock clks1_1} {reset no_reset} {args {{{name vec2_1_1__write_1} {port vec2_1_1__write_1} {size 1}}}} {enable EN_vec2_1_1__write} {ready RDY_vec2_1_1__write}} {method _read vec2_1_1__read {clock no_clock} {reset no_reset} {args {}} {result vec2_1_1__read} {ready RDY_vec2_1_1__read}}}}}}}} {interface vec3 {{interface 0 {{interface 0 {{interface 0 {{method _write vec3_0_0_0__write {clock clks1_1} {reset no_reset} {args {{{name vec3_0_0_0__write_1} {port vec3_0_0_0__write_1} {size 1}}}} {enable EN_vec3_0_0_0__write} {ready RDY_vec3_0_0_0__write}} {method _read vec3_0_0_0__read {clock no_clock} {reset no_reset} {args {}} {result vec3_0_0_0__read} {ready RDY_vec3_0_0_0__read}}}} {interface 1 {{method _write vec3_0_0_1__write {clock clks1_1} {reset no_reset} {args {{{name vec3_0_0_1__write_1} {port vec3_0_0_1__write_1} {size 1}}}} {enable EN_vec3_0_0_1__write} {ready RDY_vec3_0_0_1__write}} {method _read vec3_0_0_1__read {clock no_clock} {reset no_reset} {args {}} {result vec3_0_0_1__read} {ready RDY_vec3_0_0_1__read}}}}}} {interface 1 {{interface 0 {{method _write vec3_0_1_0__write {clock clks1_1} {reset no_reset} {args {{{name vec3_0_1_0__write_1} {port vec3_0_1_0__write_1} {size 1}}}} {enable EN_vec3_0_1_0__write} {ready RDY_vec3_0_1_0__write}} {method _read vec3_0_1_0__read {clock no_clock} {reset no_reset} {args {}} {result vec3_0_1_0__read} {ready RDY_vec3_0_1_0__read}}}} {interface 1 {{method _write vec3_0_1_1__write {clock clks1_1} {reset no_reset} {args {{{name vec3_0_1_1__write_1} {port vec3_0_1_1__write_1} {size 1}}}} {enable EN_vec3_0_1_1__write} {ready RDY_vec3_0_1_1__write}} {method _read vec3_0_1_1__read {clock no_clock} {reset no_reset} {args {}} {result vec3_0_1_1__read} {ready RDY_vec3_0_1_1__read}}}}}}}} {interface 1 {{interface 0 {{interface 0 {{method _write vec3_1_0_0__write {clock clks1_1} {reset no_reset} {args {{{name vec3_1_0_0__write_1} {port vec3_1_0_0__write_1} {size 1}}}} {enable EN_vec3_1_0_0__write} {ready RDY_vec3_1_0_0__write}} {method _read vec3_1_0_0__read {clock no_clock} {reset no_reset} {args {}} {result vec3_1_0_0__read} {ready RDY_vec3_1_0_0__read}}}} {interface 1 {{method _write vec3_1_0_1__write {clock clks1_1} {reset no_reset} {args {{{name vec3_1_0_1__write_1} {port vec3_1_0_1__write_1} {size 1}}}} {enable EN_vec3_1_0_1__write} {ready RDY_vec3_1_0_1__write}} {method _read vec3_1_0_1__read {clock no_clock} {reset no_reset} {args {}} {result vec3_1_0_1__read} {ready RDY_vec3_1_0_1__read}}}}}} {interface 1 {{interface 0 {{method _write vec3_1_1_0__write {clock clks1_1} {reset no_reset} {args {{{name vec3_1_1_0__write_1} {port vec3_1_1_0__write_1} {size 1}}}} {enable EN_vec3_1_1_0__write} {ready RDY_vec3_1_1_0__write}} {method _read vec3_1_1_0__read {clock no_clock} {reset no_reset} {args {}} {result vec3_1_1_0__read} {ready RDY_vec3_1_1_0__read}}}} {interface 1 {{method _write vec3_1_1_1__write {clock clks1_1} {reset no_reset} {args {{{name vec3_1_1_1__write_1} {port vec3_1_1_1__write_1} {size 1}}}} {enable EN_vec3_1_1_1__write} {ready RDY_vec3_1_1_1__write}} {method _read vec3_1_1_1__read {clock no_clock} {reset no_reset} {args {}} {result vec3_1_1_1__read} {ready RDY_vec3_1_1_1__read}}}}}}}}}} {method data1 data1 {clock no_clock} {reset no_reset} {args {}} {result data1} {ready RDY_data1}} {method data2 data2 {clock no_clock} {reset no_reset} {args {}} {result data2} {ready RDY_data2}} {method data3 data3 {clock no_clock} {reset no_reset} {args {}} {result data3} {ready RDY_data3}} {interface clks1 {{interface 0 {{clock {} clks1_0 {osc CLK_clks1_0} {gate CLK_GATE_clks1_0}}}} {interface 1 {{clock {} clks1_1 {osc CLK_clks1_1} {gate CLK_GATE_clks1_1}}}}}} {interface rsts1 {{interface 0 {{reset {} rsts1_0 {port RST_N_rsts1_0} {clock default_clock}}}} {interface 1 {{reset {} rsts1_1 {port RST_N_rsts1_1} {clock default_clock}}}}}} {interface ios1 {{interface 0 {{inout {} ios1_0 {port ios1_0} {clock clks1_1} {reset rsts1_1}}}} {interface 1 {{inout {} ios1_1 {port ios1_1} {clock clks1_1} {reset rsts1_1}}}}}}} +interface {{interface vec1 {{interface 0 {{method _write vec1_0__write {clock clks1_1} {reset no_reset} {args {{{name vec1_0__write_1} {port vec1_0__write_1} {size 1}}}} {results {}} {enable EN_vec1_0__write} {ready RDY_vec1_0__write}} {method _read vec1_0__read {clock no_clock} {reset no_reset} {args {}} {results {{{port vec1_0__read} {size 1}}}} {ready RDY_vec1_0__read}}}} {interface 1 {{method _write vec1_1__write {clock clks1_1} {reset no_reset} {args {{{name vec1_1__write_1} {port vec1_1__write_1} {size 1}}}} {results {}} {enable EN_vec1_1__write} {ready RDY_vec1_1__write}} {method _read vec1_1__read {clock no_clock} {reset no_reset} {args {}} {results {{{port vec1_1__read} {size 1}}}} {ready RDY_vec1_1__read}}}}}} {interface vec2 {{interface 0 {{interface 0 {{method _write vec2_0_0__write {clock clks1_1} {reset no_reset} {args {{{name vec2_0_0__write_1} {port vec2_0_0__write_1} {size 1}}}} {results {}} {enable EN_vec2_0_0__write} {ready RDY_vec2_0_0__write}} {method _read vec2_0_0__read {clock no_clock} {reset no_reset} {args {}} {results {{{port vec2_0_0__read} {size 1}}}} {ready RDY_vec2_0_0__read}}}} {interface 1 {{method _write vec2_0_1__write {clock clks1_1} {reset no_reset} {args {{{name vec2_0_1__write_1} {port vec2_0_1__write_1} {size 1}}}} {results {}} {enable EN_vec2_0_1__write} {ready RDY_vec2_0_1__write}} {method _read vec2_0_1__read {clock no_clock} {reset no_reset} {args {}} {results {{{port vec2_0_1__read} {size 1}}}} {ready RDY_vec2_0_1__read}}}}}} {interface 1 {{interface 0 {{method _write vec2_1_0__write {clock clks1_1} {reset no_reset} {args {{{name vec2_1_0__write_1} {port vec2_1_0__write_1} {size 1}}}} {results {}} {enable EN_vec2_1_0__write} {ready RDY_vec2_1_0__write}} {method _read vec2_1_0__read {clock no_clock} {reset no_reset} {args {}} {results {{{port vec2_1_0__read} {size 1}}}} {ready RDY_vec2_1_0__read}}}} {interface 1 {{method _write vec2_1_1__write {clock clks1_1} {reset no_reset} {args {{{name vec2_1_1__write_1} {port vec2_1_1__write_1} {size 1}}}} {results {}} {enable EN_vec2_1_1__write} {ready RDY_vec2_1_1__write}} {method _read vec2_1_1__read {clock no_clock} {reset no_reset} {args {}} {results {{{port vec2_1_1__read} {size 1}}}} {ready RDY_vec2_1_1__read}}}}}}}} {interface vec3 {{interface 0 {{interface 0 {{interface 0 {{method _write vec3_0_0_0__write {clock clks1_1} {reset no_reset} {args {{{name vec3_0_0_0__write_1} {port vec3_0_0_0__write_1} {size 1}}}} {results {}} {enable EN_vec3_0_0_0__write} {ready RDY_vec3_0_0_0__write}} {method _read vec3_0_0_0__read {clock no_clock} {reset no_reset} {args {}} {results {{{port vec3_0_0_0__read} {size 1}}}} {ready RDY_vec3_0_0_0__read}}}} {interface 1 {{method _write vec3_0_0_1__write {clock clks1_1} {reset no_reset} {args {{{name vec3_0_0_1__write_1} {port vec3_0_0_1__write_1} {size 1}}}} {results {}} {enable EN_vec3_0_0_1__write} {ready RDY_vec3_0_0_1__write}} {method _read vec3_0_0_1__read {clock no_clock} {reset no_reset} {args {}} {results {{{port vec3_0_0_1__read} {size 1}}}} {ready RDY_vec3_0_0_1__read}}}}}} {interface 1 {{interface 0 {{method _write vec3_0_1_0__write {clock clks1_1} {reset no_reset} {args {{{name vec3_0_1_0__write_1} {port vec3_0_1_0__write_1} {size 1}}}} {results {}} {enable EN_vec3_0_1_0__write} {ready RDY_vec3_0_1_0__write}} {method _read vec3_0_1_0__read {clock no_clock} {reset no_reset} {args {}} {results {{{port vec3_0_1_0__read} {size 1}}}} {ready RDY_vec3_0_1_0__read}}}} {interface 1 {{method _write vec3_0_1_1__write {clock clks1_1} {reset no_reset} {args {{{name vec3_0_1_1__write_1} {port vec3_0_1_1__write_1} {size 1}}}} {results {}} {enable EN_vec3_0_1_1__write} {ready RDY_vec3_0_1_1__write}} {method _read vec3_0_1_1__read {clock no_clock} {reset no_reset} {args {}} {results {{{port vec3_0_1_1__read} {size 1}}}} {ready RDY_vec3_0_1_1__read}}}}}}}} {interface 1 {{interface 0 {{interface 0 {{method _write vec3_1_0_0__write {clock clks1_1} {reset no_reset} {args {{{name vec3_1_0_0__write_1} {port vec3_1_0_0__write_1} {size 1}}}} {results {}} {enable EN_vec3_1_0_0__write} {ready RDY_vec3_1_0_0__write}} {method _read vec3_1_0_0__read {clock no_clock} {reset no_reset} {args {}} {results {{{port vec3_1_0_0__read} {size 1}}}} {ready RDY_vec3_1_0_0__read}}}} {interface 1 {{method _write vec3_1_0_1__write {clock clks1_1} {reset no_reset} {args {{{name vec3_1_0_1__write_1} {port vec3_1_0_1__write_1} {size 1}}}} {results {}} {enable EN_vec3_1_0_1__write} {ready RDY_vec3_1_0_1__write}} {method _read vec3_1_0_1__read {clock no_clock} {reset no_reset} {args {}} {results {{{port vec3_1_0_1__read} {size 1}}}} {ready RDY_vec3_1_0_1__read}}}}}} {interface 1 {{interface 0 {{method _write vec3_1_1_0__write {clock clks1_1} {reset no_reset} {args {{{name vec3_1_1_0__write_1} {port vec3_1_1_0__write_1} {size 1}}}} {results {}} {enable EN_vec3_1_1_0__write} {ready RDY_vec3_1_1_0__write}} {method _read vec3_1_1_0__read {clock no_clock} {reset no_reset} {args {}} {results {{{port vec3_1_1_0__read} {size 1}}}} {ready RDY_vec3_1_1_0__read}}}} {interface 1 {{method _write vec3_1_1_1__write {clock clks1_1} {reset no_reset} {args {{{name vec3_1_1_1__write_1} {port vec3_1_1_1__write_1} {size 1}}}} {results {}} {enable EN_vec3_1_1_1__write} {ready RDY_vec3_1_1_1__write}} {method _read vec3_1_1_1__read {clock no_clock} {reset no_reset} {args {}} {results {{{port vec3_1_1_1__read} {size 1}}}} {ready RDY_vec3_1_1_1__read}}}}}}}}}} {method data1 data1 {clock no_clock} {reset no_reset} {args {}} {results {{{port data1} {size 2}}}} {ready RDY_data1}} {method data2 data2 {clock no_clock} {reset no_reset} {args {}} {results {{{port data2} {size 4}}}} {ready RDY_data2}} {method data3 data3 {clock no_clock} {reset no_reset} {args {}} {results {{{port data3} {size 8}}}} {ready RDY_data3}} {interface clks1 {{interface 0 {{clock {} clks1_0 {osc CLK_clks1_0} {gate CLK_GATE_clks1_0}}}} {interface 1 {{clock {} clks1_1 {osc CLK_clks1_1} {gate CLK_GATE_clks1_1}}}}}} {interface rsts1 {{interface 0 {{reset {} rsts1_0 {port RST_N_rsts1_0} {clock default_clock}}}} {interface 1 {{reset {} rsts1_1 {port RST_N_rsts1_1} {clock default_clock}}}}}} {interface ios1 {{interface 0 {{inout {} ios1_0 {port ios1_0} {clock clks1_1} {reset rsts1_1}}}} {interface 1 {{inout {} ios1_1 {port ios1_1} {clock clks1_1} {reset rsts1_1}}}}}}} args {{inout io {port io} {clock default_clock} {reset default_reset} {size 2}} {clock default_clock {osc CLK}} {reset default_reset {port RST_N} {clock default_clock}}} --------- ---------- diff --git a/testsuite/bsc.bluetcl/commands/submodule.tcl.bluetcl-bh-out.expected b/testsuite/bsc.bluetcl/commands/submodule.tcl.bluetcl-bh-out.expected index 6f89b6109..fb719aa49 100644 --- a/testsuite/bsc.bluetcl/commands/submodule.tcl.bluetcl-bh-out.expected +++ b/testsuite/bsc.bluetcl/commands/submodule.tcl.bluetcl-bh-out.expected @@ -11,6 +11,7 @@ Command: submodule ports mkT clock default_clock reset default_reset args {{{port _write_1} {size 1}}} + results {} enable EN__write ready RDY__write method @@ -19,7 +20,7 @@ Command: submodule ports mkT clock default_clock reset default_reset args {} - result _read + results {{{port _read} {size 1}}} ready RDY__read args clock default_clock {osc CLK} @@ -36,6 +37,7 @@ Command: submodule ports mkT clock default_clock reset default_reset args {{{port _write_1} {size 1}}} + results {} enable EN__write ready RDY__write method @@ -44,7 +46,7 @@ Command: submodule ports mkT clock default_clock reset default_reset args {} - result _read + results {{{port _read} {size 1}}} ready RDY__read args clock default_clock {osc CLK} @@ -77,6 +79,7 @@ Command: submodule ports mkT clock clk reset rst args {{{port WVAL} {size 4}}} + results {} enable WSET method wget @@ -84,14 +87,14 @@ Command: submodule ports mkT clock clk reset rst args {} - result WGET + results {{{port WGET} {size 4}}} method whas whas clock clk reset rst args {} - result WHAS + results {{{port WHAS} {size 1}}} inout io_out io_out @@ -122,6 +125,7 @@ Command: submodule ports mkT clock clks1_1 reset no_reset args {{{port vec1_0__write_1} {size 1}}} + results {} enable EN_vec1_0__write ready RDY_vec1_0__write method @@ -130,7 +134,7 @@ Command: submodule ports mkT clock no_clock reset no_reset args {} - result vec1_0__read + results {{{port vec1_0__read} {size 1}}} ready RDY_vec1_0__read interface 1 @@ -140,6 +144,7 @@ Command: submodule ports mkT clock clks1_1 reset no_reset args {{{port vec1_1__write_1} {size 1}}} + results {} enable EN_vec1_1__write ready RDY_vec1_1__write method @@ -148,7 +153,7 @@ Command: submodule ports mkT clock no_clock reset no_reset args {} - result vec1_1__read + results {{{port vec1_1__read} {size 1}}} ready RDY_vec1_1__read interface vec2 @@ -162,6 +167,7 @@ Command: submodule ports mkT clock clks1_1 reset no_reset args {{{port vec2_0_0__write_1} {size 1}}} + results {} enable EN_vec2_0_0__write ready RDY_vec2_0_0__write method @@ -170,7 +176,7 @@ Command: submodule ports mkT clock no_clock reset no_reset args {} - result vec2_0_0__read + results {{{port vec2_0_0__read} {size 1}}} ready RDY_vec2_0_0__read interface 1 @@ -180,6 +186,7 @@ Command: submodule ports mkT clock clks1_1 reset no_reset args {{{port vec2_0_1__write_1} {size 1}}} + results {} enable EN_vec2_0_1__write ready RDY_vec2_0_1__write method @@ -188,7 +195,7 @@ Command: submodule ports mkT clock no_clock reset no_reset args {} - result vec2_0_1__read + results {{{port vec2_0_1__read} {size 1}}} ready RDY_vec2_0_1__read interface 1 @@ -200,6 +207,7 @@ Command: submodule ports mkT clock clks1_1 reset no_reset args {{{port vec2_1_0__write_1} {size 1}}} + results {} enable EN_vec2_1_0__write ready RDY_vec2_1_0__write method @@ -208,7 +216,7 @@ Command: submodule ports mkT clock no_clock reset no_reset args {} - result vec2_1_0__read + results {{{port vec2_1_0__read} {size 1}}} ready RDY_vec2_1_0__read interface 1 @@ -218,6 +226,7 @@ Command: submodule ports mkT clock clks1_1 reset no_reset args {{{port vec2_1_1__write_1} {size 1}}} + results {} enable EN_vec2_1_1__write ready RDY_vec2_1_1__write method @@ -226,7 +235,7 @@ Command: submodule ports mkT clock no_clock reset no_reset args {} - result vec2_1_1__read + results {{{port vec2_1_1__read} {size 1}}} ready RDY_vec2_1_1__read interface vec3 @@ -242,6 +251,7 @@ Command: submodule ports mkT clock clks1_1 reset no_reset args {{{port vec3_0_0_0__write_1} {size 1}}} + results {} enable EN_vec3_0_0_0__write ready RDY_vec3_0_0_0__write method @@ -250,7 +260,7 @@ Command: submodule ports mkT clock no_clock reset no_reset args {} - result vec3_0_0_0__read + results {{{port vec3_0_0_0__read} {size 1}}} ready RDY_vec3_0_0_0__read interface 1 @@ -260,6 +270,7 @@ Command: submodule ports mkT clock clks1_1 reset no_reset args {{{port vec3_0_0_1__write_1} {size 1}}} + results {} enable EN_vec3_0_0_1__write ready RDY_vec3_0_0_1__write method @@ -268,7 +279,7 @@ Command: submodule ports mkT clock no_clock reset no_reset args {} - result vec3_0_0_1__read + results {{{port vec3_0_0_1__read} {size 1}}} ready RDY_vec3_0_0_1__read interface 1 @@ -280,6 +291,7 @@ Command: submodule ports mkT clock clks1_1 reset no_reset args {{{port vec3_0_1_0__write_1} {size 1}}} + results {} enable EN_vec3_0_1_0__write ready RDY_vec3_0_1_0__write method @@ -288,7 +300,7 @@ Command: submodule ports mkT clock no_clock reset no_reset args {} - result vec3_0_1_0__read + results {{{port vec3_0_1_0__read} {size 1}}} ready RDY_vec3_0_1_0__read interface 1 @@ -298,6 +310,7 @@ Command: submodule ports mkT clock clks1_1 reset no_reset args {{{port vec3_0_1_1__write_1} {size 1}}} + results {} enable EN_vec3_0_1_1__write ready RDY_vec3_0_1_1__write method @@ -306,7 +319,7 @@ Command: submodule ports mkT clock no_clock reset no_reset args {} - result vec3_0_1_1__read + results {{{port vec3_0_1_1__read} {size 1}}} ready RDY_vec3_0_1_1__read interface 1 @@ -320,6 +333,7 @@ Command: submodule ports mkT clock clks1_1 reset no_reset args {{{port vec3_1_0_0__write_1} {size 1}}} + results {} enable EN_vec3_1_0_0__write ready RDY_vec3_1_0_0__write method @@ -328,7 +342,7 @@ Command: submodule ports mkT clock no_clock reset no_reset args {} - result vec3_1_0_0__read + results {{{port vec3_1_0_0__read} {size 1}}} ready RDY_vec3_1_0_0__read interface 1 @@ -338,6 +352,7 @@ Command: submodule ports mkT clock clks1_1 reset no_reset args {{{port vec3_1_0_1__write_1} {size 1}}} + results {} enable EN_vec3_1_0_1__write ready RDY_vec3_1_0_1__write method @@ -346,7 +361,7 @@ Command: submodule ports mkT clock no_clock reset no_reset args {} - result vec3_1_0_1__read + results {{{port vec3_1_0_1__read} {size 1}}} ready RDY_vec3_1_0_1__read interface 1 @@ -358,6 +373,7 @@ Command: submodule ports mkT clock clks1_1 reset no_reset args {{{port vec3_1_1_0__write_1} {size 1}}} + results {} enable EN_vec3_1_1_0__write ready RDY_vec3_1_1_0__write method @@ -366,7 +382,7 @@ Command: submodule ports mkT clock no_clock reset no_reset args {} - result vec3_1_1_0__read + results {{{port vec3_1_1_0__read} {size 1}}} ready RDY_vec3_1_1_0__read interface 1 @@ -376,6 +392,7 @@ Command: submodule ports mkT clock clks1_1 reset no_reset args {{{port vec3_1_1_1__write_1} {size 1}}} + results {} enable EN_vec3_1_1_1__write ready RDY_vec3_1_1_1__write method @@ -384,7 +401,7 @@ Command: submodule ports mkT clock no_clock reset no_reset args {} - result vec3_1_1_1__read + results {{{port vec3_1_1_1__read} {size 1}}} ready RDY_vec3_1_1_1__read method data1 @@ -392,7 +409,7 @@ Command: submodule ports mkT clock no_clock reset no_reset args {} - result data1 + results {{{port data1} {size 2}}} ready RDY_data1 method data2 @@ -400,7 +417,7 @@ Command: submodule ports mkT clock no_clock reset no_reset args {} - result data2 + results {{{port data2} {size 4}}} ready RDY_data2 method data3 @@ -408,7 +425,7 @@ Command: submodule ports mkT clock no_clock reset no_reset args {} - result data3 + results {{{port data3} {size 8}}} ready RDY_data3 interface clks1 @@ -458,6 +475,7 @@ Command: submodule ports mkM clock _clk__1 reset _rst__1 args {{{port D_IN} {size 1}}} + results {} enable EN method _read @@ -465,7 +483,7 @@ Command: submodule ports mkM clock _clk__1 reset _rst__1 args {} - result Q_OUT + results {{{port Q_OUT} {size 1}}} args clock _clk__1 {osc CLK} reset _rst__1 {port RST} {clock _clk__1} @@ -480,6 +498,7 @@ Command: submodule ports mkM clock _clk__1 reset _rst__1 args {{{port D_IN} {size 1}}} + results {} enable EN method _read @@ -487,7 +506,7 @@ Command: submodule ports mkM clock _clk__1 reset _rst__1 args {} - result Q_OUT + results {{{port Q_OUT} {size 1}}} args clock _clk__1 {osc CLK} reset _rst__1 {port RST} {clock _clk__1} @@ -502,6 +521,7 @@ Command: submodule ports mkM clock _clk__1 reset _rst__1 args {{{port D_IN} {size 1}}} + results {} enable EN method _read @@ -509,7 +529,7 @@ Command: submodule ports mkM clock _clk__1 reset _rst__1 args {} - result Q_OUT + results {{{port Q_OUT} {size 1}}} args clock _clk__1 {osc CLK} reset _rst__1 {port RST} {clock _clk__1} diff --git a/testsuite/bsc.bluetcl/commands/submodule.tcl.bluetcl-out.expected b/testsuite/bsc.bluetcl/commands/submodule.tcl.bluetcl-out.expected index aaf292aaf..926e03cde 100644 --- a/testsuite/bsc.bluetcl/commands/submodule.tcl.bluetcl-out.expected +++ b/testsuite/bsc.bluetcl/commands/submodule.tcl.bluetcl-out.expected @@ -11,6 +11,7 @@ Command: submodule ports mkT clock default_clock reset default_reset args {{{port _write_1} {size 1}}} + results {} enable EN__write ready RDY__write method @@ -19,7 +20,7 @@ Command: submodule ports mkT clock default_clock reset default_reset args {} - result _read + results {{{port _read} {size 1}}} ready RDY__read args clock default_clock {osc CLK} @@ -36,6 +37,7 @@ Command: submodule ports mkT clock default_clock reset default_reset args {{{port _write_1} {size 1}}} + results {} enable EN__write ready RDY__write method @@ -44,7 +46,7 @@ Command: submodule ports mkT clock default_clock reset default_reset args {} - result _read + results {{{port _read} {size 1}}} ready RDY__read args clock default_clock {osc CLK} @@ -77,6 +79,7 @@ Command: submodule ports mkT clock clk reset rst args {{{port WVAL} {size 4}}} + results {} enable WSET method wget @@ -84,14 +87,14 @@ Command: submodule ports mkT clock clk reset rst args {} - result WGET + results {{{port WGET} {size 4}}} method whas whas clock clk reset rst args {} - result WHAS + results {{{port WHAS} {size 1}}} inout io_out io_out @@ -122,6 +125,7 @@ Command: submodule ports mkT clock clks1_1 reset no_reset args {{{port vec1_0__write_1} {size 1}}} + results {} enable EN_vec1_0__write ready RDY_vec1_0__write method @@ -130,7 +134,7 @@ Command: submodule ports mkT clock no_clock reset no_reset args {} - result vec1_0__read + results {{{port vec1_0__read} {size 1}}} ready RDY_vec1_0__read interface 1 @@ -140,6 +144,7 @@ Command: submodule ports mkT clock clks1_1 reset no_reset args {{{port vec1_1__write_1} {size 1}}} + results {} enable EN_vec1_1__write ready RDY_vec1_1__write method @@ -148,7 +153,7 @@ Command: submodule ports mkT clock no_clock reset no_reset args {} - result vec1_1__read + results {{{port vec1_1__read} {size 1}}} ready RDY_vec1_1__read interface vec2 @@ -162,6 +167,7 @@ Command: submodule ports mkT clock clks1_1 reset no_reset args {{{port vec2_0_0__write_1} {size 1}}} + results {} enable EN_vec2_0_0__write ready RDY_vec2_0_0__write method @@ -170,7 +176,7 @@ Command: submodule ports mkT clock no_clock reset no_reset args {} - result vec2_0_0__read + results {{{port vec2_0_0__read} {size 1}}} ready RDY_vec2_0_0__read interface 1 @@ -180,6 +186,7 @@ Command: submodule ports mkT clock clks1_1 reset no_reset args {{{port vec2_0_1__write_1} {size 1}}} + results {} enable EN_vec2_0_1__write ready RDY_vec2_0_1__write method @@ -188,7 +195,7 @@ Command: submodule ports mkT clock no_clock reset no_reset args {} - result vec2_0_1__read + results {{{port vec2_0_1__read} {size 1}}} ready RDY_vec2_0_1__read interface 1 @@ -200,6 +207,7 @@ Command: submodule ports mkT clock clks1_1 reset no_reset args {{{port vec2_1_0__write_1} {size 1}}} + results {} enable EN_vec2_1_0__write ready RDY_vec2_1_0__write method @@ -208,7 +216,7 @@ Command: submodule ports mkT clock no_clock reset no_reset args {} - result vec2_1_0__read + results {{{port vec2_1_0__read} {size 1}}} ready RDY_vec2_1_0__read interface 1 @@ -218,6 +226,7 @@ Command: submodule ports mkT clock clks1_1 reset no_reset args {{{port vec2_1_1__write_1} {size 1}}} + results {} enable EN_vec2_1_1__write ready RDY_vec2_1_1__write method @@ -226,7 +235,7 @@ Command: submodule ports mkT clock no_clock reset no_reset args {} - result vec2_1_1__read + results {{{port vec2_1_1__read} {size 1}}} ready RDY_vec2_1_1__read interface vec3 @@ -242,6 +251,7 @@ Command: submodule ports mkT clock clks1_1 reset no_reset args {{{port vec3_0_0_0__write_1} {size 1}}} + results {} enable EN_vec3_0_0_0__write ready RDY_vec3_0_0_0__write method @@ -250,7 +260,7 @@ Command: submodule ports mkT clock no_clock reset no_reset args {} - result vec3_0_0_0__read + results {{{port vec3_0_0_0__read} {size 1}}} ready RDY_vec3_0_0_0__read interface 1 @@ -260,6 +270,7 @@ Command: submodule ports mkT clock clks1_1 reset no_reset args {{{port vec3_0_0_1__write_1} {size 1}}} + results {} enable EN_vec3_0_0_1__write ready RDY_vec3_0_0_1__write method @@ -268,7 +279,7 @@ Command: submodule ports mkT clock no_clock reset no_reset args {} - result vec3_0_0_1__read + results {{{port vec3_0_0_1__read} {size 1}}} ready RDY_vec3_0_0_1__read interface 1 @@ -280,6 +291,7 @@ Command: submodule ports mkT clock clks1_1 reset no_reset args {{{port vec3_0_1_0__write_1} {size 1}}} + results {} enable EN_vec3_0_1_0__write ready RDY_vec3_0_1_0__write method @@ -288,7 +300,7 @@ Command: submodule ports mkT clock no_clock reset no_reset args {} - result vec3_0_1_0__read + results {{{port vec3_0_1_0__read} {size 1}}} ready RDY_vec3_0_1_0__read interface 1 @@ -298,6 +310,7 @@ Command: submodule ports mkT clock clks1_1 reset no_reset args {{{port vec3_0_1_1__write_1} {size 1}}} + results {} enable EN_vec3_0_1_1__write ready RDY_vec3_0_1_1__write method @@ -306,7 +319,7 @@ Command: submodule ports mkT clock no_clock reset no_reset args {} - result vec3_0_1_1__read + results {{{port vec3_0_1_1__read} {size 1}}} ready RDY_vec3_0_1_1__read interface 1 @@ -320,6 +333,7 @@ Command: submodule ports mkT clock clks1_1 reset no_reset args {{{port vec3_1_0_0__write_1} {size 1}}} + results {} enable EN_vec3_1_0_0__write ready RDY_vec3_1_0_0__write method @@ -328,7 +342,7 @@ Command: submodule ports mkT clock no_clock reset no_reset args {} - result vec3_1_0_0__read + results {{{port vec3_1_0_0__read} {size 1}}} ready RDY_vec3_1_0_0__read interface 1 @@ -338,6 +352,7 @@ Command: submodule ports mkT clock clks1_1 reset no_reset args {{{port vec3_1_0_1__write_1} {size 1}}} + results {} enable EN_vec3_1_0_1__write ready RDY_vec3_1_0_1__write method @@ -346,7 +361,7 @@ Command: submodule ports mkT clock no_clock reset no_reset args {} - result vec3_1_0_1__read + results {{{port vec3_1_0_1__read} {size 1}}} ready RDY_vec3_1_0_1__read interface 1 @@ -358,6 +373,7 @@ Command: submodule ports mkT clock clks1_1 reset no_reset args {{{port vec3_1_1_0__write_1} {size 1}}} + results {} enable EN_vec3_1_1_0__write ready RDY_vec3_1_1_0__write method @@ -366,7 +382,7 @@ Command: submodule ports mkT clock no_clock reset no_reset args {} - result vec3_1_1_0__read + results {{{port vec3_1_1_0__read} {size 1}}} ready RDY_vec3_1_1_0__read interface 1 @@ -376,6 +392,7 @@ Command: submodule ports mkT clock clks1_1 reset no_reset args {{{port vec3_1_1_1__write_1} {size 1}}} + results {} enable EN_vec3_1_1_1__write ready RDY_vec3_1_1_1__write method @@ -384,7 +401,7 @@ Command: submodule ports mkT clock no_clock reset no_reset args {} - result vec3_1_1_1__read + results {{{port vec3_1_1_1__read} {size 1}}} ready RDY_vec3_1_1_1__read method data1 @@ -392,7 +409,7 @@ Command: submodule ports mkT clock no_clock reset no_reset args {} - result data1 + results {{{port data1} {size 2}}} ready RDY_data1 method data2 @@ -400,7 +417,7 @@ Command: submodule ports mkT clock no_clock reset no_reset args {} - result data2 + results {{{port data2} {size 4}}} ready RDY_data2 method data3 @@ -408,7 +425,7 @@ Command: submodule ports mkT clock no_clock reset no_reset args {} - result data3 + results {{{port data3} {size 8}}} ready RDY_data3 interface clks1 @@ -458,6 +475,7 @@ Command: submodule ports mkM clock _clk__1 reset _rst__1 args {{{port D_IN} {size 1}}} + results {} enable EN method _read @@ -465,7 +483,7 @@ Command: submodule ports mkM clock _clk__1 reset _rst__1 args {} - result Q_OUT + results {{{port Q_OUT} {size 1}}} args clock _clk__1 {osc CLK} reset _rst__1 {port RST} {clock _clk__1} @@ -480,6 +498,7 @@ Command: submodule ports mkM clock _clk__1 reset _rst__1 args {{{port D_IN} {size 1}}} + results {} enable EN method _read @@ -487,7 +506,7 @@ Command: submodule ports mkM clock _clk__1 reset _rst__1 args {} - result Q_OUT + results {{{port Q_OUT} {size 1}}} args clock _clk__1 {osc CLK} reset _rst__1 {port RST} {clock _clk__1} @@ -502,6 +521,7 @@ Command: submodule ports mkM clock _clk__1 reset _rst__1 args {{{port D_IN} {size 1}}} + results {} enable EN method _read @@ -509,7 +529,7 @@ Command: submodule ports mkM clock _clk__1 reset _rst__1 args {} - result Q_OUT + results {{{port Q_OUT} {size 1}}} args clock _clk__1 {osc CLK} reset _rst__1 {port RST} {clock _clk__1} diff --git a/testsuite/bsc.bluetcl/targeted/port_types/SplitPortTypes.bs b/testsuite/bsc.bluetcl/targeted/port_types/SplitPortTypes.bs new file mode 100644 index 000000000..5fec7e02f --- /dev/null +++ b/testsuite/bsc.bluetcl/targeted/port_types/SplitPortTypes.bs @@ -0,0 +1,60 @@ +package SplitPortTypes where + +-- Test that port types are reported correctly all the way through to Bluetcl +-- ("module porttypes" / "module ports") when a method's arguments and/or +-- result are split into multiple input/output ports (deep and shallow). + +import SplitPorts + +struct Inner = + a :: Bool + b :: Int 16 + deriving (Bits) + +struct Outer = + x :: UInt 8 + y :: Inner + z :: Bit 4 + deriving (Bits) + +interface SplitPortTypes = + -- ---- split OUTPUT ports ---- + -- value method, result deep-split: one port per leaf field + -- (x :: UInt 8, y.a :: Bool, y.b :: Int 16, z :: Bit 4) + getDeep :: DeepSplit Outer + -- value method, result shallow-split: Inner stays packed + -- (x :: UInt 8, y :: Inner, z :: Bit 4) + getShallow :: ShallowSplit Outer + -- ActionValue method whose value is deep-split into multiple output ports + nextDeep :: ActionValue (DeepSplit Outer) + + -- ---- split INPUT ports ---- + -- one argument deep-split into multiple input ports + putDeep :: DeepSplit Outer -> Action + -- one argument shallow-split into input ports (Inner stays packed) + putShallow :: ShallowSplit Outer -> Action + -- two deep-split arguments, named via the arg_names pragma + combineDeep :: DeepSplit Outer -> DeepSplit Outer -> Action + {-# arg_names = ["lhs", "rhs"] #-} + + -- ---- split INPUT and OUTPUT together ---- + -- value method whose argument and result are both deep-split + transform :: DeepSplit Outer -> DeepSplit Outer + +{-# synthesize mkSplitPortTypes #-} +mkSplitPortTypes :: Module SplitPortTypes +mkSplitPortTypes = + module + r :: Reg (UInt 8) <- mkReg 0 + let mkOuter v = Outer { x = v; y = Inner { a = v == 0; b = 7 }; z = 3 } + interface + getDeep = DeepSplit (mkOuter r) + getShallow = ShallowSplit (mkOuter r) + nextDeep = do + r := r + 1 + return (DeepSplit (mkOuter r)) + putDeep (DeepSplit o) = r := o.x + putShallow (ShallowSplit o) = r := o.x + combineDeep (DeepSplit lhs) (DeepSplit rhs) = r := lhs.x + rhs.x + transform (DeepSplit o) = + DeepSplit (Outer { x = o.x + 1; y = o.y; z = o.z }) diff --git a/testsuite/bsc.bluetcl/targeted/port_types/inhigh.tcl.bluetcl-bh-out.expected b/testsuite/bsc.bluetcl/targeted/port_types/inhigh.tcl.bluetcl-bh-out.expected index f7972c0b8..dadadf149 100644 --- a/testsuite/bsc.bluetcl/targeted/port_types/inhigh.tcl.bluetcl-bh-out.expected +++ b/testsuite/bsc.bluetcl/targeted/port_types/inhigh.tcl.bluetcl-bh-out.expected @@ -1,11 +1,11 @@ -verilog mkInhighEnable_Sub sysInhighEnable ---------- -{rg1 MOD {interface {{method _write _write {clock _clk__1} {reset _rst__1} {args {{{port Q_IN} {size 1}}}}} {method _read _read {clock _clk__1} {reset _rst__1} {args {}} {result D_OUT}}}} {args {{reset _rst__1 {port RST} {clock _clk__1}} {clock _clk__1 {osc CLK} {gate CLK_GATE}}}}} {rg2 mkInhighEnable_Sub {interface {{method _write _write {clock default_clock} {reset no_reset} {args {{{port _write_1} {size 1}}}}} {method _read _read {clock default_clock} {reset no_reset} {args {}} {result _read}}}} {args {{clock default_clock {osc CLK}} {reset default_reset {port RST_N} {clock default_clock}}}}} +{rg1 MOD {interface {{method _write _write {clock _clk__1} {reset _rst__1} {args {{{port Q_IN} {size 1}}}} {results {}}} {method _read _read {clock _clk__1} {reset _rst__1} {args {}} {results {{{port D_OUT} {size 1}}}}}}} {args {{reset _rst__1 {port RST} {clock _clk__1}} {clock _clk__1 {osc CLK} {gate CLK_GATE}}}}} {rg2 mkInhighEnable_Sub {interface {{method _write _write {clock default_clock} {reset no_reset} {args {{{port _write_1} {size 1}}}} {results {}}} {method _read _read {clock default_clock} {reset no_reset} {args {}} {results {{{port _read} {size 1}}}}}}} {args {{clock default_clock {osc CLK}} {reset default_reset {port RST_N} {clock default_clock}}}}} {rg1 MOD {ports {{RST Prelude.Reset} {CLK Prelude.Clock} {CLK_GATE Prelude.Bool} {Q_IN Prelude.Bool} {D_OUT Prelude.Bool}}}} {rg2 mkInhighEnable_Sub {ports {{CLK Prelude.Clock} {RST_N Prelude.Reset} {_write_1 Prelude.Bool} {_read Prelude.Bool}}}} ---------- -{interface {{method _write _write {clock default_clock} {reset no_reset} {args {{{name _write_1} {port _write_1} {size 1}}}}} {method _read _read {clock default_clock} {reset no_reset} {args {}} {result _read}}}} {args {{clock default_clock {osc CLK}} {reset default_reset {port RST_N} {clock default_clock}}}} +{interface {{method _write _write {clock default_clock} {reset no_reset} {args {{{name _write_1} {port _write_1} {size 1}}}} {results {}}} {method _read _read {clock default_clock} {reset no_reset} {args {}} {results {{{port _read} {size 1}}}}}}} {args {{clock default_clock {osc CLK}} {reset default_reset {port RST_N} {clock default_clock}}}} {CLK Prelude.Clock} {RST_N Prelude.Reset} {_write_1 Prelude.Bool} {_read Prelude.Bool} ---------- diff --git a/testsuite/bsc.bluetcl/targeted/port_types/inhigh.tcl.bluetcl-out.expected b/testsuite/bsc.bluetcl/targeted/port_types/inhigh.tcl.bluetcl-out.expected index 1bf3c6e11..127dc8996 100644 --- a/testsuite/bsc.bluetcl/targeted/port_types/inhigh.tcl.bluetcl-out.expected +++ b/testsuite/bsc.bluetcl/targeted/port_types/inhigh.tcl.bluetcl-out.expected @@ -1,11 +1,11 @@ -verilog mkInhighEnable_Sub sysInhighEnable ---------- -{rg1 MOD {interface {{method _write _write {clock _clk__1} {reset _rst__1} {args {{{port Q_IN} {size 1}}}}} {method _read _read {clock _clk__1} {reset _rst__1} {args {}} {result D_OUT}}}} {args {{reset _rst__1 {port RST} {clock _clk__1}} {clock _clk__1 {osc CLK} {gate CLK_GATE}}}}} {rg2 mkInhighEnable_Sub {interface {{method _write _write {clock default_clock} {reset no_reset} {args {{{port _write_1} {size 1}}}}} {method _read _read {clock default_clock} {reset no_reset} {args {}} {result _read}}}} {args {{clock default_clock {osc CLK}} {reset default_reset {port RST_N} {clock default_clock}}}}} +{rg1 MOD {interface {{method _write _write {clock _clk__1} {reset _rst__1} {args {{{port Q_IN} {size 1}}}} {results {}}} {method _read _read {clock _clk__1} {reset _rst__1} {args {}} {results {{{port D_OUT} {size 1}}}}}}} {args {{reset _rst__1 {port RST} {clock _clk__1}} {clock _clk__1 {osc CLK} {gate CLK_GATE}}}}} {rg2 mkInhighEnable_Sub {interface {{method _write _write {clock default_clock} {reset no_reset} {args {{{port _write_1} {size 1}}}} {results {}}} {method _read _read {clock default_clock} {reset no_reset} {args {}} {results {{{port _read} {size 1}}}}}}} {args {{clock default_clock {osc CLK}} {reset default_reset {port RST_N} {clock default_clock}}}}} {rg1 MOD {ports {{RST Reset} {CLK Clock} {CLK_GATE Bool} {Q_IN Bool} {D_OUT Bool}}}} {rg2 mkInhighEnable_Sub {ports {{CLK Clock} {RST_N Reset} {_write_1 Bool} {_read Bool}}}} ---------- -{interface {{method _write _write {clock default_clock} {reset no_reset} {args {{{name _write_1} {port _write_1} {size 1}}}}} {method _read _read {clock default_clock} {reset no_reset} {args {}} {result _read}}}} {args {{clock default_clock {osc CLK}} {reset default_reset {port RST_N} {clock default_clock}}}} +{interface {{method _write _write {clock default_clock} {reset no_reset} {args {{{name _write_1} {port _write_1} {size 1}}}} {results {}}} {method _read _read {clock default_clock} {reset no_reset} {args {}} {results {{{port _read} {size 1}}}}}}} {args {{clock default_clock {osc CLK}} {reset default_reset {port RST_N} {clock default_clock}}}} {CLK Clock} {RST_N Reset} {_write_1 Bool} {_read Bool} ---------- diff --git a/testsuite/bsc.bluetcl/targeted/port_types/port_types.exp b/testsuite/bsc.bluetcl/targeted/port_types/port_types.exp index 2781faf0b..0b029117c 100644 --- a/testsuite/bsc.bluetcl/targeted/port_types/port_types.exp +++ b/testsuite/bsc.bluetcl/targeted/port_types/port_types.exp @@ -19,3 +19,11 @@ bsc_compile Prims.bsv {-verilog -elab} bluetcl_run_compare_pass prims.tcl "" "" # --------------- +# Test that port types are reported correctly for methods whose arguments +# and/or result are split into multiple input/output ports (deep/shallow, +# value and ActionValue) + +bsc_compile SplitPortTypes.bs {-verilog -elab} +bluetcl_run_compare_pass split_port_types.tcl + +# --------------- diff --git a/testsuite/bsc.bluetcl/targeted/port_types/prims.tcl.bluetcl-bh-out.expected b/testsuite/bsc.bluetcl/targeted/port_types/prims.tcl.bluetcl-bh-out.expected index 547da936a..59b75dd63 100644 --- a/testsuite/bsc.bluetcl/targeted/port_types/prims.tcl.bluetcl-bh-out.expected +++ b/testsuite/bsc.bluetcl/targeted/port_types/prims.tcl.bluetcl-bh-out.expected @@ -1,75 +1,75 @@ -verilog sysPrims ---------- -rg RegN {interface {{method _write _write {clock _clk__1} {reset _rst__1} {args {{{port D_IN} {size 32}}}} {enable EN}} {method _read _read {clock _clk__1} {reset _rst__1} {args {}} {result Q_OUT}}}} {args {{clock _clk__1 {osc CLK}} {reset _rst__1 {port RST} {clock _clk__1}} {parameter width {param width}} {parameter init {param init}}}} +rg RegN {interface {{method _write _write {clock _clk__1} {reset _rst__1} {args {{{port D_IN} {size 32}}}} {results {}} {enable EN}} {method _read _read {clock _clk__1} {reset _rst__1} {args {}} {results {{{port Q_OUT} {size 32}}}}}}} {args {{clock _clk__1 {osc CLK}} {reset _rst__1 {port RST} {clock _clk__1}} {parameter width {param width}} {parameter init {param init}}}} rg RegN {ports {{CLK Prelude.Clock} {RST Prelude.Reset} {D_IN {Prelude.Int 32}} {EN Prelude.Bool} {Q_OUT {Prelude.Int 32}}}} ---------- -rgA RegA {interface {{method _write _write {clock _clk__1} {reset _rst__1} {args {{{port D_IN} {size 32}}}} {enable EN}} {method _read _read {clock _clk__1} {reset _rst__1} {args {}} {result Q_OUT}}}} {args {{clock _clk__1 {osc CLK}} {reset _rst__1 {port RST} {clock _clk__1}} {parameter width {param width}} {parameter init {param init}}}} +rgA RegA {interface {{method _write _write {clock _clk__1} {reset _rst__1} {args {{{port D_IN} {size 32}}}} {results {}} {enable EN}} {method _read _read {clock _clk__1} {reset _rst__1} {args {}} {results {{{port Q_OUT} {size 32}}}}}}} {args {{clock _clk__1 {osc CLK}} {reset _rst__1 {port RST} {clock _clk__1}} {parameter width {param width}} {parameter init {param init}}}} rgA RegA {ports {{CLK Prelude.Clock} {RST Prelude.Reset} {D_IN {Prelude.Int 32}} {EN Prelude.Bool} {Q_OUT {Prelude.Int 32}}}} ---------- -rgU RegUN {interface {{method _write _write {clock _clk__1} {reset no_reset} {args {{{port D_IN} {size 32}}}} {enable EN}} {method _read _read {clock _clk__1} {reset no_reset} {args {}} {result Q_OUT}}}} {args {{clock _clk__1 {osc CLK}} {parameter width {param width}}}} +rgU RegUN {interface {{method _write _write {clock _clk__1} {reset no_reset} {args {{{port D_IN} {size 32}}}} {results {}} {enable EN}} {method _read _read {clock _clk__1} {reset no_reset} {args {}} {results {{{port Q_OUT} {size 32}}}}}}} {args {{clock _clk__1 {osc CLK}} {parameter width {param width}}}} rgU RegUN {ports {{CLK Prelude.Clock} {D_IN {Prelude.Int 32}} {EN Prelude.Bool} {Q_OUT {Prelude.Int 32}}}} ---------- -rw RWire {interface {{method wset wset {clock clk} {reset rst} {args {{{port WVAL} {size 32}}}} {enable WSET}} {method wget wget {clock clk} {reset rst} {args {}} {result WGET} {ready WHAS}}}} {args {{parameter width {param width}} {clock clk} {reset rst {clock clk}}}} +rw RWire {interface {{method wset wset {clock clk} {reset rst} {args {{{port WVAL} {size 32}}}} {results {}} {enable WSET}} {method wget wget {clock clk} {reset rst} {args {}} {results {{{port WGET} {size 32}}}} {ready WHAS}}}} {args {{parameter width {param width}} {clock clk} {reset rst {clock clk}}}} rw RWire {ports {{WVAL {Prelude.Int 32}} {WSET Prelude.Bool} {WGET {Prelude.Int 32}} {WHAS Prelude.Bool}}} ---------- -rw0 RWire0 {interface {{method wset wset {clock clk} {reset rst} {args {}} {enable WSET}} {method wget wget {clock clk} {reset rst} {args {}} {ready WHAS}}}} {args {{clock clk} {reset rst {clock clk}}}} +rw0 RWire0 {interface {{method wset wset {clock clk} {reset rst} {args {}} {results {}} {enable WSET}} {method wget wget {clock clk} {reset rst} {args {}} {results {}} {ready WHAS}}}} {args {{clock clk} {reset rst {clock clk}}}} rw0 RWire0 {ports {{WSET Prelude.Bool} {WHAS Prelude.Bool}}} ---------- -w RWire {interface {{method _write _write {clock clk} {reset rst} {args {{{port WVAL} {size 32}}}} {enable WSET}} {method _read _read {clock clk} {reset rst} {args {}} {result WGET} {ready WHAS}}}} {args {{parameter width {param width}} {clock clk} {reset rst {clock clk}}}} +w RWire {interface {{method _write _write {clock clk} {reset rst} {args {{{port WVAL} {size 32}}}} {results {}} {enable WSET}} {method _read _read {clock clk} {reset rst} {args {}} {results {{{port WGET} {size 32}}}} {ready WHAS}}}} {args {{parameter width {param width}} {clock clk} {reset rst {clock clk}}}} w RWire {ports {{WVAL {Prelude.Int 32}} {WSET Prelude.Bool} {WGET {Prelude.Int 32}} {WHAS Prelude.Bool}}} ---------- -dw RWire {interface {{method _write _write {clock clk} {reset rst} {args {{{port WVAL} {size 32}}}} {enable WSET}} {method _read _read {clock clk} {reset rst} {args {}} {result WGET} {ready WHAS}}}} {args {{parameter width {param width}} {clock clk} {reset rst {clock clk}}}} +dw RWire {interface {{method _write _write {clock clk} {reset rst} {args {{{port WVAL} {size 32}}}} {results {}} {enable WSET}} {method _read _read {clock clk} {reset rst} {args {}} {results {{{port WGET} {size 32}}}} {ready WHAS}}}} {args {{parameter width {param width}} {clock clk} {reset rst {clock clk}}}} dw RWire {ports {{WVAL {Prelude.Int 32}} {WSET Prelude.Bool} {WGET {Prelude.Int 32}} {WHAS Prelude.Bool}}} ---------- -bw BypassWire {interface {{method _write _write {clock clk} {reset rst} {args {{{port WVAL} {size 32}}}}} {method _read _read {clock clk} {reset rst} {args {}} {result WGET}}}} {args {{parameter width {param width}} {clock clk} {reset rst {clock clk}}}} +bw BypassWire {interface {{method _write _write {clock clk} {reset rst} {args {{{port WVAL} {size 32}}}} {results {}}} {method _read _read {clock clk} {reset rst} {args {}} {results {{{port WGET} {size 32}}}}}}} {args {{parameter width {param width}} {clock clk} {reset rst {clock clk}}}} bw BypassWire {ports {{WVAL {Prelude.Int 32}} {WGET {Prelude.Int 32}}}} ---------- -pw RWire0 {interface {{method send send {clock clk} {reset rst} {args {}} {enable WSET}} {method _read _read {clock clk} {reset rst} {args {}} {result WHAS}}}} {args {{clock clk} {reset rst {clock clk}}}} +pw RWire0 {interface {{method send send {clock clk} {reset rst} {args {}} {results {}} {enable WSET}} {method _read _read {clock clk} {reset rst} {args {}} {results {{{port WHAS} {size 1}}}}}}} {args {{clock clk} {reset rst {clock clk}}}} pw RWire0 {ports {{WSET Prelude.Bool} {WHAS Prelude.Bool}}} ---------- -pwo RWire0 {interface {{method send send {clock clk} {reset rst} {args {}} {enable WSET}} {method _read _read {clock clk} {reset rst} {args {}} {result WHAS}}}} {args {{clock clk} {reset rst {clock clk}}}} +pwo RWire0 {interface {{method send send {clock clk} {reset rst} {args {}} {results {}} {enable WSET}} {method _read _read {clock clk} {reset rst} {args {}} {results {{{port WHAS} {size 1}}}}}}} {args {{clock clk} {reset rst {clock clk}}}} pwo RWire0 {ports {{WSET Prelude.Bool} {WHAS Prelude.Bool}}} ---------- -rf RegFile {interface {{method upd upd {clock _clk__1} {reset no_reset} {args {{{port ADDR_IN} {size 2}} {{port D_IN} {size 32}}}} {enable WE}} {method sub_1 sub_1 {clock _clk__1} {reset no_reset} {args {{{port ADDR_1} {size 2}}}} {result D_OUT_1}} {method sub_2 sub_2 {clock _clk__1} {reset no_reset} {args {{{port ADDR_2} {size 2}}}} {result D_OUT_2}} {method sub_3 sub_3 {clock _clk__1} {reset no_reset} {args {{{port ADDR_3} {size 2}}}} {result D_OUT_3}} {method sub_4 sub_4 {clock _clk__1} {reset no_reset} {args {{{port ADDR_4} {size 2}}}} {result D_OUT_4}} {method sub_5 sub_5 {clock _clk__1} {reset no_reset} {args {{{port ADDR_5} {size 2}}}} {result D_OUT_5}}}} {args {{clock _clk__1 {osc CLK}} {parameter addr_width {param addr_width}} {parameter data_width {param data_width}} {parameter lo {param lo}} {parameter hi {param hi}}}} +rf RegFile {interface {{method upd upd {clock _clk__1} {reset no_reset} {args {{{port ADDR_IN} {size 2}} {{port D_IN} {size 32}}}} {results {}} {enable WE}} {method sub_1 sub_1 {clock _clk__1} {reset no_reset} {args {{{port ADDR_1} {size 2}}}} {results {{{port D_OUT_1} {size 32}}}}} {method sub_2 sub_2 {clock _clk__1} {reset no_reset} {args {{{port ADDR_2} {size 2}}}} {results {{{port D_OUT_2} {size 32}}}}} {method sub_3 sub_3 {clock _clk__1} {reset no_reset} {args {{{port ADDR_3} {size 2}}}} {results {{{port D_OUT_3} {size 32}}}}} {method sub_4 sub_4 {clock _clk__1} {reset no_reset} {args {{{port ADDR_4} {size 2}}}} {results {{{port D_OUT_4} {size 32}}}}} {method sub_5 sub_5 {clock _clk__1} {reset no_reset} {args {{{port ADDR_5} {size 2}}}} {results {{{port D_OUT_5} {size 32}}}}}}} {args {{clock _clk__1 {osc CLK}} {parameter addr_width {param addr_width}} {parameter data_width {param data_width}} {parameter lo {param lo}} {parameter hi {param hi}}}} rf RegFile {ports {{CLK Prelude.Clock} {ADDR_IN {Prelude.Bit 2}} {D_IN {Prelude.Int 32}} {WE Prelude.Bool} {ADDR_1 {Prelude.Bit 2}} {D_OUT_1 {Prelude.Int 32}} {ADDR_2 {Prelude.Bit 2}} {D_OUT_2 {Prelude.Int 32}} {ADDR_3 {Prelude.Bit 2}} {D_OUT_3 {Prelude.Int 32}} {ADDR_4 {Prelude.Bit 2}} {D_OUT_4 {Prelude.Int 32}} {ADDR_5 {Prelude.Bit 2}} {D_OUT_5 {Prelude.Int 32}}}} ---------- -ff1 FIFO2 {interface {{method enq enq {clock clk} {reset _rst__1} {args {{{port D_IN} {size 32}}}} {enable ENQ} {ready FULL_N}} {method deq deq {clock clk} {reset _rst__1} {args {}} {enable DEQ} {ready EMPTY_N}} {method first first {clock clk} {reset _rst__1} {args {}} {result D_OUT} {ready EMPTY_N}} {method notFull notFull {clock clk} {reset _rst__1} {args {}} {result FULL_N}} {method notEmpty notEmpty {clock clk} {reset _rst__1} {args {}} {result EMPTY_N}} {method clear clear {clock clk} {reset _rst__1} {args {}} {enable CLR}}}} {args {{reset _rst__1 {port RST} {clock clk}} {clock clk {osc CLK}} {parameter width {param width}} {parameter guarded {param guarded}}}} +ff1 FIFO2 {interface {{method enq enq {clock clk} {reset _rst__1} {args {{{port D_IN} {size 32}}}} {results {}} {enable ENQ} {ready FULL_N}} {method deq deq {clock clk} {reset _rst__1} {args {}} {results {}} {enable DEQ} {ready EMPTY_N}} {method first first {clock clk} {reset _rst__1} {args {}} {results {{{port D_OUT} {size 32}}}} {ready EMPTY_N}} {method notFull notFull {clock clk} {reset _rst__1} {args {}} {results {{{port FULL_N} {size 1}}}}} {method notEmpty notEmpty {clock clk} {reset _rst__1} {args {}} {results {{{port EMPTY_N} {size 1}}}}} {method clear clear {clock clk} {reset _rst__1} {args {}} {results {}} {enable CLR}}}} {args {{reset _rst__1 {port RST} {clock clk}} {clock clk {osc CLK}} {parameter width {param width}} {parameter guarded {param guarded}}}} ff1 FIFO2 {ports {{RST Prelude.Reset} {CLK Prelude.Clock} {D_IN {Prelude.Int 32}} {ENQ Prelude.Bool} {FULL_N Prelude.Bool} {DEQ Prelude.Bool} {EMPTY_N Prelude.Bool} {D_OUT {Prelude.Int 32}} {CLR Prelude.Bool}}} ---------- -f1 FIFO1 {interface {{method enq enq {clock clk} {reset _rst__1} {args {{{port D_IN} {size 32}}}} {enable ENQ} {ready FULL_N}} {method deq deq {clock clk} {reset _rst__1} {args {}} {enable DEQ} {ready EMPTY_N}} {method first first {clock clk} {reset _rst__1} {args {}} {result D_OUT} {ready EMPTY_N}} {method clear clear {clock clk} {reset _rst__1} {args {}} {enable CLR}}}} {args {{reset _rst__1 {port RST} {clock clk}} {clock clk {osc CLK}} {parameter width {param width}} {parameter guarded {param guarded}}}} +f1 FIFO1 {interface {{method enq enq {clock clk} {reset _rst__1} {args {{{port D_IN} {size 32}}}} {results {}} {enable ENQ} {ready FULL_N}} {method deq deq {clock clk} {reset _rst__1} {args {}} {results {}} {enable DEQ} {ready EMPTY_N}} {method first first {clock clk} {reset _rst__1} {args {}} {results {{{port D_OUT} {size 32}}}} {ready EMPTY_N}} {method clear clear {clock clk} {reset _rst__1} {args {}} {results {}} {enable CLR}}}} {args {{reset _rst__1 {port RST} {clock clk}} {clock clk {osc CLK}} {parameter width {param width}} {parameter guarded {param guarded}}}} f1 FIFO1 {ports {{RST Prelude.Reset} {CLK Prelude.Clock} {D_IN {Prelude.Int 32}} {ENQ Prelude.Bool} {FULL_N Prelude.Bool} {DEQ Prelude.Bool} {EMPTY_N Prelude.Bool} {D_OUT {Prelude.Int 32}} {CLR Prelude.Bool}}} ---------- -f10 FIFO10 {interface {{method enq enq {clock clk} {reset _rst__1} {args {}} {enable ENQ} {ready FULL_N}} {method deq deq {clock clk} {reset _rst__1} {args {}} {enable DEQ} {ready EMPTY_N}} {method first first {clock clk} {reset _rst__1} {args {}} {ready EMPTY_N}} {method clear clear {clock clk} {reset _rst__1} {args {}} {enable CLR}}}} {args {{reset _rst__1 {port RST} {clock clk}} {clock clk {osc CLK}} {parameter guarded {param guarded}}}} +f10 FIFO10 {interface {{method enq enq {clock clk} {reset _rst__1} {args {}} {results {}} {enable ENQ} {ready FULL_N}} {method deq deq {clock clk} {reset _rst__1} {args {}} {results {}} {enable DEQ} {ready EMPTY_N}} {method first first {clock clk} {reset _rst__1} {args {}} {results {}} {ready EMPTY_N}} {method clear clear {clock clk} {reset _rst__1} {args {}} {results {}} {enable CLR}}}} {args {{reset _rst__1 {port RST} {clock clk}} {clock clk {osc CLK}} {parameter guarded {param guarded}}}} f10 FIFO10 {ports {{RST Prelude.Reset} {CLK Prelude.Clock} {ENQ Prelude.Bool} {FULL_N Prelude.Bool} {DEQ Prelude.Bool} {EMPTY_N Prelude.Bool} {CLR Prelude.Bool}}} ---------- -f2 FIFO2 {interface {{method enq enq {clock clk} {reset _rst__1} {args {{{port D_IN} {size 32}}}} {enable ENQ} {ready FULL_N}} {method deq deq {clock clk} {reset _rst__1} {args {}} {enable DEQ} {ready EMPTY_N}} {method first first {clock clk} {reset _rst__1} {args {}} {result D_OUT} {ready EMPTY_N}} {method clear clear {clock clk} {reset _rst__1} {args {}} {enable CLR}}}} {args {{reset _rst__1 {port RST} {clock clk}} {clock clk {osc CLK}} {parameter width {param width}} {parameter guarded {param guarded}}}} +f2 FIFO2 {interface {{method enq enq {clock clk} {reset _rst__1} {args {{{port D_IN} {size 32}}}} {results {}} {enable ENQ} {ready FULL_N}} {method deq deq {clock clk} {reset _rst__1} {args {}} {results {}} {enable DEQ} {ready EMPTY_N}} {method first first {clock clk} {reset _rst__1} {args {}} {results {{{port D_OUT} {size 32}}}} {ready EMPTY_N}} {method clear clear {clock clk} {reset _rst__1} {args {}} {results {}} {enable CLR}}}} {args {{reset _rst__1 {port RST} {clock clk}} {clock clk {osc CLK}} {parameter width {param width}} {parameter guarded {param guarded}}}} f2 FIFO2 {ports {{RST Prelude.Reset} {CLK Prelude.Clock} {D_IN {Prelude.Int 32}} {ENQ Prelude.Bool} {FULL_N Prelude.Bool} {DEQ Prelude.Bool} {EMPTY_N Prelude.Bool} {D_OUT {Prelude.Int 32}} {CLR Prelude.Bool}}} ---------- -f20 FIFO20 {interface {{method enq enq {clock clk} {reset _rst__1} {args {}} {enable ENQ} {ready FULL_N}} {method deq deq {clock clk} {reset _rst__1} {args {}} {enable DEQ} {ready EMPTY_N}} {method first first {clock clk} {reset _rst__1} {args {}} {ready EMPTY_N}} {method clear clear {clock clk} {reset _rst__1} {args {}} {enable CLR}}}} {args {{reset _rst__1 {port RST} {clock clk}} {clock clk {osc CLK}} {parameter guarded {param guarded}}}} +f20 FIFO20 {interface {{method enq enq {clock clk} {reset _rst__1} {args {}} {results {}} {enable ENQ} {ready FULL_N}} {method deq deq {clock clk} {reset _rst__1} {args {}} {results {}} {enable DEQ} {ready EMPTY_N}} {method first first {clock clk} {reset _rst__1} {args {}} {results {}} {ready EMPTY_N}} {method clear clear {clock clk} {reset _rst__1} {args {}} {results {}} {enable CLR}}}} {args {{reset _rst__1 {port RST} {clock clk}} {clock clk {osc CLK}} {parameter guarded {param guarded}}}} f20 FIFO20 {ports {{RST Prelude.Reset} {CLK Prelude.Clock} {ENQ Prelude.Bool} {FULL_N Prelude.Bool} {DEQ Prelude.Bool} {EMPTY_N Prelude.Bool} {CLR Prelude.Bool}}} ---------- -fs SizedFIFO {interface {{method enq enq {clock clk} {reset _rst__1} {args {{{port D_IN} {size 32}}}} {enable ENQ} {ready FULL_N}} {method deq deq {clock clk} {reset _rst__1} {args {}} {enable DEQ} {ready EMPTY_N}} {method first first {clock clk} {reset _rst__1} {args {}} {result D_OUT} {ready EMPTY_N}} {method clear clear {clock clk} {reset _rst__1} {args {}} {enable CLR}}}} {args {{reset _rst__1 {port RST} {clock clk}} {clock clk {osc CLK}} {parameter p1width {param p1width}} {parameter p2depth {param p2depth}} {parameter p3cntr_width {param p3cntr_width}} {parameter guarded {param guarded}}}} +fs SizedFIFO {interface {{method enq enq {clock clk} {reset _rst__1} {args {{{port D_IN} {size 32}}}} {results {}} {enable ENQ} {ready FULL_N}} {method deq deq {clock clk} {reset _rst__1} {args {}} {results {}} {enable DEQ} {ready EMPTY_N}} {method first first {clock clk} {reset _rst__1} {args {}} {results {{{port D_OUT} {size 32}}}} {ready EMPTY_N}} {method clear clear {clock clk} {reset _rst__1} {args {}} {results {}} {enable CLR}}}} {args {{reset _rst__1 {port RST} {clock clk}} {clock clk {osc CLK}} {parameter p1width {param p1width}} {parameter p2depth {param p2depth}} {parameter p3cntr_width {param p3cntr_width}} {parameter guarded {param guarded}}}} fs SizedFIFO {ports {{RST Prelude.Reset} {CLK Prelude.Clock} {D_IN {Prelude.Int 32}} {ENQ Prelude.Bool} {FULL_N Prelude.Bool} {DEQ Prelude.Bool} {EMPTY_N Prelude.Bool} {D_OUT {Prelude.Int 32}} {CLR Prelude.Bool}}} ---------- -fs0 SizedFIFO0 {interface {{method enq enq {clock clk} {reset _rst__1} {args {}} {enable ENQ} {ready FULL_N}} {method deq deq {clock clk} {reset _rst__1} {args {}} {enable DEQ} {ready EMPTY_N}} {method first first {clock clk} {reset _rst__1} {args {}} {ready EMPTY_N}} {method clear clear {clock clk} {reset _rst__1} {args {}} {enable CLR}}}} {args {{reset _rst__1 {port RST} {clock clk}} {clock clk {osc CLK}} {parameter p1depth {param p1depth}} {parameter p2cntr_width {param p2cntr_width}} {parameter guarded {param guarded}}}} +fs0 SizedFIFO0 {interface {{method enq enq {clock clk} {reset _rst__1} {args {}} {results {}} {enable ENQ} {ready FULL_N}} {method deq deq {clock clk} {reset _rst__1} {args {}} {results {}} {enable DEQ} {ready EMPTY_N}} {method first first {clock clk} {reset _rst__1} {args {}} {results {}} {ready EMPTY_N}} {method clear clear {clock clk} {reset _rst__1} {args {}} {results {}} {enable CLR}}}} {args {{reset _rst__1 {port RST} {clock clk}} {clock clk {osc CLK}} {parameter p1depth {param p1depth}} {parameter p2cntr_width {param p2cntr_width}} {parameter guarded {param guarded}}}} fs0 SizedFIFO0 {ports {{RST Prelude.Reset} {CLK Prelude.Clock} {ENQ Prelude.Bool} {FULL_N Prelude.Bool} {DEQ Prelude.Bool} {EMPTY_N Prelude.Bool} {CLR Prelude.Bool}}} ---------- -fL1 FIFOL1 {interface {{method enq enq {clock clk} {reset _rst__1} {args {{{port D_IN} {size 32}}}} {enable ENQ} {ready FULL_N}} {method deq deq {clock clk} {reset _rst__1} {args {}} {enable DEQ} {ready EMPTY_N}} {method first first {clock clk} {reset _rst__1} {args {}} {result D_OUT} {ready EMPTY_N}} {method clear clear {clock clk} {reset _rst__1} {args {}} {enable CLR}}}} {args {{reset _rst__1 {port RST} {clock clk}} {clock clk {osc CLK}} {parameter width {param width}}}} +fL1 FIFOL1 {interface {{method enq enq {clock clk} {reset _rst__1} {args {{{port D_IN} {size 32}}}} {results {}} {enable ENQ} {ready FULL_N}} {method deq deq {clock clk} {reset _rst__1} {args {}} {results {}} {enable DEQ} {ready EMPTY_N}} {method first first {clock clk} {reset _rst__1} {args {}} {results {{{port D_OUT} {size 32}}}} {ready EMPTY_N}} {method clear clear {clock clk} {reset _rst__1} {args {}} {results {}} {enable CLR}}}} {args {{reset _rst__1 {port RST} {clock clk}} {clock clk {osc CLK}} {parameter width {param width}}}} fL1 FIFOL1 {ports {{RST Prelude.Reset} {CLK Prelude.Clock} {D_IN {Prelude.Int 32}} {ENQ Prelude.Bool} {FULL_N Prelude.Bool} {DEQ Prelude.Bool} {EMPTY_N Prelude.Bool} {D_OUT {Prelude.Int 32}} {CLR Prelude.Bool}}} ---------- -fL10 FIFO20 {interface {{method enq enq {clock clk} {reset _rst__1} {args {}} {enable ENQ} {ready FULL_N}} {method deq deq {clock clk} {reset _rst__1} {args {}} {enable DEQ} {ready EMPTY_N}} {method first first {clock clk} {reset _rst__1} {args {}} {ready EMPTY_N}} {method clear clear {clock clk} {reset _rst__1} {args {}} {enable CLR}}}} {args {{reset _rst__1 {port RST} {clock clk}} {clock clk {osc CLK}} {parameter guarded {param guarded}}}} +fL10 FIFO20 {interface {{method enq enq {clock clk} {reset _rst__1} {args {}} {results {}} {enable ENQ} {ready FULL_N}} {method deq deq {clock clk} {reset _rst__1} {args {}} {results {}} {enable DEQ} {ready EMPTY_N}} {method first first {clock clk} {reset _rst__1} {args {}} {results {}} {ready EMPTY_N}} {method clear clear {clock clk} {reset _rst__1} {args {}} {results {}} {enable CLR}}}} {args {{reset _rst__1 {port RST} {clock clk}} {clock clk {osc CLK}} {parameter guarded {param guarded}}}} fL10 FIFO20 {ports {{RST Prelude.Reset} {CLK Prelude.Clock} {ENQ Prelude.Bool} {FULL_N Prelude.Bool} {DEQ Prelude.Bool} {EMPTY_N Prelude.Bool} {CLR Prelude.Bool}}} ---------- dclk ClockGen {interface {{clock gen_clk gen_clk {osc CLK_OUT}}}} {args {{parameter v1Width {param v1Width}} {parameter v2Width {param v2Width}} {parameter initDelay {param initDelay}} {parameter initValue {param initValue}} {parameter otherValue {param otherValue}}}} dclk ClockGen {ports {{CLK_OUT Prelude.Clock}}} ---------- -sr SyncRegister {interface {{method _write _write {clock clk_src} {reset sRstIn} {args {{{port sD_IN} {size 32}}}} {enable sEN} {ready sRDY}} {method _read _read {clock clk_dst} {reset no_reset} {args {}} {result dD_OUT}}}} {args {{parameter width {param width}} {parameter init {param init}} {clock clk_src {osc sCLK}} {clock clk_dst {osc dCLK}} {reset sRstIn {port sRST} {clock clk_src}}}} +sr SyncRegister {interface {{method _write _write {clock clk_src} {reset sRstIn} {args {{{port sD_IN} {size 32}}}} {results {}} {enable sEN} {ready sRDY}} {method _read _read {clock clk_dst} {reset no_reset} {args {}} {results {{{port dD_OUT} {size 32}}}}}}} {args {{parameter width {param width}} {parameter init {param init}} {clock clk_src {osc sCLK}} {clock clk_dst {osc dCLK}} {reset sRstIn {port sRST} {clock clk_src}}}} sr SyncRegister {ports {{sCLK Prelude.Clock} {dCLK Prelude.Clock} {sRST Prelude.Reset} {sD_IN {Prelude.Int 32}} {sEN Prelude.Bool} {sRDY Prelude.Bool} {dD_OUT {Prelude.Int 32}}}} ---------- -bcw CrossingBypassWire {interface {{method wset wset {clock clk} {reset no_reset} {args {{{port WVAL} {size 32}}}}} {method wget wget {clock dstClk} {reset no_reset} {args {}} {result WGET}}}} {args {{parameter width {param width}} {clock clk {osc CLK}} {clock dstClk}}} +bcw CrossingBypassWire {interface {{method wset wset {clock clk} {reset no_reset} {args {{{port WVAL} {size 32}}}} {results {}}} {method wget wget {clock dstClk} {reset no_reset} {args {}} {results {{{port WGET} {size 32}}}}}}} {args {{parameter width {param width}} {clock clk {osc CLK}} {clock dstClk}}} bcw CrossingBypassWire {ports {{CLK Prelude.Clock} {WVAL {Prelude.Int 32}} {WGET {Prelude.Int 32}}}} ---------- -ncw CrossingBypassWire {interface {{method wset wset {clock clk} {reset no_reset} {args {{{port WVAL} {size 32}}}}} {method wget wget {clock dstClk} {reset no_reset} {args {}} {result WGET}}}} {args {{parameter width {param width}} {clock clk {osc CLK}} {clock dstClk}}} +ncw CrossingBypassWire {interface {{method wset wset {clock clk} {reset no_reset} {args {{{port WVAL} {size 32}}}} {results {}}} {method wget wget {clock dstClk} {reset no_reset} {args {}} {results {{{port WGET} {size 32}}}}}}} {args {{parameter width {param width}} {clock clk {osc CLK}} {clock dstClk}}} ncw CrossingBypassWire {ports {{CLK Prelude.Clock} {WVAL {Prelude.Int 32}} {WGET {Prelude.Int 32}}}} ---------- diff --git a/testsuite/bsc.bluetcl/targeted/port_types/prims.tcl.bluetcl-out.expected b/testsuite/bsc.bluetcl/targeted/port_types/prims.tcl.bluetcl-out.expected index 56f80bdcd..d1099dcef 100644 --- a/testsuite/bsc.bluetcl/targeted/port_types/prims.tcl.bluetcl-out.expected +++ b/testsuite/bsc.bluetcl/targeted/port_types/prims.tcl.bluetcl-out.expected @@ -1,75 +1,75 @@ -verilog sysPrims ---------- -rg RegN {interface {{method _write _write {clock _clk__1} {reset _rst__1} {args {{{port D_IN} {size 32}}}} {enable EN}} {method _read _read {clock _clk__1} {reset _rst__1} {args {}} {result Q_OUT}}}} {args {{clock _clk__1 {osc CLK}} {reset _rst__1 {port RST} {clock _clk__1}} {parameter width {param width}} {parameter init {param init}}}} +rg RegN {interface {{method _write _write {clock _clk__1} {reset _rst__1} {args {{{port D_IN} {size 32}}}} {results {}} {enable EN}} {method _read _read {clock _clk__1} {reset _rst__1} {args {}} {results {{{port Q_OUT} {size 32}}}}}}} {args {{clock _clk__1 {osc CLK}} {reset _rst__1 {port RST} {clock _clk__1}} {parameter width {param width}} {parameter init {param init}}}} rg RegN {ports {{CLK Clock} {RST Reset} {D_IN Int#(32)} {EN Bool} {Q_OUT Int#(32)}}} ---------- -rgA RegA {interface {{method _write _write {clock _clk__1} {reset _rst__1} {args {{{port D_IN} {size 32}}}} {enable EN}} {method _read _read {clock _clk__1} {reset _rst__1} {args {}} {result Q_OUT}}}} {args {{clock _clk__1 {osc CLK}} {reset _rst__1 {port RST} {clock _clk__1}} {parameter width {param width}} {parameter init {param init}}}} +rgA RegA {interface {{method _write _write {clock _clk__1} {reset _rst__1} {args {{{port D_IN} {size 32}}}} {results {}} {enable EN}} {method _read _read {clock _clk__1} {reset _rst__1} {args {}} {results {{{port Q_OUT} {size 32}}}}}}} {args {{clock _clk__1 {osc CLK}} {reset _rst__1 {port RST} {clock _clk__1}} {parameter width {param width}} {parameter init {param init}}}} rgA RegA {ports {{CLK Clock} {RST Reset} {D_IN Int#(32)} {EN Bool} {Q_OUT Int#(32)}}} ---------- -rgU RegUN {interface {{method _write _write {clock _clk__1} {reset no_reset} {args {{{port D_IN} {size 32}}}} {enable EN}} {method _read _read {clock _clk__1} {reset no_reset} {args {}} {result Q_OUT}}}} {args {{clock _clk__1 {osc CLK}} {parameter width {param width}}}} +rgU RegUN {interface {{method _write _write {clock _clk__1} {reset no_reset} {args {{{port D_IN} {size 32}}}} {results {}} {enable EN}} {method _read _read {clock _clk__1} {reset no_reset} {args {}} {results {{{port Q_OUT} {size 32}}}}}}} {args {{clock _clk__1 {osc CLK}} {parameter width {param width}}}} rgU RegUN {ports {{CLK Clock} {D_IN Int#(32)} {EN Bool} {Q_OUT Int#(32)}}} ---------- -rw RWire {interface {{method wset wset {clock clk} {reset rst} {args {{{port WVAL} {size 32}}}} {enable WSET}} {method wget wget {clock clk} {reset rst} {args {}} {result WGET} {ready WHAS}}}} {args {{parameter width {param width}} {clock clk} {reset rst {clock clk}}}} +rw RWire {interface {{method wset wset {clock clk} {reset rst} {args {{{port WVAL} {size 32}}}} {results {}} {enable WSET}} {method wget wget {clock clk} {reset rst} {args {}} {results {{{port WGET} {size 32}}}} {ready WHAS}}}} {args {{parameter width {param width}} {clock clk} {reset rst {clock clk}}}} rw RWire {ports {{WVAL Int#(32)} {WSET Bool} {WGET Int#(32)} {WHAS Bool}}} ---------- -rw0 RWire0 {interface {{method wset wset {clock clk} {reset rst} {args {}} {enable WSET}} {method wget wget {clock clk} {reset rst} {args {}} {ready WHAS}}}} {args {{clock clk} {reset rst {clock clk}}}} +rw0 RWire0 {interface {{method wset wset {clock clk} {reset rst} {args {}} {results {}} {enable WSET}} {method wget wget {clock clk} {reset rst} {args {}} {results {}} {ready WHAS}}}} {args {{clock clk} {reset rst {clock clk}}}} rw0 RWire0 {ports {{WSET Bool} {WHAS Bool}}} ---------- -w RWire {interface {{method _write _write {clock clk} {reset rst} {args {{{port WVAL} {size 32}}}} {enable WSET}} {method _read _read {clock clk} {reset rst} {args {}} {result WGET} {ready WHAS}}}} {args {{parameter width {param width}} {clock clk} {reset rst {clock clk}}}} +w RWire {interface {{method _write _write {clock clk} {reset rst} {args {{{port WVAL} {size 32}}}} {results {}} {enable WSET}} {method _read _read {clock clk} {reset rst} {args {}} {results {{{port WGET} {size 32}}}} {ready WHAS}}}} {args {{parameter width {param width}} {clock clk} {reset rst {clock clk}}}} w RWire {ports {{WVAL Int#(32)} {WSET Bool} {WGET Int#(32)} {WHAS Bool}}} ---------- -dw RWire {interface {{method _write _write {clock clk} {reset rst} {args {{{port WVAL} {size 32}}}} {enable WSET}} {method _read _read {clock clk} {reset rst} {args {}} {result WGET} {ready WHAS}}}} {args {{parameter width {param width}} {clock clk} {reset rst {clock clk}}}} +dw RWire {interface {{method _write _write {clock clk} {reset rst} {args {{{port WVAL} {size 32}}}} {results {}} {enable WSET}} {method _read _read {clock clk} {reset rst} {args {}} {results {{{port WGET} {size 32}}}} {ready WHAS}}}} {args {{parameter width {param width}} {clock clk} {reset rst {clock clk}}}} dw RWire {ports {{WVAL Int#(32)} {WSET Bool} {WGET Int#(32)} {WHAS Bool}}} ---------- -bw BypassWire {interface {{method _write _write {clock clk} {reset rst} {args {{{port WVAL} {size 32}}}}} {method _read _read {clock clk} {reset rst} {args {}} {result WGET}}}} {args {{parameter width {param width}} {clock clk} {reset rst {clock clk}}}} +bw BypassWire {interface {{method _write _write {clock clk} {reset rst} {args {{{port WVAL} {size 32}}}} {results {}}} {method _read _read {clock clk} {reset rst} {args {}} {results {{{port WGET} {size 32}}}}}}} {args {{parameter width {param width}} {clock clk} {reset rst {clock clk}}}} bw BypassWire {ports {{WVAL Int#(32)} {WGET Int#(32)}}} ---------- -pw RWire0 {interface {{method send send {clock clk} {reset rst} {args {}} {enable WSET}} {method _read _read {clock clk} {reset rst} {args {}} {result WHAS}}}} {args {{clock clk} {reset rst {clock clk}}}} +pw RWire0 {interface {{method send send {clock clk} {reset rst} {args {}} {results {}} {enable WSET}} {method _read _read {clock clk} {reset rst} {args {}} {results {{{port WHAS} {size 1}}}}}}} {args {{clock clk} {reset rst {clock clk}}}} pw RWire0 {ports {{WSET Bool} {WHAS Bool}}} ---------- -pwo RWire0 {interface {{method send send {clock clk} {reset rst} {args {}} {enable WSET}} {method _read _read {clock clk} {reset rst} {args {}} {result WHAS}}}} {args {{clock clk} {reset rst {clock clk}}}} +pwo RWire0 {interface {{method send send {clock clk} {reset rst} {args {}} {results {}} {enable WSET}} {method _read _read {clock clk} {reset rst} {args {}} {results {{{port WHAS} {size 1}}}}}}} {args {{clock clk} {reset rst {clock clk}}}} pwo RWire0 {ports {{WSET Bool} {WHAS Bool}}} ---------- -rf RegFile {interface {{method upd upd {clock _clk__1} {reset no_reset} {args {{{port ADDR_IN} {size 2}} {{port D_IN} {size 32}}}} {enable WE}} {method sub_1 sub_1 {clock _clk__1} {reset no_reset} {args {{{port ADDR_1} {size 2}}}} {result D_OUT_1}} {method sub_2 sub_2 {clock _clk__1} {reset no_reset} {args {{{port ADDR_2} {size 2}}}} {result D_OUT_2}} {method sub_3 sub_3 {clock _clk__1} {reset no_reset} {args {{{port ADDR_3} {size 2}}}} {result D_OUT_3}} {method sub_4 sub_4 {clock _clk__1} {reset no_reset} {args {{{port ADDR_4} {size 2}}}} {result D_OUT_4}} {method sub_5 sub_5 {clock _clk__1} {reset no_reset} {args {{{port ADDR_5} {size 2}}}} {result D_OUT_5}}}} {args {{clock _clk__1 {osc CLK}} {parameter addr_width {param addr_width}} {parameter data_width {param data_width}} {parameter lo {param lo}} {parameter hi {param hi}}}} +rf RegFile {interface {{method upd upd {clock _clk__1} {reset no_reset} {args {{{port ADDR_IN} {size 2}} {{port D_IN} {size 32}}}} {results {}} {enable WE}} {method sub_1 sub_1 {clock _clk__1} {reset no_reset} {args {{{port ADDR_1} {size 2}}}} {results {{{port D_OUT_1} {size 32}}}}} {method sub_2 sub_2 {clock _clk__1} {reset no_reset} {args {{{port ADDR_2} {size 2}}}} {results {{{port D_OUT_2} {size 32}}}}} {method sub_3 sub_3 {clock _clk__1} {reset no_reset} {args {{{port ADDR_3} {size 2}}}} {results {{{port D_OUT_3} {size 32}}}}} {method sub_4 sub_4 {clock _clk__1} {reset no_reset} {args {{{port ADDR_4} {size 2}}}} {results {{{port D_OUT_4} {size 32}}}}} {method sub_5 sub_5 {clock _clk__1} {reset no_reset} {args {{{port ADDR_5} {size 2}}}} {results {{{port D_OUT_5} {size 32}}}}}}} {args {{clock _clk__1 {osc CLK}} {parameter addr_width {param addr_width}} {parameter data_width {param data_width}} {parameter lo {param lo}} {parameter hi {param hi}}}} rf RegFile {ports {{CLK Clock} {ADDR_IN Bit#(2)} {D_IN Int#(32)} {WE Bool} {ADDR_1 Bit#(2)} {D_OUT_1 Int#(32)} {ADDR_2 Bit#(2)} {D_OUT_2 Int#(32)} {ADDR_3 Bit#(2)} {D_OUT_3 Int#(32)} {ADDR_4 Bit#(2)} {D_OUT_4 Int#(32)} {ADDR_5 Bit#(2)} {D_OUT_5 Int#(32)}}} ---------- -ff1 FIFO2 {interface {{method enq enq {clock clk} {reset _rst__1} {args {{{port D_IN} {size 32}}}} {enable ENQ} {ready FULL_N}} {method deq deq {clock clk} {reset _rst__1} {args {}} {enable DEQ} {ready EMPTY_N}} {method first first {clock clk} {reset _rst__1} {args {}} {result D_OUT} {ready EMPTY_N}} {method notFull notFull {clock clk} {reset _rst__1} {args {}} {result FULL_N}} {method notEmpty notEmpty {clock clk} {reset _rst__1} {args {}} {result EMPTY_N}} {method clear clear {clock clk} {reset _rst__1} {args {}} {enable CLR}}}} {args {{reset _rst__1 {port RST} {clock clk}} {clock clk {osc CLK}} {parameter width {param width}} {parameter guarded {param guarded}}}} +ff1 FIFO2 {interface {{method enq enq {clock clk} {reset _rst__1} {args {{{port D_IN} {size 32}}}} {results {}} {enable ENQ} {ready FULL_N}} {method deq deq {clock clk} {reset _rst__1} {args {}} {results {}} {enable DEQ} {ready EMPTY_N}} {method first first {clock clk} {reset _rst__1} {args {}} {results {{{port D_OUT} {size 32}}}} {ready EMPTY_N}} {method notFull notFull {clock clk} {reset _rst__1} {args {}} {results {{{port FULL_N} {size 1}}}}} {method notEmpty notEmpty {clock clk} {reset _rst__1} {args {}} {results {{{port EMPTY_N} {size 1}}}}} {method clear clear {clock clk} {reset _rst__1} {args {}} {results {}} {enable CLR}}}} {args {{reset _rst__1 {port RST} {clock clk}} {clock clk {osc CLK}} {parameter width {param width}} {parameter guarded {param guarded}}}} ff1 FIFO2 {ports {{RST Reset} {CLK Clock} {D_IN Int#(32)} {ENQ Bool} {FULL_N Bool} {DEQ Bool} {EMPTY_N Bool} {D_OUT Int#(32)} {CLR Bool}}} ---------- -f1 FIFO1 {interface {{method enq enq {clock clk} {reset _rst__1} {args {{{port D_IN} {size 32}}}} {enable ENQ} {ready FULL_N}} {method deq deq {clock clk} {reset _rst__1} {args {}} {enable DEQ} {ready EMPTY_N}} {method first first {clock clk} {reset _rst__1} {args {}} {result D_OUT} {ready EMPTY_N}} {method clear clear {clock clk} {reset _rst__1} {args {}} {enable CLR}}}} {args {{reset _rst__1 {port RST} {clock clk}} {clock clk {osc CLK}} {parameter width {param width}} {parameter guarded {param guarded}}}} +f1 FIFO1 {interface {{method enq enq {clock clk} {reset _rst__1} {args {{{port D_IN} {size 32}}}} {results {}} {enable ENQ} {ready FULL_N}} {method deq deq {clock clk} {reset _rst__1} {args {}} {results {}} {enable DEQ} {ready EMPTY_N}} {method first first {clock clk} {reset _rst__1} {args {}} {results {{{port D_OUT} {size 32}}}} {ready EMPTY_N}} {method clear clear {clock clk} {reset _rst__1} {args {}} {results {}} {enable CLR}}}} {args {{reset _rst__1 {port RST} {clock clk}} {clock clk {osc CLK}} {parameter width {param width}} {parameter guarded {param guarded}}}} f1 FIFO1 {ports {{RST Reset} {CLK Clock} {D_IN Int#(32)} {ENQ Bool} {FULL_N Bool} {DEQ Bool} {EMPTY_N Bool} {D_OUT Int#(32)} {CLR Bool}}} ---------- -f10 FIFO10 {interface {{method enq enq {clock clk} {reset _rst__1} {args {}} {enable ENQ} {ready FULL_N}} {method deq deq {clock clk} {reset _rst__1} {args {}} {enable DEQ} {ready EMPTY_N}} {method first first {clock clk} {reset _rst__1} {args {}} {ready EMPTY_N}} {method clear clear {clock clk} {reset _rst__1} {args {}} {enable CLR}}}} {args {{reset _rst__1 {port RST} {clock clk}} {clock clk {osc CLK}} {parameter guarded {param guarded}}}} +f10 FIFO10 {interface {{method enq enq {clock clk} {reset _rst__1} {args {}} {results {}} {enable ENQ} {ready FULL_N}} {method deq deq {clock clk} {reset _rst__1} {args {}} {results {}} {enable DEQ} {ready EMPTY_N}} {method first first {clock clk} {reset _rst__1} {args {}} {results {}} {ready EMPTY_N}} {method clear clear {clock clk} {reset _rst__1} {args {}} {results {}} {enable CLR}}}} {args {{reset _rst__1 {port RST} {clock clk}} {clock clk {osc CLK}} {parameter guarded {param guarded}}}} f10 FIFO10 {ports {{RST Reset} {CLK Clock} {ENQ Bool} {FULL_N Bool} {DEQ Bool} {EMPTY_N Bool} {CLR Bool}}} ---------- -f2 FIFO2 {interface {{method enq enq {clock clk} {reset _rst__1} {args {{{port D_IN} {size 32}}}} {enable ENQ} {ready FULL_N}} {method deq deq {clock clk} {reset _rst__1} {args {}} {enable DEQ} {ready EMPTY_N}} {method first first {clock clk} {reset _rst__1} {args {}} {result D_OUT} {ready EMPTY_N}} {method clear clear {clock clk} {reset _rst__1} {args {}} {enable CLR}}}} {args {{reset _rst__1 {port RST} {clock clk}} {clock clk {osc CLK}} {parameter width {param width}} {parameter guarded {param guarded}}}} +f2 FIFO2 {interface {{method enq enq {clock clk} {reset _rst__1} {args {{{port D_IN} {size 32}}}} {results {}} {enable ENQ} {ready FULL_N}} {method deq deq {clock clk} {reset _rst__1} {args {}} {results {}} {enable DEQ} {ready EMPTY_N}} {method first first {clock clk} {reset _rst__1} {args {}} {results {{{port D_OUT} {size 32}}}} {ready EMPTY_N}} {method clear clear {clock clk} {reset _rst__1} {args {}} {results {}} {enable CLR}}}} {args {{reset _rst__1 {port RST} {clock clk}} {clock clk {osc CLK}} {parameter width {param width}} {parameter guarded {param guarded}}}} f2 FIFO2 {ports {{RST Reset} {CLK Clock} {D_IN Int#(32)} {ENQ Bool} {FULL_N Bool} {DEQ Bool} {EMPTY_N Bool} {D_OUT Int#(32)} {CLR Bool}}} ---------- -f20 FIFO20 {interface {{method enq enq {clock clk} {reset _rst__1} {args {}} {enable ENQ} {ready FULL_N}} {method deq deq {clock clk} {reset _rst__1} {args {}} {enable DEQ} {ready EMPTY_N}} {method first first {clock clk} {reset _rst__1} {args {}} {ready EMPTY_N}} {method clear clear {clock clk} {reset _rst__1} {args {}} {enable CLR}}}} {args {{reset _rst__1 {port RST} {clock clk}} {clock clk {osc CLK}} {parameter guarded {param guarded}}}} +f20 FIFO20 {interface {{method enq enq {clock clk} {reset _rst__1} {args {}} {results {}} {enable ENQ} {ready FULL_N}} {method deq deq {clock clk} {reset _rst__1} {args {}} {results {}} {enable DEQ} {ready EMPTY_N}} {method first first {clock clk} {reset _rst__1} {args {}} {results {}} {ready EMPTY_N}} {method clear clear {clock clk} {reset _rst__1} {args {}} {results {}} {enable CLR}}}} {args {{reset _rst__1 {port RST} {clock clk}} {clock clk {osc CLK}} {parameter guarded {param guarded}}}} f20 FIFO20 {ports {{RST Reset} {CLK Clock} {ENQ Bool} {FULL_N Bool} {DEQ Bool} {EMPTY_N Bool} {CLR Bool}}} ---------- -fs SizedFIFO {interface {{method enq enq {clock clk} {reset _rst__1} {args {{{port D_IN} {size 32}}}} {enable ENQ} {ready FULL_N}} {method deq deq {clock clk} {reset _rst__1} {args {}} {enable DEQ} {ready EMPTY_N}} {method first first {clock clk} {reset _rst__1} {args {}} {result D_OUT} {ready EMPTY_N}} {method clear clear {clock clk} {reset _rst__1} {args {}} {enable CLR}}}} {args {{reset _rst__1 {port RST} {clock clk}} {clock clk {osc CLK}} {parameter p1width {param p1width}} {parameter p2depth {param p2depth}} {parameter p3cntr_width {param p3cntr_width}} {parameter guarded {param guarded}}}} +fs SizedFIFO {interface {{method enq enq {clock clk} {reset _rst__1} {args {{{port D_IN} {size 32}}}} {results {}} {enable ENQ} {ready FULL_N}} {method deq deq {clock clk} {reset _rst__1} {args {}} {results {}} {enable DEQ} {ready EMPTY_N}} {method first first {clock clk} {reset _rst__1} {args {}} {results {{{port D_OUT} {size 32}}}} {ready EMPTY_N}} {method clear clear {clock clk} {reset _rst__1} {args {}} {results {}} {enable CLR}}}} {args {{reset _rst__1 {port RST} {clock clk}} {clock clk {osc CLK}} {parameter p1width {param p1width}} {parameter p2depth {param p2depth}} {parameter p3cntr_width {param p3cntr_width}} {parameter guarded {param guarded}}}} fs SizedFIFO {ports {{RST Reset} {CLK Clock} {D_IN Int#(32)} {ENQ Bool} {FULL_N Bool} {DEQ Bool} {EMPTY_N Bool} {D_OUT Int#(32)} {CLR Bool}}} ---------- -fs0 SizedFIFO0 {interface {{method enq enq {clock clk} {reset _rst__1} {args {}} {enable ENQ} {ready FULL_N}} {method deq deq {clock clk} {reset _rst__1} {args {}} {enable DEQ} {ready EMPTY_N}} {method first first {clock clk} {reset _rst__1} {args {}} {ready EMPTY_N}} {method clear clear {clock clk} {reset _rst__1} {args {}} {enable CLR}}}} {args {{reset _rst__1 {port RST} {clock clk}} {clock clk {osc CLK}} {parameter p1depth {param p1depth}} {parameter p2cntr_width {param p2cntr_width}} {parameter guarded {param guarded}}}} +fs0 SizedFIFO0 {interface {{method enq enq {clock clk} {reset _rst__1} {args {}} {results {}} {enable ENQ} {ready FULL_N}} {method deq deq {clock clk} {reset _rst__1} {args {}} {results {}} {enable DEQ} {ready EMPTY_N}} {method first first {clock clk} {reset _rst__1} {args {}} {results {}} {ready EMPTY_N}} {method clear clear {clock clk} {reset _rst__1} {args {}} {results {}} {enable CLR}}}} {args {{reset _rst__1 {port RST} {clock clk}} {clock clk {osc CLK}} {parameter p1depth {param p1depth}} {parameter p2cntr_width {param p2cntr_width}} {parameter guarded {param guarded}}}} fs0 SizedFIFO0 {ports {{RST Reset} {CLK Clock} {ENQ Bool} {FULL_N Bool} {DEQ Bool} {EMPTY_N Bool} {CLR Bool}}} ---------- -fL1 FIFOL1 {interface {{method enq enq {clock clk} {reset _rst__1} {args {{{port D_IN} {size 32}}}} {enable ENQ} {ready FULL_N}} {method deq deq {clock clk} {reset _rst__1} {args {}} {enable DEQ} {ready EMPTY_N}} {method first first {clock clk} {reset _rst__1} {args {}} {result D_OUT} {ready EMPTY_N}} {method clear clear {clock clk} {reset _rst__1} {args {}} {enable CLR}}}} {args {{reset _rst__1 {port RST} {clock clk}} {clock clk {osc CLK}} {parameter width {param width}}}} +fL1 FIFOL1 {interface {{method enq enq {clock clk} {reset _rst__1} {args {{{port D_IN} {size 32}}}} {results {}} {enable ENQ} {ready FULL_N}} {method deq deq {clock clk} {reset _rst__1} {args {}} {results {}} {enable DEQ} {ready EMPTY_N}} {method first first {clock clk} {reset _rst__1} {args {}} {results {{{port D_OUT} {size 32}}}} {ready EMPTY_N}} {method clear clear {clock clk} {reset _rst__1} {args {}} {results {}} {enable CLR}}}} {args {{reset _rst__1 {port RST} {clock clk}} {clock clk {osc CLK}} {parameter width {param width}}}} fL1 FIFOL1 {ports {{RST Reset} {CLK Clock} {D_IN Int#(32)} {ENQ Bool} {FULL_N Bool} {DEQ Bool} {EMPTY_N Bool} {D_OUT Int#(32)} {CLR Bool}}} ---------- -fL10 FIFO20 {interface {{method enq enq {clock clk} {reset _rst__1} {args {}} {enable ENQ} {ready FULL_N}} {method deq deq {clock clk} {reset _rst__1} {args {}} {enable DEQ} {ready EMPTY_N}} {method first first {clock clk} {reset _rst__1} {args {}} {ready EMPTY_N}} {method clear clear {clock clk} {reset _rst__1} {args {}} {enable CLR}}}} {args {{reset _rst__1 {port RST} {clock clk}} {clock clk {osc CLK}} {parameter guarded {param guarded}}}} +fL10 FIFO20 {interface {{method enq enq {clock clk} {reset _rst__1} {args {}} {results {}} {enable ENQ} {ready FULL_N}} {method deq deq {clock clk} {reset _rst__1} {args {}} {results {}} {enable DEQ} {ready EMPTY_N}} {method first first {clock clk} {reset _rst__1} {args {}} {results {}} {ready EMPTY_N}} {method clear clear {clock clk} {reset _rst__1} {args {}} {results {}} {enable CLR}}}} {args {{reset _rst__1 {port RST} {clock clk}} {clock clk {osc CLK}} {parameter guarded {param guarded}}}} fL10 FIFO20 {ports {{RST Reset} {CLK Clock} {ENQ Bool} {FULL_N Bool} {DEQ Bool} {EMPTY_N Bool} {CLR Bool}}} ---------- dclk ClockGen {interface {{clock gen_clk gen_clk {osc CLK_OUT}}}} {args {{parameter v1Width {param v1Width}} {parameter v2Width {param v2Width}} {parameter initDelay {param initDelay}} {parameter initValue {param initValue}} {parameter otherValue {param otherValue}}}} dclk ClockGen {ports {{CLK_OUT Clock}}} ---------- -sr SyncRegister {interface {{method _write _write {clock clk_src} {reset sRstIn} {args {{{port sD_IN} {size 32}}}} {enable sEN} {ready sRDY}} {method _read _read {clock clk_dst} {reset no_reset} {args {}} {result dD_OUT}}}} {args {{parameter width {param width}} {parameter init {param init}} {clock clk_src {osc sCLK}} {clock clk_dst {osc dCLK}} {reset sRstIn {port sRST} {clock clk_src}}}} +sr SyncRegister {interface {{method _write _write {clock clk_src} {reset sRstIn} {args {{{port sD_IN} {size 32}}}} {results {}} {enable sEN} {ready sRDY}} {method _read _read {clock clk_dst} {reset no_reset} {args {}} {results {{{port dD_OUT} {size 32}}}}}}} {args {{parameter width {param width}} {parameter init {param init}} {clock clk_src {osc sCLK}} {clock clk_dst {osc dCLK}} {reset sRstIn {port sRST} {clock clk_src}}}} sr SyncRegister {ports {{sCLK Clock} {dCLK Clock} {sRST Reset} {sD_IN Int#(32)} {sEN Bool} {sRDY Bool} {dD_OUT Int#(32)}}} ---------- -bcw CrossingBypassWire {interface {{method wset wset {clock clk} {reset no_reset} {args {{{port WVAL} {size 32}}}}} {method wget wget {clock dstClk} {reset no_reset} {args {}} {result WGET}}}} {args {{parameter width {param width}} {clock clk {osc CLK}} {clock dstClk}}} +bcw CrossingBypassWire {interface {{method wset wset {clock clk} {reset no_reset} {args {{{port WVAL} {size 32}}}} {results {}}} {method wget wget {clock dstClk} {reset no_reset} {args {}} {results {{{port WGET} {size 32}}}}}}} {args {{parameter width {param width}} {clock clk {osc CLK}} {clock dstClk}}} bcw CrossingBypassWire {ports {{CLK Clock} {WVAL Int#(32)} {WGET Int#(32)}}} ---------- -ncw CrossingBypassWire {interface {{method wset wset {clock clk} {reset no_reset} {args {{{port WVAL} {size 32}}}}} {method wget wget {clock dstClk} {reset no_reset} {args {}} {result WGET}}}} {args {{parameter width {param width}} {clock clk {osc CLK}} {clock dstClk}}} +ncw CrossingBypassWire {interface {{method wset wset {clock clk} {reset no_reset} {args {{{port WVAL} {size 32}}}} {results {}}} {method wget wget {clock dstClk} {reset no_reset} {args {}} {results {{{port WGET} {size 32}}}}}}} {args {{parameter width {param width}} {clock clk {osc CLK}} {clock dstClk}}} ncw CrossingBypassWire {ports {{CLK Clock} {WVAL Int#(32)} {WGET Int#(32)}}} ---------- diff --git a/testsuite/bsc.bluetcl/targeted/port_types/split_port_types.tcl b/testsuite/bsc.bluetcl/targeted/port_types/split_port_types.tcl new file mode 100644 index 000000000..cfc785205 --- /dev/null +++ b/testsuite/bsc.bluetcl/targeted/port_types/split_port_types.tcl @@ -0,0 +1,16 @@ +namespace import ::Bluetcl::* + +puts [flags set {-verilog}] +puts [module load mkSplitPortTypes] + +puts {----------} +puts "module porttypes mkSplitPortTypes" +foreach e [module porttypes mkSplitPortTypes] { + puts $e +} + +puts {----------} +puts "module ports mkSplitPortTypes" +foreach e [module ports mkSplitPortTypes] { + puts $e +} diff --git a/testsuite/bsc.bluetcl/targeted/port_types/split_port_types.tcl.bluetcl-bh-out.expected b/testsuite/bsc.bluetcl/targeted/port_types/split_port_types.tcl.bluetcl-bh-out.expected new file mode 100644 index 000000000..6abf20c92 --- /dev/null +++ b/testsuite/bsc.bluetcl/targeted/port_types/split_port_types.tcl.bluetcl-bh-out.expected @@ -0,0 +1,55 @@ +-verilog +mkSplitPortTypes +---------- +module porttypes mkSplitPortTypes +CLK Prelude.Clock +RST_N Prelude.Reset +getDeep_x {Prelude.UInt 8} +getDeep_y_a Prelude.Bool +getDeep_y_b {Prelude.Int 16} +getDeep_z {Prelude.Bit 4} +RDY_getDeep Prelude.Bool +getShallow_x {Prelude.UInt 8} +getShallow_y SplitPortTypes.Inner +getShallow_z {Prelude.Bit 4} +RDY_getShallow Prelude.Bool +nextDeep_x {Prelude.UInt 8} +nextDeep_y_a Prelude.Bool +nextDeep_y_b {Prelude.Int 16} +nextDeep_z {Prelude.Bit 4} +EN_nextDeep Prelude.Bool +RDY_nextDeep Prelude.Bool +putDeep_1_x {Prelude.UInt 8} +putDeep_1_y_a Prelude.Bool +putDeep_1_y_b {Prelude.Int 16} +putDeep_1_z {Prelude.Bit 4} +EN_putDeep Prelude.Bool +RDY_putDeep Prelude.Bool +putShallow_1_x {Prelude.UInt 8} +putShallow_1_y SplitPortTypes.Inner +putShallow_1_z {Prelude.Bit 4} +EN_putShallow Prelude.Bool +RDY_putShallow Prelude.Bool +combineDeep_lhs_x {Prelude.UInt 8} +combineDeep_lhs_y_a Prelude.Bool +combineDeep_lhs_y_b {Prelude.Int 16} +combineDeep_lhs_z {Prelude.Bit 4} +combineDeep_rhs_x {Prelude.UInt 8} +combineDeep_rhs_y_a Prelude.Bool +combineDeep_rhs_y_b {Prelude.Int 16} +combineDeep_rhs_z {Prelude.Bit 4} +EN_combineDeep Prelude.Bool +RDY_combineDeep Prelude.Bool +transform_1_x {Prelude.UInt 8} +transform_1_y_a Prelude.Bool +transform_1_y_b {Prelude.Int 16} +transform_1_z {Prelude.Bit 4} +transform_x {Prelude.UInt 8} +transform_y_a Prelude.Bool +transform_y_b {Prelude.Int 16} +transform_z {Prelude.Bit 4} +RDY_transform Prelude.Bool +---------- +module ports mkSplitPortTypes +interface {{method getDeep getDeep {clock default_clock} {reset default_reset} {args {}} {results {{{port getDeep_x} {size 8}} {{port getDeep_y_a} {size 1}} {{port getDeep_y_b} {size 16}} {{port getDeep_z} {size 4}}}} {ready RDY_getDeep}} {method getShallow getShallow {clock default_clock} {reset default_reset} {args {}} {results {{{port getShallow_x} {size 8}} {{port getShallow_y} {size 17}} {{port getShallow_z} {size 4}}}} {ready RDY_getShallow}} {method nextDeep nextDeep {clock default_clock} {reset default_reset} {args {}} {results {{{port nextDeep_x} {size 8}} {{port nextDeep_y_a} {size 1}} {{port nextDeep_y_b} {size 16}} {{port nextDeep_z} {size 4}}}} {enable EN_nextDeep} {ready RDY_nextDeep}} {method putDeep putDeep {clock default_clock} {reset default_reset} {args {{{name putDeep_1_x} {port putDeep_1_x} {size 8}} {{name putDeep_1_y_a} {port putDeep_1_y_a} {size 1}} {{name putDeep_1_y_b} {port putDeep_1_y_b} {size 16}} {{name putDeep_1_z} {port putDeep_1_z} {size 4}}}} {results {}} {enable EN_putDeep} {ready RDY_putDeep}} {method putShallow putShallow {clock default_clock} {reset default_reset} {args {{{name putShallow_1_x} {port putShallow_1_x} {size 8}} {{name putShallow_1_y} {port putShallow_1_y} {size 17}} {{name putShallow_1_z} {port putShallow_1_z} {size 4}}}} {results {}} {enable EN_putShallow} {ready RDY_putShallow}} {method combineDeep combineDeep {clock default_clock} {reset default_reset} {args {{{name combineDeep_lhs_x} {port combineDeep_lhs_x} {size 8}} {{name combineDeep_lhs_y_a} {port combineDeep_lhs_y_a} {size 1}} {{name combineDeep_lhs_y_b} {port combineDeep_lhs_y_b} {size 16}} {{name combineDeep_lhs_z} {port combineDeep_lhs_z} {size 4}} {{name combineDeep_rhs_x} {port combineDeep_rhs_x} {size 8}} {{name combineDeep_rhs_y_a} {port combineDeep_rhs_y_a} {size 1}} {{name combineDeep_rhs_y_b} {port combineDeep_rhs_y_b} {size 16}} {{name combineDeep_rhs_z} {port combineDeep_rhs_z} {size 4}}}} {results {}} {enable EN_combineDeep} {ready RDY_combineDeep}} {method transform transform {clock no_clock} {reset no_reset} {args {{{name transform_1_x} {port transform_1_x} {size 8}} {{name transform_1_y_a} {port transform_1_y_a} {size 1}} {{name transform_1_y_b} {port transform_1_y_b} {size 16}} {{name transform_1_z} {port transform_1_z} {size 4}}}} {results {{{port transform_x} {size 8}} {{port transform_y_a} {size 1}} {{port transform_y_b} {size 16}} {{port transform_z} {size 4}}}} {ready RDY_transform}}} +args {{clock default_clock {osc CLK}} {reset default_reset {port RST_N} {clock default_clock}}} diff --git a/testsuite/bsc.bluetcl/targeted/port_types/split_port_types.tcl.bluetcl-out.expected b/testsuite/bsc.bluetcl/targeted/port_types/split_port_types.tcl.bluetcl-out.expected new file mode 100644 index 000000000..83b846b70 --- /dev/null +++ b/testsuite/bsc.bluetcl/targeted/port_types/split_port_types.tcl.bluetcl-out.expected @@ -0,0 +1,55 @@ +-verilog +mkSplitPortTypes +---------- +module porttypes mkSplitPortTypes +CLK Clock +RST_N Reset +getDeep_x UInt#(8) +getDeep_y_a Bool +getDeep_y_b Int#(16) +getDeep_z Bit#(4) +RDY_getDeep Bool +getShallow_x UInt#(8) +getShallow_y SplitPortTypes::Inner +getShallow_z Bit#(4) +RDY_getShallow Bool +nextDeep_x UInt#(8) +nextDeep_y_a Bool +nextDeep_y_b Int#(16) +nextDeep_z Bit#(4) +EN_nextDeep Bool +RDY_nextDeep Bool +putDeep_1_x UInt#(8) +putDeep_1_y_a Bool +putDeep_1_y_b Int#(16) +putDeep_1_z Bit#(4) +EN_putDeep Bool +RDY_putDeep Bool +putShallow_1_x UInt#(8) +putShallow_1_y SplitPortTypes::Inner +putShallow_1_z Bit#(4) +EN_putShallow Bool +RDY_putShallow Bool +combineDeep_lhs_x UInt#(8) +combineDeep_lhs_y_a Bool +combineDeep_lhs_y_b Int#(16) +combineDeep_lhs_z Bit#(4) +combineDeep_rhs_x UInt#(8) +combineDeep_rhs_y_a Bool +combineDeep_rhs_y_b Int#(16) +combineDeep_rhs_z Bit#(4) +EN_combineDeep Bool +RDY_combineDeep Bool +transform_1_x UInt#(8) +transform_1_y_a Bool +transform_1_y_b Int#(16) +transform_1_z Bit#(4) +transform_x UInt#(8) +transform_y_a Bool +transform_y_b Int#(16) +transform_z Bit#(4) +RDY_transform Bool +---------- +module ports mkSplitPortTypes +interface {{method getDeep getDeep {clock default_clock} {reset default_reset} {args {}} {results {{{port getDeep_x} {size 8}} {{port getDeep_y_a} {size 1}} {{port getDeep_y_b} {size 16}} {{port getDeep_z} {size 4}}}} {ready RDY_getDeep}} {method getShallow getShallow {clock default_clock} {reset default_reset} {args {}} {results {{{port getShallow_x} {size 8}} {{port getShallow_y} {size 17}} {{port getShallow_z} {size 4}}}} {ready RDY_getShallow}} {method nextDeep nextDeep {clock default_clock} {reset default_reset} {args {}} {results {{{port nextDeep_x} {size 8}} {{port nextDeep_y_a} {size 1}} {{port nextDeep_y_b} {size 16}} {{port nextDeep_z} {size 4}}}} {enable EN_nextDeep} {ready RDY_nextDeep}} {method putDeep putDeep {clock default_clock} {reset default_reset} {args {{{name putDeep_1_x} {port putDeep_1_x} {size 8}} {{name putDeep_1_y_a} {port putDeep_1_y_a} {size 1}} {{name putDeep_1_y_b} {port putDeep_1_y_b} {size 16}} {{name putDeep_1_z} {port putDeep_1_z} {size 4}}}} {results {}} {enable EN_putDeep} {ready RDY_putDeep}} {method putShallow putShallow {clock default_clock} {reset default_reset} {args {{{name putShallow_1_x} {port putShallow_1_x} {size 8}} {{name putShallow_1_y} {port putShallow_1_y} {size 17}} {{name putShallow_1_z} {port putShallow_1_z} {size 4}}}} {results {}} {enable EN_putShallow} {ready RDY_putShallow}} {method combineDeep combineDeep {clock default_clock} {reset default_reset} {args {{{name combineDeep_lhs_x} {port combineDeep_lhs_x} {size 8}} {{name combineDeep_lhs_y_a} {port combineDeep_lhs_y_a} {size 1}} {{name combineDeep_lhs_y_b} {port combineDeep_lhs_y_b} {size 16}} {{name combineDeep_lhs_z} {port combineDeep_lhs_z} {size 4}} {{name combineDeep_rhs_x} {port combineDeep_rhs_x} {size 8}} {{name combineDeep_rhs_y_a} {port combineDeep_rhs_y_a} {size 1}} {{name combineDeep_rhs_y_b} {port combineDeep_rhs_y_b} {size 16}} {{name combineDeep_rhs_z} {port combineDeep_rhs_z} {size 4}}}} {results {}} {enable EN_combineDeep} {ready RDY_combineDeep}} {method transform transform {clock no_clock} {reset no_reset} {args {{{name transform_1_x} {port transform_1_x} {size 8}} {{name transform_1_y_a} {port transform_1_y_a} {size 1}} {{name transform_1_y_b} {port transform_1_y_b} {size 16}} {{name transform_1_z} {port transform_1_z} {size 4}}}} {results {{{port transform_x} {size 8}} {{port transform_y_a} {size 1}} {{port transform_y_b} {size 16}} {{port transform_z} {size 4}}}} {ready RDY_transform}}} +args {{clock default_clock {osc CLK}} {reset default_reset {port RST_N} {clock default_clock}}} diff --git a/testsuite/bsc.bluetcl/targeted/port_types/zero_size.tcl.bluetcl-bh-out.expected b/testsuite/bsc.bluetcl/targeted/port_types/zero_size.tcl.bluetcl-bh-out.expected index e3facb44e..bb0527ecb 100644 --- a/testsuite/bsc.bluetcl/targeted/port_types/zero_size.tcl.bluetcl-bh-out.expected +++ b/testsuite/bsc.bluetcl/targeted/port_types/zero_size.tcl.bluetcl-bh-out.expected @@ -1,11 +1,11 @@ -verilog mkZeroSize_Sub sysZeroSize ---------- -{rg1 MOD {interface {{method _write _write {clock _clk__1} {reset _rst__1} {args {}} {enable EN}} {method _read _read {clock _clk__1} {reset _rst__1} {args {}}}}} {args {{reset _rst__1 {port RST} {clock _clk__1}} {clock _clk__1 {osc CLK} {gate CLK_GATE}}}}} {rg2 mkZeroSize_Sub {interface {{method m1 m1 {clock no_clock} {reset no_reset} {args {}} {ready RDY_m1}} {method m2 m2 {clock default_clock} {reset no_reset} {args {{{port m2_y} {size 1}}}} {enable EN_m2} {ready RDY_m2}} {method m3 m3 {clock default_clock} {reset no_reset} {args {}} {enable EN_m3} {ready RDY_m3}}}} {args {{clock default_clock {osc CLK}} {reset default_reset {port RST_N} {clock default_clock}}}}} +{rg1 MOD {interface {{method _write _write {clock _clk__1} {reset _rst__1} {args {}} {results {}} {enable EN}} {method _read _read {clock _clk__1} {reset _rst__1} {args {}} {results {}}}}} {args {{reset _rst__1 {port RST} {clock _clk__1}} {clock _clk__1 {osc CLK} {gate CLK_GATE}}}}} {rg2 mkZeroSize_Sub {interface {{method m1 m1 {clock no_clock} {reset no_reset} {args {}} {results {}} {ready RDY_m1}} {method m2 m2 {clock default_clock} {reset no_reset} {args {{{port m2_y} {size 1}}}} {results {}} {enable EN_m2} {ready RDY_m2}} {method m3 m3 {clock default_clock} {reset no_reset} {args {}} {results {}} {enable EN_m3} {ready RDY_m3}}}} {args {{clock default_clock {osc CLK}} {reset default_reset {port RST_N} {clock default_clock}}}}} {rg1 MOD {ports {{RST Prelude.Reset} {CLK Prelude.Clock} {CLK_GATE Prelude.Bool} {EN Prelude.Bool}}}} {rg2 mkZeroSize_Sub {ports {{CLK Prelude.Clock} {RST_N Prelude.Reset} {RDY_m1 Prelude.Bool} {m2_y Prelude.Bool} {EN_m2 Prelude.Bool} {RDY_m2 Prelude.Bool} {EN_m3 Prelude.Bool} {RDY_m3 Prelude.Bool}}}} ---------- -{interface {{method m1 m1 {clock no_clock} {reset no_reset} {args {}} {ready RDY_m1}} {method m2 m2 {clock default_clock} {reset no_reset} {args {{{name m2_y} {port m2_y} {size 1}}}} {enable EN_m2} {ready RDY_m2}} {method m3 m3 {clock default_clock} {reset no_reset} {args {}} {enable EN_m3} {ready RDY_m3}}}} {args {{clock default_clock {osc CLK}} {reset default_reset {port RST_N} {clock default_clock}}}} +{interface {{method m1 m1 {clock no_clock} {reset no_reset} {args {}} {results {}} {ready RDY_m1}} {method m2 m2 {clock default_clock} {reset no_reset} {args {{{name m2_y} {port m2_y} {size 1}}}} {results {}} {enable EN_m2} {ready RDY_m2}} {method m3 m3 {clock default_clock} {reset no_reset} {args {}} {results {}} {enable EN_m3} {ready RDY_m3}}}} {args {{clock default_clock {osc CLK}} {reset default_reset {port RST_N} {clock default_clock}}}} {CLK Prelude.Clock} {RST_N Prelude.Reset} {RDY_m1 Prelude.Bool} {m2_y Prelude.Bool} {EN_m2 Prelude.Bool} {RDY_m2 Prelude.Bool} {EN_m3 Prelude.Bool} {RDY_m3 Prelude.Bool} ---------- diff --git a/testsuite/bsc.bluetcl/targeted/port_types/zero_size.tcl.bluetcl-out.expected b/testsuite/bsc.bluetcl/targeted/port_types/zero_size.tcl.bluetcl-out.expected index 4d5264b9d..e62ad7fa7 100644 --- a/testsuite/bsc.bluetcl/targeted/port_types/zero_size.tcl.bluetcl-out.expected +++ b/testsuite/bsc.bluetcl/targeted/port_types/zero_size.tcl.bluetcl-out.expected @@ -1,11 +1,11 @@ -verilog mkZeroSize_Sub sysZeroSize ---------- -{rg1 MOD {interface {{method _write _write {clock _clk__1} {reset _rst__1} {args {}} {enable EN}} {method _read _read {clock _clk__1} {reset _rst__1} {args {}}}}} {args {{reset _rst__1 {port RST} {clock _clk__1}} {clock _clk__1 {osc CLK} {gate CLK_GATE}}}}} {rg2 mkZeroSize_Sub {interface {{method m1 m1 {clock no_clock} {reset no_reset} {args {}} {ready RDY_m1}} {method m2 m2 {clock default_clock} {reset no_reset} {args {{{port m2_y} {size 1}}}} {enable EN_m2} {ready RDY_m2}} {method m3 m3 {clock default_clock} {reset no_reset} {args {}} {enable EN_m3} {ready RDY_m3}}}} {args {{clock default_clock {osc CLK}} {reset default_reset {port RST_N} {clock default_clock}}}}} +{rg1 MOD {interface {{method _write _write {clock _clk__1} {reset _rst__1} {args {}} {results {}} {enable EN}} {method _read _read {clock _clk__1} {reset _rst__1} {args {}} {results {}}}}} {args {{reset _rst__1 {port RST} {clock _clk__1}} {clock _clk__1 {osc CLK} {gate CLK_GATE}}}}} {rg2 mkZeroSize_Sub {interface {{method m1 m1 {clock no_clock} {reset no_reset} {args {}} {results {}} {ready RDY_m1}} {method m2 m2 {clock default_clock} {reset no_reset} {args {{{port m2_y} {size 1}}}} {results {}} {enable EN_m2} {ready RDY_m2}} {method m3 m3 {clock default_clock} {reset no_reset} {args {}} {results {}} {enable EN_m3} {ready RDY_m3}}}} {args {{clock default_clock {osc CLK}} {reset default_reset {port RST_N} {clock default_clock}}}}} {rg1 MOD {ports {{RST Reset} {CLK Clock} {CLK_GATE Bool} {EN Bool}}}} {rg2 mkZeroSize_Sub {ports {{CLK Clock} {RST_N Reset} {RDY_m1 Bool} {m2_y Bool} {EN_m2 Bool} {RDY_m2 Bool} {EN_m3 Bool} {RDY_m3 Bool}}}} ---------- -{interface {{method m1 m1 {clock no_clock} {reset no_reset} {args {}} {ready RDY_m1}} {method m2 m2 {clock default_clock} {reset no_reset} {args {{{name m2_y} {port m2_y} {size 1}}}} {enable EN_m2} {ready RDY_m2}} {method m3 m3 {clock default_clock} {reset no_reset} {args {}} {enable EN_m3} {ready RDY_m3}}}} {args {{clock default_clock {osc CLK}} {reset default_reset {port RST_N} {clock default_clock}}}} +{interface {{method m1 m1 {clock no_clock} {reset no_reset} {args {}} {results {}} {ready RDY_m1}} {method m2 m2 {clock default_clock} {reset no_reset} {args {{{name m2_y} {port m2_y} {size 1}}}} {results {}} {enable EN_m2} {ready RDY_m2}} {method m3 m3 {clock default_clock} {reset no_reset} {args {}} {results {}} {enable EN_m3} {ready RDY_m3}}}} {args {{clock default_clock {osc CLK}} {reset default_reset {port RST_N} {clock default_clock}}}} {CLK Clock} {RST_N Reset} {RDY_m1 Bool} {m2_y Bool} {EN_m2 Bool} {RDY_m2 Bool} {EN_m3 Bool} {RDY_m3 Bool} ---------- diff --git a/testsuite/bsc.bugs/bluespec_inc/b1610/Test2.bs b/testsuite/bsc.bugs/bluespec_inc/b1610/Test2.bs index 20b45d091..9eb201aa5 100644 --- a/testsuite/bsc.bugs/bluespec_inc/b1610/Test2.bs +++ b/testsuite/bsc.bugs/bluespec_inc/b1610/Test2.bs @@ -1,7 +1,7 @@ package Test2 where interface RegPrimPairBoolMaybeBitSizeOfBit32_ = - _write :: Bit 34 -> ActionValue_ 0 + _write :: Bit 34 -> ActionValue_ (Bit 0) fromRegPrimPairBoolMaybeBitSizeOfBit32_ :: (Bits (Bool, Maybe (Bit (SizeOf (Bit 32)))) 34) => diff --git a/testsuite/bsc.bugs/bluespec_inc/b1758/b1758.exp b/testsuite/bsc.bugs/bluespec_inc/b1758/b1758.exp index e9dcc3bca..5a00dd66b 100644 --- a/testsuite/bsc.bugs/bluespec_inc/b1758/b1758.exp +++ b/testsuite/bsc.bugs/bluespec_inc/b1758/b1758.exp @@ -8,12 +8,10 @@ compile_verilog_pass ZeroBitValueMethod.bsv {} {-dexpanded -dATS} # Test that the method reference has been replaced by 0 in the evaluator if { $vtest == 1 } { - # XXX This still need to be fixed - find_regexp ZeroBitValueMethod.bsv.bsc-vcomp-out \ + find_regexp_fail ZeroBitValueMethod.bsv.bsc-vcomp-out \ {\= \.ZeroBitValueMethod\.getVal g} - # XXX AConv doesn't replace it either find_regexp ZeroBitValueMethod.bsv.bsc-vcomp-out \ - {\= g\.getVal} + {\=\=> Prelude\.\$display#0 "v \= %b" 0} } # ----- @@ -23,12 +21,10 @@ compile_verilog_pass ZeroBitActionValueMethod.bsv {} {-dexpanded -dATS} # Test that the method reference has been replaced by 0 in the evaluator if { $vtest == 1 } { - # XXX This still need to be fixed - find_regexp ZeroBitActionValueMethod.bsv.bsc-vcomp-out \ + find_regexp_fail ZeroBitActionValueMethod.bsv.bsc-vcomp-out \ {\= \.Prelude\.avValue_ ·0 \(\.ZeroBitActionValueMethod\.get g\)} - # At least AConv replaces it find_regexp ZeroBitActionValueMethod.bsv.bsc-vcomp-out \ - {g\.get\; p\.put 0\'d0\;} + {g\.get\; p\.put\;} } # ----- diff --git a/testsuite/bsc.codegen/foreign/BDPIActionValue_.bsv b/testsuite/bsc.codegen/foreign/BDPIActionValue_.bsv index 6c4fba560..681ab00ad 100644 --- a/testsuite/bsc.codegen/foreign/BDPIActionValue_.bsv +++ b/testsuite/bsc.codegen/foreign/BDPIActionValue_.bsv @@ -1,4 +1,4 @@ -import "BDPI" function ActionValue_#(32) my_time (Bit#(8) x); +import "BDPI" function ActionValue_#(Bit#(32)) my_time (Bit#(8) x); function ActionValue#(Bit#(32)) my_time2(Bit#(8) x); let y = my_time(x); diff --git a/testsuite/bsc.evaluator/mkTest.atsexpand.expected b/testsuite/bsc.evaluator/mkTest.atsexpand.expected index 63e14d11e..1dff74ee0 100644 --- a/testsuite/bsc.evaluator/mkTest.atsexpand.expected +++ b/testsuite/bsc.evaluator/mkTest.atsexpand.expected @@ -26,7 +26,7 @@ slots :: ABSTRACT: Prelude.VReg = RegUN []) [clock { osc: CLK gate: 1'd1 }, 32'd1] [] - meth types=[([], Nothing, Just (Bit 1)), ([Bit 1], Just (Bit 1), Nothing)] + meth types=[([], Nothing, [Bit 1]), ([Bit 1], Just (Bit 1), [])] port types=D_IN -> Prelude.Bool Q_OUT -> Prelude.Bool slots_1 :: ABSTRACT: Prelude.VReg = RegUN @@ -41,7 +41,7 @@ slots_1 :: ABSTRACT: Prelude.VReg = RegUN []) [clock { osc: CLK gate: 1'd1 }, 32'd1] [] - meth types=[([], Nothing, Just (Bit 1)), ([Bit 1], Just (Bit 1), Nothing)] + meth types=[([], Nothing, [Bit 1]), ([Bit 1], Just (Bit 1), [])] port types=D_IN -> Prelude.Bool Q_OUT -> Prelude.Bool ptr :: ABSTRACT: Prelude.VReg = RegUN @@ -56,7 +56,7 @@ ptr :: ABSTRACT: Prelude.VReg = RegUN []) [clock { osc: CLK gate: 1'd1 }, 32'd5] [] - meth types=[([], Nothing, Just (Bit 5)), ([Bit 5], Just (Bit 1), Nothing)] + meth types=[([], Nothing, [Bit 5]), ([Bit 5], Just (Bit 1), [])] port types=D_IN -> Prelude.Bit 5 Q_OUT -> Prelude.Bit 5 pred :: ABSTRACT: Prelude.VReg = RegUN @@ -71,7 +71,7 @@ pred :: ABSTRACT: Prelude.VReg = RegUN []) [clock { osc: CLK gate: 1'd1 }, 32'd1] [] - meth types=[([], Nothing, Just (Bit 1)), ([Bit 1], Just (Bit 1), Nothing)] + meth types=[([], Nothing, [Bit 1]), ([Bit 1], Just (Bit 1), [])] port types=D_IN -> Prelude.Bool Q_OUT -> Prelude.Bool -- AP rules diff --git a/testsuite/bsc.evaluator/mkTest.atsexpand.nolift.expandif.expected b/testsuite/bsc.evaluator/mkTest.atsexpand.nolift.expandif.expected index 342befbad..2c1fcb19f 100644 --- a/testsuite/bsc.evaluator/mkTest.atsexpand.nolift.expandif.expected +++ b/testsuite/bsc.evaluator/mkTest.atsexpand.nolift.expandif.expected @@ -26,7 +26,7 @@ slots :: ABSTRACT: Prelude.VReg = RegUN []) [clock { osc: CLK gate: 1'd1 }, 32'd1] [] - meth types=[([], Nothing, Just (Bit 1)), ([Bit 1], Just (Bit 1), Nothing)] + meth types=[([], Nothing, [Bit 1]), ([Bit 1], Just (Bit 1), [])] port types=D_IN -> Prelude.Bool Q_OUT -> Prelude.Bool slots_1 :: ABSTRACT: Prelude.VReg = RegUN @@ -41,7 +41,7 @@ slots_1 :: ABSTRACT: Prelude.VReg = RegUN []) [clock { osc: CLK gate: 1'd1 }, 32'd1] [] - meth types=[([], Nothing, Just (Bit 1)), ([Bit 1], Just (Bit 1), Nothing)] + meth types=[([], Nothing, [Bit 1]), ([Bit 1], Just (Bit 1), [])] port types=D_IN -> Prelude.Bool Q_OUT -> Prelude.Bool ptr :: ABSTRACT: Prelude.VReg = RegUN @@ -56,7 +56,7 @@ ptr :: ABSTRACT: Prelude.VReg = RegUN []) [clock { osc: CLK gate: 1'd1 }, 32'd5] [] - meth types=[([], Nothing, Just (Bit 5)), ([Bit 5], Just (Bit 1), Nothing)] + meth types=[([], Nothing, [Bit 5]), ([Bit 5], Just (Bit 1), [])] port types=D_IN -> Prelude.Bit 5 Q_OUT -> Prelude.Bit 5 pred :: ABSTRACT: Prelude.VReg = RegUN @@ -71,7 +71,7 @@ pred :: ABSTRACT: Prelude.VReg = RegUN []) [clock { osc: CLK gate: 1'd1 }, 32'd1] [] - meth types=[([], Nothing, Just (Bit 1)), ([Bit 1], Just (Bit 1), Nothing)] + meth types=[([], Nothing, [Bit 1]), ([Bit 1], Just (Bit 1), [])] port types=D_IN -> Prelude.Bool Q_OUT -> Prelude.Bool -- AP rules diff --git a/testsuite/bsc.evaluator/sysITransformConstantAcrossEquals.atsexpand.expected b/testsuite/bsc.evaluator/sysITransformConstantAcrossEquals.atsexpand.expected index e9b7f4719..bdff286a1 100644 --- a/testsuite/bsc.evaluator/sysITransformConstantAcrossEquals.atsexpand.expected +++ b/testsuite/bsc.evaluator/sysITransformConstantAcrossEquals.atsexpand.expected @@ -26,7 +26,7 @@ r :: ABSTRACT: Prelude.VReg = RegUN []) [clock { osc: CLK gate: 1'd1 }, 32'd3] [] - meth types=[([], Nothing, Just (Bit 3)), ([Bit 3], Just (Bit 1), Nothing)] + meth types=[([], Nothing, [Bit 3]), ([Bit 3], Just (Bit 1), [])] port types=D_IN -> Prelude.Bit 3 Q_OUT -> Prelude.Bit 3 x :: ABSTRACT: Prelude.VReg = RegUN @@ -41,7 +41,7 @@ x :: ABSTRACT: Prelude.VReg = RegUN []) [clock { osc: CLK gate: 1'd1 }, 32'd2] [] - meth types=[([], Nothing, Just (Bit 2)), ([Bit 2], Just (Bit 1), Nothing)] + meth types=[([], Nothing, [Bit 2]), ([Bit 2], Just (Bit 1), [])] port types=D_IN -> Prelude.Bit 2 Q_OUT -> Prelude.Bit 2 y :: ABSTRACT: Prelude.VReg = RegUN @@ -56,7 +56,7 @@ y :: ABSTRACT: Prelude.VReg = RegUN []) [clock { osc: CLK gate: 1'd1 }, 32'd2] [] - meth types=[([], Nothing, Just (Bit 2)), ([Bit 2], Just (Bit 1), Nothing)] + meth types=[([], Nothing, [Bit 2]), ([Bit 2], Just (Bit 1), [])] port types=D_IN -> Prelude.Bit 2 Q_OUT -> Prelude.Bit 2 z :: ABSTRACT: Prelude.VReg = RegUN @@ -71,7 +71,7 @@ z :: ABSTRACT: Prelude.VReg = RegUN []) [clock { osc: CLK gate: 1'd1 }, 32'd2] [] - meth types=[([], Nothing, Just (Bit 2)), ([Bit 2], Just (Bit 1), Nothing)] + meth types=[([], Nothing, [Bit 2]), ([Bit 2], Just (Bit 1), [])] port types=D_IN -> Prelude.Bit 2 Q_OUT -> Prelude.Bit 2 -- AP rules diff --git a/testsuite/bsc.evaluator/sysShiftMult.ats.expected b/testsuite/bsc.evaluator/sysShiftMult.ats.expected index 82f846b43..c2250b423 100644 --- a/testsuite/bsc.evaluator/sysShiftMult.ats.expected +++ b/testsuite/bsc.evaluator/sysShiftMult.ats.expected @@ -26,7 +26,7 @@ x :: ABSTRACT: Prelude.VReg = RegN []) [clock { osc: CLK gate: 1'd1 }, reset { wire: RST_N }, 32'd32, 32'd17] [] - meth types=[([], Nothing, Just (Bit 32)), ([Bit 32], Just (Bit 1), Nothing)] + meth types=[([], Nothing, [Bit 32]), ([Bit 32], Just (Bit 1), [])] port types=D_IN -> Prelude.Bit 32 Q_OUT -> Prelude.Bit 32 y :: ABSTRACT: Prelude.VReg = RegN @@ -41,7 +41,7 @@ y :: ABSTRACT: Prelude.VReg = RegN []) [clock { osc: CLK gate: 1'd1 }, reset { wire: RST_N }, 32'd32, 32'd24] [] - meth types=[([], Nothing, Just (Bit 32)), ([Bit 32], Just (Bit 1), Nothing)] + meth types=[([], Nothing, [Bit 32]), ([Bit 32], Just (Bit 1), [])] port types=D_IN -> Prelude.Bit 32 Q_OUT -> Prelude.Bit 32 -- AP local definitions diff --git a/testsuite/bsc.if/split/MultiPortAVNoSplit.bs b/testsuite/bsc.if/split/MultiPortAVNoSplit.bs new file mode 100644 index 000000000..d2608e670 --- /dev/null +++ b/testsuite/bsc.if/split/MultiPortAVNoSplit.bs @@ -0,0 +1,24 @@ +package MultiPortAVNoSplit where + +import SplitPorts + +struct Pair = + p1 :: Bool + p2 :: Bool + deriving (Bits) + +-- Port-split ActionValue result in iSplitIface (ShallowSplit value stays a +-- tuple, not Bit#(n)), action left unsplit (one rule). +interface Ifc = + avmeth :: ActionValue (ShallowSplit Pair) + +{-# synthesize sysMultiPortAVNoSplit #-} +sysMultiPortAVNoSplit :: Module Ifc +sysMultiPortAVNoSplit = + module + cond :: Reg Bool <- mkRegU + x :: Reg Bool <- mkRegU + interface + avmeth = + do nosplitIf cond (x := True) (x := False) + return (ShallowSplit (Pair { p1 = cond; p2 = x })) diff --git a/testsuite/bsc.if/split/MultiPortAVSplit.bs b/testsuite/bsc.if/split/MultiPortAVSplit.bs new file mode 100644 index 000000000..47d8ddd5a --- /dev/null +++ b/testsuite/bsc.if/split/MultiPortAVSplit.bs @@ -0,0 +1,25 @@ +package MultiPortAVSplit where + +import SplitPorts + +struct Pair = + p1 :: Bool + p2 :: Bool + deriving (Bits) + +-- Port-split ActionValue result in iSplitIface: ShallowSplit keeps the value a +-- tuple, not Bit#(n). splitIf also splits the action into two rules (the value +-- is shared). See MultiPortAVNoSplit for the unsplit case. +interface Ifc = + avmeth :: ActionValue (ShallowSplit Pair) + +{-# synthesize sysMultiPortAVSplit #-} +sysMultiPortAVSplit :: Module Ifc +sysMultiPortAVSplit = + module + cond :: Reg Bool <- mkRegU + x :: Reg Bool <- mkRegU + interface + avmeth = + do splitIf cond (x := True) (x := False) + return (ShallowSplit (Pair { p1 = cond; p2 = x })) diff --git a/testsuite/bsc.if/split/splitIf.exp b/testsuite/bsc.if/split/splitIf.exp index 36c6a9671..73758685f 100644 --- a/testsuite/bsc.if/split/splitIf.exp +++ b/testsuite/bsc.if/split/splitIf.exp @@ -119,3 +119,8 @@ count_rules_after_splitIf Cond_AV_NoSplit.bsv 3 {sysCond_AV_NoSplit} {-split-if} count_rules_after_splitIf Cond_MethodArg_Split.bsv 1 {sysCond_MethodArg_Split} count_rules_after_splitIf Cond_MethodArg_NoSplit.bsv 3 {sysCond_MethodArg_NoSplit} {-split-if} +# Port-split ActionValue result in iSplitIface (ShallowSplit value stays a tuple, +# not Bit#(n)). NoSplit: action unsplit; Split: splitIf also splits the action. +count_rules_after_splitIf MultiPortAVNoSplit.bs 1 {sysMultiPortAVNoSplit} +count_rules_after_splitIf MultiPortAVSplit.bs 2 {sysMultiPortAVSplit} + diff --git a/testsuite/bsc.interra/messages/EResources/EResources.bs.bsc-vcomp-out.expected b/testsuite/bsc.interra/messages/EResources/EResources.bs.bsc-vcomp-out.expected index c2834ce68..6b022d6a2 100755 --- a/testsuite/bsc.interra/messages/EResources/EResources.bs.bsc-vcomp-out.expected +++ b/testsuite/bsc.interra/messages/EResources/EResources.bs.bsc-vcomp-out.expected @@ -5,5 +5,5 @@ Verilog file created: subtractor.v code generation for mkDifference starts Error: "EResources.bs", line 43, column 13: (G0002) `m.minus' needs more than 1 ports for the following uses: - `m.minus x__h369 y__h370' at "EResources.bs", line 43, column 13 - `m.minus y__h370 x__h369' at "EResources.bs", line 43, column 13 + `m.minus x___d1 y___d2' at "EResources.bs", line 43, column 13 + `m.minus y___d2 x___d1' at "EResources.bs", line 43, column 13 diff --git a/testsuite/bsc.lib/Prelude/TupleSize.bs b/testsuite/bsc.lib/Prelude/TupleSize.bs index 8596eb9e6..2f05acc21 100644 --- a/testsuite/bsc.lib/Prelude/TupleSize.bs +++ b/testsuite/bsc.lib/Prelude/TupleSize.bs @@ -4,7 +4,7 @@ package TupleSize where -- Helper function that requires TupleSize constraint tupleSize :: (TupleSize t n) => t -> Integer -tupleSize _ = valueOf n +tupleSize _ = valueOf (TTupleSize t) {-# verilog sysTupleSize #-} sysTupleSize :: Module Empty diff --git a/testsuite/bsc.misc/lambda_calculus/lc-sysTb.out.expected b/testsuite/bsc.misc/lambda_calculus/lc-sysTb.out.expected index b8f66649d..d7eb40301 100644 --- a/testsuite/bsc.misc/lambda_calculus/lc-sysTb.out.expected +++ b/testsuite/bsc.misc/lambda_calculus/lc-sysTb.out.expected @@ -31,16 +31,16 @@ dim_sysTb = rule_RL_r0_sysTb :: MOD_sysTb -> (Bool, MOD_sysTb, ()); rule_RL_r0_sysTb = (\ (state0 :: MOD_sysTb) -> - let { (def_c1__h532 :: Bit #51) = meth_read_RegN (inst_c1__sysTb state0) - ; (def_c2__h543 :: Bit #51) = meth_read_RegN (inst_c2__sysTb state0) + let { (def_c2___d6 :: Bit #51) = meth_read_RegN (inst_c2__sysTb state0) + ; (def_c1___d5 :: Bit #51) = meth_read_RegN (inst_c1__sysTb state0) ; (def_state___d2 :: Bit #2) = meth_read_RegN (inst_state__sysTb state0) ; (def_gcd_RDY_start____d1 :: Bool) = meth_RDY_start_sysMethods (inst_gcd__sysTb state0) - ; (def_add___d7 :: Bit #51) = noinline_add def_c1__h532 (3 :: Bit #51) - ; (def_add___d8 :: Bit #51) = noinline_add def_c2__h543 (2 :: Bit #51) + ; (def_add___d7 :: Bit #51) = noinline_add def_c1___d5 (3 :: Bit #51) + ; (def_add___d8 :: Bit #51) = noinline_add def_c2___d6 (2 :: Bit #51) ; (def_state_EQ_0___d3 :: Bool) = primEQ def_state___d2 (0 :: Bit #2) ; (def_gcd_RDY_start_AND_state_EQ_0___d4 :: Bool) = def_gcd_RDY_start____d1 && def_state_EQ_0___d3 ; (act1 :: (Bool, MOD_sysMethods, ())) = - meth_start_sysMethods def_c1__h532 def_c2__h543 (inst_gcd__sysTb state0) + meth_start_sysMethods def_c1___d5 def_c2___d6 (inst_gcd__sysTb state0) ; (guard1 :: Bool) = fst3 act1 ; (state1 :: MOD_sysTb) = state0 { inst_gcd__sysTb = snd3 act1 } ; (act2 :: (Bool, MOD_RegN #51, ())) = meth_write_RegN def_add___d7 (inst_c1__sysTb state1) @@ -58,14 +58,14 @@ rule_RL_r0_sysTb = rule_RL_r1_sysTb :: MOD_sysTb -> (Bool, MOD_sysTb, ()); rule_RL_r1_sysTb = (\ (state0 :: MOD_sysTb) -> - let { (def_c1__h532 :: Bit #51) = meth_read_RegN (inst_c1__sysTb state0) - ; (def_c2__h543 :: Bit #51) = meth_read_RegN (inst_c2__sysTb state0) + let { (def_c2___d6 :: Bit #51) = meth_read_RegN (inst_c2__sysTb state0) + ; (def_c1___d5 :: Bit #51) = meth_read_RegN (inst_c1__sysTb state0) ; (def_state___d2 :: Bit #2) = meth_read_RegN (inst_state__sysTb state0) - ; (def_add___d7 :: Bit #51) = noinline_add def_c1__h532 (3 :: Bit #51) - ; (def_add___d8 :: Bit #51) = noinline_add def_c2__h543 (2 :: Bit #51) + ; (def_add___d7 :: Bit #51) = noinline_add def_c1___d5 (3 :: Bit #51) + ; (def_add___d8 :: Bit #51) = noinline_add def_c2___d6 (2 :: Bit #51) ; (def_state_EQ_1___d9 :: Bool) = primEQ def_state___d2 (1 :: Bit #2) ; (act1 :: (Bool, MOD_sysMethods, Bit #51)) = - meth_start_and_result_sysMethods def_c1__h532 def_c2__h543 (inst_gcd__sysTb state0) + meth_start_and_result_sysMethods def_c1___d5 def_c2___d6 (inst_gcd__sysTb state0) ; (guard1 :: Bool) = fst3 act1 ; (state1 :: MOD_sysTb) = state0 { inst_gcd__sysTb = snd3 act1 } ; (def_gcd_start_and_result___d10 :: Bit #51) = thd act1 @@ -121,8 +121,8 @@ rule_RL_r2_sysTb = rule_RL_exit_sysTb :: MOD_sysTb -> (Bool, MOD_sysTb, ()); rule_RL_exit_sysTb = (\ (state0 :: MOD_sysTb) -> - let { (def_c1__h532 :: Bit #51) = meth_read_RegN (inst_c1__sysTb state0) - ; (def_c1_ULE_100___d21 :: Bool) = primULE def_c1__h532 (100 :: Bit #51) + let { (def_c1___d5 :: Bit #51) = meth_read_RegN (inst_c1__sysTb state0) + ; (def_c1_ULE_100___d21 :: Bool) = primULE def_c1___d5 (100 :: Bit #51) ; (def_TASK_time___d23 :: Bit #64) = (primAny :: Bit #64) } in mktuple (not def_c1_ULE_100___d21) state0 ()); diff --git a/testsuite/bsc.misc/sal/CTX_sysTb.sal.expected b/testsuite/bsc.misc/sal/CTX_sysTb.sal.expected index a2f5775ea..cb4b6d151 100644 --- a/testsuite/bsc.misc/sal/CTX_sysTb.sal.expected +++ b/testsuite/bsc.misc/sal/CTX_sysTb.sal.expected @@ -19,17 +19,17 @@ BEGIN #) ; rule_RL_r0 (state0 : STATE) : [ BOOLEAN, STATE ] = - LET def_c1__h532 : Bit{51}!T = CTX_RegN{51}!meth_read(state0.inst_c1) - IN LET def_c2__h543 : Bit{51}!T = CTX_RegN{51}!meth_read(state0.inst_c2) + LET def_c2___d6 : Bit{51}!T = CTX_RegN{51}!meth_read(state0.inst_c2) + IN LET def_c1___d5 : Bit{51}!T = CTX_RegN{51}!meth_read(state0.inst_c1) IN LET def_state___d2 : Bit{2}!T = CTX_RegN{2}!meth_read(state0.inst_state) IN LET def_gcd_RDY_start____d1 : BOOLEAN = CTX_sysMethods!meth_RDY_start(state0.inst_gcd) - IN LET def_add___d7 : Bit{51}!T = CTX_module_add!fn(def_c1__h532, Bit{51}!mkConst(3)) - IN LET def_add___d8 : Bit{51}!T = CTX_module_add!fn(def_c2__h543, Bit{51}!mkConst(2)) + IN LET def_add___d7 : Bit{51}!T = CTX_module_add!fn(def_c1___d5, Bit{51}!mkConst(3)) + IN LET def_add___d8 : Bit{51}!T = CTX_module_add!fn(def_c2___d6, Bit{51}!mkConst(2)) IN LET def_state_EQ_0___d3 : BOOLEAN = Prim1{2}!primEQ(def_state___d2, Bit{2}!mkConst(0)) IN LET def_gcd_RDY_start_AND_state_EQ_0___d4 : BOOLEAN = def_gcd_RDY_start____d1 AND def_state_EQ_0___d3 IN LET act1 : [ CTX_sysMethods!STATE, Unit!T ] = - CTX_sysMethods!meth_start(def_c1__h532, def_c2__h543, state0.inst_gcd) + CTX_sysMethods!meth_start(def_c1___d5, def_c2___d6, state0.inst_gcd) IN LET state1 : STATE = state0 WITH .inst_gcd := act1.1 IN LET act2 : [ CTX_RegN{51}!STATE, Unit!T ] = CTX_RegN{51}!meth_write(def_add___d7, state1.inst_c1) IN LET state2 : STATE = state1 WITH .inst_c1 := act2.1 @@ -41,14 +41,14 @@ BEGIN IN ( def_gcd_RDY_start_AND_state_EQ_0___d4, state4 ) ; rule_RL_r1 (state0 : STATE) : [ BOOLEAN, STATE ] = - LET def_c1__h532 : Bit{51}!T = CTX_RegN{51}!meth_read(state0.inst_c1) - IN LET def_c2__h543 : Bit{51}!T = CTX_RegN{51}!meth_read(state0.inst_c2) + LET def_c2___d6 : Bit{51}!T = CTX_RegN{51}!meth_read(state0.inst_c2) + IN LET def_c1___d5 : Bit{51}!T = CTX_RegN{51}!meth_read(state0.inst_c1) IN LET def_state___d2 : Bit{2}!T = CTX_RegN{2}!meth_read(state0.inst_state) - IN LET def_add___d7 : Bit{51}!T = CTX_module_add!fn(def_c1__h532, Bit{51}!mkConst(3)) - IN LET def_add___d8 : Bit{51}!T = CTX_module_add!fn(def_c2__h543, Bit{51}!mkConst(2)) + IN LET def_add___d7 : Bit{51}!T = CTX_module_add!fn(def_c1___d5, Bit{51}!mkConst(3)) + IN LET def_add___d8 : Bit{51}!T = CTX_module_add!fn(def_c2___d6, Bit{51}!mkConst(2)) IN LET def_state_EQ_1___d9 : BOOLEAN = Prim1{2}!primEQ(def_state___d2, Bit{2}!mkConst(1)) IN LET act1 : [ CTX_sysMethods!STATE, Bit{51}!T ] = - CTX_sysMethods!meth_start_and_result(def_c1__h532, def_c2__h543, state0.inst_gcd) + CTX_sysMethods!meth_start_and_result(def_c1___d5, def_c2___d6, state0.inst_gcd) IN LET state1 : STATE = state0 WITH .inst_gcd := act1.1 IN LET def_gcd_start_and_result___d10 : Bit{51}!T = act1.2 IN LET def_gcd_start_and_result_0_PLUS_1___d11 : Bit{51}!T = @@ -87,8 +87,8 @@ BEGIN IN ( def_gcd_RDY_result__4_AND_state_EQ_2_5___d16, state2 ) ; rule_RL_exit (state0 : STATE) : [ BOOLEAN, STATE ] = - LET def_c1__h532 : Bit{51}!T = CTX_RegN{51}!meth_read(state0.inst_c1) - IN LET def_c1_ULE_100___d21 : BOOLEAN = Prim1{51}!primULE(def_c1__h532, Bit{51}!mkConst(100)) + LET def_c1___d5 : Bit{51}!T = CTX_RegN{51}!meth_read(state0.inst_c1) + IN LET def_c1_ULE_100___d21 : BOOLEAN = Prim1{51}!primULE(def_c1___d5, Bit{51}!mkConst(100)) IN LET def_TASK_time___d23 : Bit{64}!T = Bit{64}!undef IN ( NOT def_c1_ULE_100___d21, state0 ) ; diff --git a/testsuite/bsc.names/signal_names/LiteralNum_ENotation.bsv.bsc-vcomp-out.expected b/testsuite/bsc.names/signal_names/LiteralNum_ENotation.bsv.bsc-vcomp-out.expected index 4fbc93c46..9e7784b8a 100644 --- a/testsuite/bsc.names/signal_names/LiteralNum_ENotation.bsv.bsc-vcomp-out.expected +++ b/testsuite/bsc.names/signal_names/LiteralNum_ENotation.bsv.bsc-vcomp-out.expected @@ -30,7 +30,7 @@ rg_start :: ABSTRACT: Prelude.VReg = RegN []) [clock { osc: CLK gate: 1'd1 }, reset { wire: RST_N }, 32'd1, 1'd1] [] - meth types=[([], Nothing, Just (Bit 1)), ([Bit 1], Just (Bit 1), Nothing)] + meth types=[([], Nothing, [Bit 1]), ([Bit 1], Just (Bit 1), [])] port types=D_IN -> Prelude.Bool Q_OUT -> Prelude.Bool -- AP local definitions diff --git a/testsuite/bsc.names/signal_names/Method.bsv.bsc-vcomp-out.expected b/testsuite/bsc.names/signal_names/Method.bsv.bsc-vcomp-out.expected index 3c77e5980..e7a70d288 100644 --- a/testsuite/bsc.names/signal_names/Method.bsv.bsc-vcomp-out.expected +++ b/testsuite/bsc.names/signal_names/Method.bsv.bsc-vcomp-out.expected @@ -35,9 +35,9 @@ rg :: ABSTRACT: PreludeBSV._PreludeBSV.VRWire103 = RWire [(WSET, WHAS), (WVAL, WGET)]) [32'd8, clock { osc: CLK gate: 1'd1 }, reset { wire: RST_N }] [] - meth types=[([Bit 8], Just (Bit 1), Nothing), - ([], Nothing, Just (Bit 1)), - ([], Nothing, Just (Bit 8))] + meth types=[([Bit 8], Just (Bit 1), []), + ([], Nothing, [Bit 1]), + ([], Nothing, [Bit 8])] port types=WGET -> Prelude.Bit 8 WHAS -> Prelude.Bool WVAL -> Prelude.Bit 8 diff --git a/testsuite/bsc.names/signal_names/MethodActionValue.bsv.bsc-vcomp-out.expected b/testsuite/bsc.names/signal_names/MethodActionValue.bsv.bsc-vcomp-out.expected index 5d88c8eb0..4b22211c9 100644 --- a/testsuite/bsc.names/signal_names/MethodActionValue.bsv.bsc-vcomp-out.expected +++ b/testsuite/bsc.names/signal_names/MethodActionValue.bsv.bsc-vcomp-out.expected @@ -81,7 +81,7 @@ i :: ABSTRACT: MethodActionValue.Ifc­ = mkMethodActionValue_Sub []) [clock { osc: CLK gate: 1'd1 }, reset { wire: RST_N }] [] - meth types=[([], Just (Bit 1), Just (Bit 8)), ([], Nothing, Just (Bit 1))] + meth types=[([], Just (Bit 1), [Bit 8]), ([], Nothing, [Bit 1])] port types=m -> Prelude.Bit 8 -- AP local definitions i_m_PLUS_8___d2 :: Bit 8; diff --git a/testsuite/bsc.names/signal_names/MethodRead.bsv.bsc-vcomp-out.expected b/testsuite/bsc.names/signal_names/MethodRead.bsv.bsc-vcomp-out.expected index d6a707799..bdb5827d3 100644 --- a/testsuite/bsc.names/signal_names/MethodRead.bsv.bsc-vcomp-out.expected +++ b/testsuite/bsc.names/signal_names/MethodRead.bsv.bsc-vcomp-out.expected @@ -29,7 +29,7 @@ rg :: ABSTRACT: Prelude.VReg = RegUN []) [clock { osc: CLK gate: 1'd1 }, 32'd8] [] - meth types=[([], Nothing, Just (Bit 8)), ([Bit 8], Just (Bit 1), Nothing)] + meth types=[([], Nothing, [Bit 8]), ([Bit 8], Just (Bit 1), [])] port types=D_IN -> Prelude.Bit 8 Q_OUT -> Prelude.Bit 8 -- AP local definitions diff --git a/testsuite/bsc.scheduler/SplitIf.bsv.bsc-sched-out.expected b/testsuite/bsc.scheduler/SplitIf.bsv.bsc-sched-out.expected index 3b9ed6a6d..08348949d 100644 --- a/testsuite/bsc.scheduler/SplitIf.bsv.bsc-sched-out.expected +++ b/testsuite/bsc.scheduler/SplitIf.bsv.bsc-sched-out.expected @@ -70,7 +70,7 @@ order: [RL_r, RL_toggleDir, RL_done, RL_incr] (dir.read, [(dir.read, 1)]), (dir.write, [(dir.write NOT_dir___d2, 1)]), (test.RDY_xfer, [(test.RDY_xfer, 1)]), - (test.xfer, [(test.xfer dir__h205, 1)])] + (test.xfer, [(test.xfer dir___d1, 1)])] ----- diff --git a/testsuite/bsc.scheduler/SplitIf2.bsv.bsc-sched-out.expected b/testsuite/bsc.scheduler/SplitIf2.bsv.bsc-sched-out.expected index aca7ed8ea..51f702f9d 100644 --- a/testsuite/bsc.scheduler/SplitIf2.bsv.bsc-sched-out.expected +++ b/testsuite/bsc.scheduler/SplitIf2.bsv.bsc-sched-out.expected @@ -75,7 +75,7 @@ order: [RL_r, RL_toggleDir, RL_done, RL_incr] (dir.read, [(dir.read, 1)]), (dir.write, [(dir.write NOT_dir___d2, 1)]), (test.RDY_xfer, [(test.RDY_xfer, 1)]), - (test.xfer, [(test.xfer dir__h208, 1)])] + (test.xfer, [(test.xfer dir___d1, 1)])] ----- diff --git a/testsuite/bsc.scheduler/avmeth/AVArgUse_C.bsv.bsc-sched-out.expected b/testsuite/bsc.scheduler/avmeth/AVArgUse_C.bsv.bsc-sched-out.expected index c2842b2ee..5f1f97015 100644 --- a/testsuite/bsc.scheduler/avmeth/AVArgUse_C.bsv.bsc-sched-out.expected +++ b/testsuite/bsc.scheduler/avmeth/AVArgUse_C.bsv.bsc-sched-out.expected @@ -45,7 +45,7 @@ order: [RL_rA, RL_rB] ----- === resources (AVArgUse_C sysAVArgUse_C): -[(dut.m, [(dut.m r1__h275 32'd1, 1), (dut.m 32'd5 r1__h275, 1)]), +[(dut.m, [(dut.m r1___d1 32'd1, 1), (dut.m 32'd5 r1___d1, 1)]), (r1.read, [(r1.read, 1)]), (r1.write, [(r1.write r1_PLUS_1___d4, 1)])] diff --git a/testsuite/bsc.scheduler/avmeth/AVArgUse_SBR.bsv.bsc-sched-out.expected b/testsuite/bsc.scheduler/avmeth/AVArgUse_SBR.bsv.bsc-sched-out.expected index 61a1e33fd..f3e1b2f46 100644 --- a/testsuite/bsc.scheduler/avmeth/AVArgUse_SBR.bsv.bsc-sched-out.expected +++ b/testsuite/bsc.scheduler/avmeth/AVArgUse_SBR.bsv.bsc-sched-out.expected @@ -43,7 +43,7 @@ order: [RL_rB, RL_rA] ----- === resources (AVArgUse_SBR sysAVArgUse_SBR): -[(dut.m, [(dut.m r1__h275 32'd1, 1), (dut.m 32'd5 r1__h275, 1)]), +[(dut.m, [(dut.m r1___d1 32'd1, 1), (dut.m 32'd5 r1___d1, 1)]), (r1.read, [(r1.read, 1)]), (r1.write, [(r1.write r1_PLUS_1___d4, 1)])] diff --git a/testsuite/bsc.scheduler/paths/AVEnArgMuxPath.bs b/testsuite/bsc.scheduler/paths/AVEnArgMuxPath.bs new file mode 100644 index 000000000..29ba01573 --- /dev/null +++ b/testsuite/bsc.scheduler/paths/AVEnArgMuxPath.bs @@ -0,0 +1,48 @@ +package AVEnArgMuxPath where + +import SplitPorts +import Vector + +struct Pair = + p1 :: Bool + p2 :: Bool + deriving (Bits) + +-- Single-ported combinational lookup submodule (RegFile-like): the read is +-- combinational from the index argument. +interface LookupIfc = + lookup :: Bit 4 -> Bool + +{-# synthesize mkAVEnArgMuxSub #-} +mkAVEnArgMuxSub :: Module LookupIfc +mkAVEnArgMuxSub = + module + rs :: Vector 16 (Reg Bool) <- replicateM (mkReg False) + interface + lookup i = (select rs i)._read + +-- ActionValue method whose SPLIT input port upd_1_p1 selects an index into +-- the single-ported submodule. Because a rule in the same module also uses +-- that one read port, BSC muxes the read index by the method's enable, so +-- the split output port upd_p1 is combinational on BOTH the split input +-- (upd_1_p1) and the enable (EN_upd). This exercises the enable-to-output +-- edge for a split AV result. upd_p2 is registered: no combinational path. +interface AVIfc = + upd :: ShallowSplit Pair -> ActionValue (ShallowSplit Pair) + +{-# synthesize mkAVEnArgMuxPath #-} +mkAVEnArgMuxPath :: Module AVIfc +mkAVEnArgMuxPath = + module + sub <- mkAVEnArgMuxSub + ptr :: Reg (Bit 4) <- mkRegU + r :: Reg Bool <- mkReg False + rules + "bump": when True ==> + action + ptr := ptr + 1 + r := sub.lookup ptr + interface + upd (ShallowSplit a) = + do ptr := ptr + (if a.p1 then 1 else 0) -- makes the rule conflict with the method + return (ShallowSplit (Pair { p1 = sub.lookup (if a.p1 then 3 else 5); p2 = r })) diff --git a/testsuite/bsc.scheduler/paths/AVSplitInPath.bs b/testsuite/bsc.scheduler/paths/AVSplitInPath.bs new file mode 100644 index 000000000..5c8481c3f --- /dev/null +++ b/testsuite/bsc.scheduler/paths/AVSplitInPath.bs @@ -0,0 +1,26 @@ +package AVSplitInPath where + +import SplitPorts + +struct Pair = + p1 :: Bool + p2 :: Bool + deriving (Bits) + +interface AVIfc = + -- ActionValue method with BOTH a split input arg and a split result. + -- The output p1 is combinational from the *crossed* input field p2, and + -- the output p2 is combinational from the input field p1. This pins down + -- per-input-port path tracking: each split output port depends on exactly + -- one specific split input port, and the "diagonal" edges are absent. + upd :: ShallowSplit Pair -> ActionValue (ShallowSplit Pair) + +{-# synthesize mkAVSplitInPath #-} +mkAVSplitInPath :: Module AVIfc +mkAVSplitInPath = + module + r :: Reg Bool <- mkReg False + interface + upd (ShallowSplit a) = + do r := a.p1 + return (ShallowSplit (Pair { p1 = a.p2; p2 = a.p1 })) diff --git a/testsuite/bsc.scheduler/paths/AVSubmodInPath.bs b/testsuite/bsc.scheduler/paths/AVSubmodInPath.bs new file mode 100644 index 000000000..8102d3b97 --- /dev/null +++ b/testsuite/bsc.scheduler/paths/AVSubmodInPath.bs @@ -0,0 +1,42 @@ +package AVSubmodInPath where + +import SplitPorts + +struct Pair = + p1 :: Bool + p2 :: Bool + deriving (Bits) + +-- A value submodule with a split input and split output: result p1 is +-- combinational from input p1, result p2 from a register. +interface SubIfc = + get :: ShallowSplit Pair -> ShallowSplit Pair + +{-# synthesize mkAVSubmodInSub #-} +mkAVSubmodInSub :: Module SubIfc +mkAVSubmodInSub = + module + r :: Reg Bool <- mkReg False + interface + get (ShallowSplit a) = ShallowSplit (Pair { p1 = a.p1; p2 = r }) + +-- A top-level ActionValue method whose split input arg is wired straight +-- into the submodule's split input, and whose split result is the +-- submodule's split result. This threads per-port paths through a +-- submodule from an AV method: upd_1_p1 -> upd_p1 only. upd_1_p2 reaches +-- only the submodule's registered field, so no path to either output, and +-- upd_p2 (the registered field) has no combinational path at all. +interface AVIfc = + upd :: ShallowSplit Pair -> ActionValue (ShallowSplit Pair) + +{-# synthesize mkAVSubmodInPath #-} +mkAVSubmodInPath :: Module AVIfc +mkAVSubmodInPath = + module + s <- mkAVSubmodInSub + cnt :: Reg Bool <- mkReg False + interface + upd (ShallowSplit a) = + do cnt := a.p2 + case s.get (ShallowSplit a) of + ShallowSplit res -> return (ShallowSplit res) diff --git a/testsuite/bsc.scheduler/paths/ArgSelectorPath.bs b/testsuite/bsc.scheduler/paths/ArgSelectorPath.bs new file mode 100644 index 000000000..82ba75701 --- /dev/null +++ b/testsuite/bsc.scheduler/paths/ArgSelectorPath.bs @@ -0,0 +1,31 @@ +package ArgSelectorPath where + +import SplitPorts + +-- Split input: a selector field, one data field, one unused field. +struct Cmd = + sel :: Bool + d :: Bool + dead :: Bool + deriving (Bits) + +interface TopIfc = + -- split input (3 ports), single unsplit Bool output + run :: ShallowSplit Cmd -> Bool + +-- The synthesized module takes a Bool MODULE ARGUMENT (port input) 'v'. +-- A split method-input field 'sel' selects between the module-argument-driven +-- value 'v' and the split data field 'd'. The path therefore ENTERS via the +-- split method input (run_1_sel / run_1_d) and exits through logic that also +-- depends on the module argument 'v': +-- run = sel ? v : d +-- so the output 'run' is combinationally reachable from run_1_sel, run_1_d, +-- AND the module-argument port v. The unused field 'dead' yields no path. +-- This exercises a split method input feeding a mux whose other leg is the +-- module's own argument port (the missing module-argument + split-input case). +{-# synthesize mkArgSelectorPath #-} +mkArgSelectorPath :: Bool -> Module TopIfc +mkArgSelectorPath v = + module + interface + run (ShallowSplit c) = if c.sel then v else c.d diff --git a/testsuite/bsc.scheduler/paths/DeepLeafBasic.bs b/testsuite/bsc.scheduler/paths/DeepLeafBasic.bs new file mode 100644 index 000000000..f4a1603c0 --- /dev/null +++ b/testsuite/bsc.scheduler/paths/DeepLeafBasic.bs @@ -0,0 +1,28 @@ +package DeepLeafBasic where + +import SplitPorts + +-- Inner nested struct +struct Inner = + a :: Bool + b :: Bool + deriving (Bits) + +-- Outer struct whose fields are themselves structs +struct Outer = + x :: Inner + y :: Inner + deriving (Bits) + +interface Ifc = + get :: DeepSplit Outer -> DeepSplit Outer + +{-# synthesize mkDeepLeafBasic #-} +mkDeepLeafBasic :: Module Ifc +mkDeepLeafBasic = + module + r :: Reg Bool <- mkReg False + interface + get (DeepSplit a) = + DeepSplit (Outer { x = Inner { a = a.x.a; b = r } + ; y = Inner { a = r; b = a.y.b } }) diff --git a/testsuite/bsc.scheduler/paths/DeepLeafConst.bs b/testsuite/bsc.scheduler/paths/DeepLeafConst.bs new file mode 100644 index 000000000..e7fcc5eb0 --- /dev/null +++ b/testsuite/bsc.scheduler/paths/DeepLeafConst.bs @@ -0,0 +1,35 @@ +package DeepLeafConst where + +import SplitPorts + +-- Nested struct (Outer field is itself a struct). +struct Inner = + a :: Bool + b :: Bool + deriving (Bits) + +struct Outer = + x :: Inner + y :: Inner + deriving (Bits) + +interface Ifc = + get :: DeepSplit Outer -> DeepSplit Outer + +-- Each of the four deep leaves is driven by a different kind of source, so +-- path analysis must produce a path for exactly one of them: +-- get_x_a <- a.x.a (combinational input => get_1_x_a -> get_x_a) +-- get_x_b <- True (constant => no path) +-- get_y_a <- r (register => no path) +-- get_y_b <- False (constant => no path) +-- Crucially, only ONE input leaf is even used, so none of the other input +-- leaves (get_1_x_b, get_1_y_a, get_1_y_b) may appear as a path source. +{-# synthesize mkDeepLeafConst #-} +mkDeepLeafConst :: Module Ifc +mkDeepLeafConst = + module + r :: Reg Bool <- mkReg False + interface + get (DeepSplit a) = + DeepSplit (Outer { x = Inner { a = a.x.a; b = True } + ; y = Inner { a = r; b = False } }) diff --git a/testsuite/bsc.scheduler/paths/DeepLeafCross.bs b/testsuite/bsc.scheduler/paths/DeepLeafCross.bs new file mode 100644 index 000000000..8c71fd2e2 --- /dev/null +++ b/testsuite/bsc.scheduler/paths/DeepLeafCross.bs @@ -0,0 +1,34 @@ +package DeepLeafCross where + +import SplitPorts + +-- Nested struct: Outer has two Inner-struct fields. +struct Inner = + a :: Bool + b :: Bool + deriving (Bits) + +struct Outer = + x :: Inner + y :: Inner + deriving (Bits) + +interface Ifc = + -- Deep split: every leaf becomes its own port (get_1_x_a, get_x_a, ...). + get :: DeepSplit Outer -> DeepSplit Outer + +-- The output leaves are wired from *different* input leaves than the +-- same-named one, so path analysis must follow the actual data flow rather +-- than matching port names: +-- get_x_a <- a.y.b (so edge: get_1_y_b -> get_x_a, NOT get_1_x_a) +-- get_y_b <- a.x_a (so edge: get_1_x_a -> get_y_b, NOT get_1_y_b) +-- The other two leaves are registered, so they have no incoming path. +{-# synthesize mkDeepLeafCross #-} +mkDeepLeafCross :: Module Ifc +mkDeepLeafCross = + module + r :: Reg Bool <- mkReg False + interface + get (DeepSplit a) = + DeepSplit (Outer { x = Inner { a = a.y.b; b = r } + ; y = Inner { a = r; b = a.x.a } }) diff --git a/testsuite/bsc.scheduler/paths/DeepLeafLoop.bs b/testsuite/bsc.scheduler/paths/DeepLeafLoop.bs new file mode 100644 index 000000000..f7c4ac1c1 --- /dev/null +++ b/testsuite/bsc.scheduler/paths/DeepLeafLoop.bs @@ -0,0 +1,45 @@ +package DeepLeafLoop where + +import SplitPorts + +-- Nested struct (Outer field is itself a struct), deep-split into leaf ports. +struct Inner = + a :: Bool + b :: Bool + deriving (Bits) + +struct Outer = + x :: Inner + y :: Inner + deriving (Bits) + +interface SubIfc = + -- Deep-split combinational method: each leaf output is wired straight from + -- the matching leaf input, so e.g. get_1_x_a -> get_x_a is combinational. + get :: DeepSplit Outer -> DeepSplit Outer + +{-# synthesize mkDeepLeafLoopSub #-} +mkDeepLeafLoopSub :: Module SubIfc +mkDeepLeafLoopSub = + module + interface + get (DeepSplit a) = + DeepSplit (Outer { x = Inner { a = a.x.a; b = a.x.b } + ; y = Inner { a = a.y.a; b = a.y.b } }) + +-- Close a combinational loop through the submodule's deep leaf port x.a: +-- rw.wget -> get's deep input leaf x.a -> get's deep output leaf x.a -> rw.wset +-- Path analysis must detect this through the per-leaf result node, so +-- compilation fails with G0032. +{-# synthesize mkDeepLeafLoop #-} +mkDeepLeafLoop :: Module Empty +mkDeepLeafLoop = + module + s <- mkDeepLeafLoopSub + rw :: RWire Bool <- mkRWire + let fb = isValid (rw.wget) + rules + "close_loop": when True ==> + case s.get (DeepSplit (Outer { x = Inner { a = fb; b = False } + ; y = Inner { a = False; b = False } })) of + DeepSplit res -> if res.x.a then rw.wset True else noAction diff --git a/testsuite/bsc.scheduler/paths/DeepLeafTwoLevels.bs b/testsuite/bsc.scheduler/paths/DeepLeafTwoLevels.bs new file mode 100644 index 000000000..a10928491 --- /dev/null +++ b/testsuite/bsc.scheduler/paths/DeepLeafTwoLevels.bs @@ -0,0 +1,41 @@ +package DeepLeafTwoLevels where + +import SplitPorts + +-- Three levels of nesting: Top -> Mid -> Leaf. +struct Leaf = + lo :: Bool + hi :: Bool + deriving (Bits) + +struct Mid = + p :: Leaf + q :: Leaf + deriving (Bits) + +struct Top = + m :: Mid + n :: Mid + deriving (Bits) + +interface Ifc = + -- Deep split recurses two levels of nested structs down to leaf ports, + -- e.g. input get_1_m_p_lo, output get_m_p_lo. + get :: DeepSplit Top -> DeepSplit Top + +-- Only two of the eight deep leaves are combinational from their matching +-- input leaf; the rest come from a register. This checks that path analysis +-- reaches two-levels-deep leaf ports and isolates them: +-- get_m_p_lo <- a.m.p.lo => get_1_m_p_lo -> get_m_p_lo +-- get_n_q_hi <- a.n.q.hi => get_1_n_q_hi -> get_n_q_hi +{-# synthesize mkDeepLeafTwoLevels #-} +mkDeepLeafTwoLevels :: Module Ifc +mkDeepLeafTwoLevels = + module + r :: Reg Bool <- mkReg False + interface + get (DeepSplit a) = + DeepSplit (Top { m = Mid { p = Leaf { lo = a.m.p.lo; hi = r } + ; q = Leaf { lo = r; hi = r } } + ; n = Mid { p = Leaf { lo = r; hi = r } + ; q = Leaf { lo = r; hi = a.n.q.hi } } }) diff --git a/testsuite/bsc.scheduler/paths/DeepWireFanout.bs b/testsuite/bsc.scheduler/paths/DeepWireFanout.bs new file mode 100644 index 000000000..15c019985 --- /dev/null +++ b/testsuite/bsc.scheduler/paths/DeepWireFanout.bs @@ -0,0 +1,37 @@ +package DeepWireFanout where + +import SplitPorts + +struct Inner = + x :: Bool + y :: Bool + deriving (Bits) + +struct Outer = + a :: Inner + b :: Bool + deriving (Bits) + +interface Ifc = + -- DeepSplit input recurses to leaf ports (put_1_a_x, put_1_a_y, put_1_b). + -- One Action method forwards ONLY the deep leaf a.x onto a combinational + -- wire; two distinct value methods read it. The single deep leaf input + -- sub-port put_1_a_x fans out to the outputs of TWO different methods, while + -- its siblings put_1_a_y and put_1_b reach neither output. + put :: DeepSplit Outer -> Action + outA :: Bool + outB :: Bool + +{-# synthesize mkDeepWireFanout #-} +mkDeepWireFanout :: Module Ifc +mkDeepWireFanout = + module + w :: RWire Bool <- mkRWire + interface + put (DeepSplit o) = w.wset o.a.x + outA = case w.wget of + Just v -> v + Nothing -> False + outB = case w.wget of + Just v -> not v + Nothing -> True diff --git a/testsuite/bsc.scheduler/paths/EnRdyAVEnResult.bs b/testsuite/bsc.scheduler/paths/EnRdyAVEnResult.bs new file mode 100644 index 000000000..64a8363d5 --- /dev/null +++ b/testsuite/bsc.scheduler/paths/EnRdyAVEnResult.bs @@ -0,0 +1,28 @@ +package EnRdyAVEnResult where + +import SplitPorts + +struct Pair = + p1 :: Bool + p2 :: Bool + deriving (Bits) + +interface Ifc = + -- An ActionValue method with a split result. Field p1 is combinational from + -- the split input sub-port (upd_1_p1). Field p2 is combinational from the + -- method's own enable EN_upd: it forwards EN onto an RWire whose validity is + -- read by a separate value method 'busy', so EN_upd reaches RDY/busy while + -- upd_1_p1 reaches the split result port upd_p1. + upd :: ShallowSplit Pair -> ActionValue (ShallowSplit Pair) + busy :: Bool + +{-# synthesize mkEnRdyAVEnResult #-} +mkEnRdyAVEnResult :: Module Ifc +mkEnRdyAVEnResult = + module + w :: RWire Bool <- mkRWire + interface + upd (ShallowSplit a) = + do w.wset a.p2 + return (ShallowSplit (Pair { p1 = a.p1; p2 = a.p2 })) + busy = isValid (w.wget) diff --git a/testsuite/bsc.scheduler/paths/EnRdyDeepEnOut.bs b/testsuite/bsc.scheduler/paths/EnRdyDeepEnOut.bs new file mode 100644 index 000000000..bfe95c146 --- /dev/null +++ b/testsuite/bsc.scheduler/paths/EnRdyDeepEnOut.bs @@ -0,0 +1,32 @@ +package EnRdyDeepEnOut where + +import SplitPorts + +struct Inner = + a :: Bool + b :: Bool + deriving (Bits) + +struct Outer = + x :: Inner + y :: Bool + deriving (Bits) + +interface Ifc = + -- An Action method 'fire' with an enable, and a value method 'rd' whose + -- DEEP-split result has a leaf (x_a) driven combinationally by EN_fire, + -- while sibling leaves (x_b, y) come from registers. Path analysis should + -- report a path only to the deep leaf output port rd_x_a. + fire :: Bool -> Action + rd :: DeepSplit Outer + +{-# synthesize mkEnRdyDeepEnOut #-} +mkEnRdyDeepEnOut :: Module Ifc +mkEnRdyDeepEnOut = + module + w :: RWire Bool <- mkRWire + rb :: Reg Bool <- mkReg False + ry :: Reg Bool <- mkReg False + interface + fire v = w.wset v + rd = DeepSplit (Outer { x = Inner { a = isValid (w.wget); b = rb }; y = ry }) diff --git a/testsuite/bsc.scheduler/paths/EnRdyEnToSplitOut.bs b/testsuite/bsc.scheduler/paths/EnRdyEnToSplitOut.bs new file mode 100644 index 000000000..10e6a5770 --- /dev/null +++ b/testsuite/bsc.scheduler/paths/EnRdyEnToSplitOut.bs @@ -0,0 +1,23 @@ +package EnRdyEnToSplitOut where + +import SplitPorts + +struct Pair = + p1 :: Bool + p2 :: Bool + deriving (Bits) + +interface Ifc = + -- An Action method with an enable, plus a value method whose split result + -- depends combinationally on whether that Action method fired (its EN). + doit :: Bool -> Action + rd :: ShallowSplit Pair + +{-# synthesize mkEnRdyEnToSplitOut #-} +mkEnRdyEnToSplitOut :: Module Ifc +mkEnRdyEnToSplitOut = + module + w :: RWire Bool <- mkRWire + interface + doit x = w.wset x + rd = ShallowSplit (Pair { p1 = isValid (w.wget); p2 = False }) diff --git a/testsuite/bsc.scheduler/paths/EnRdyInToRdy.bs b/testsuite/bsc.scheduler/paths/EnRdyInToRdy.bs new file mode 100644 index 000000000..ddc6ef34f --- /dev/null +++ b/testsuite/bsc.scheduler/paths/EnRdyInToRdy.bs @@ -0,0 +1,25 @@ +package EnRdyInToRdy where + +import SplitPorts + +struct Pair = + p1 :: Bool + p2 :: Bool + deriving (Bits) + +interface Ifc = + -- 'put' takes a split argument and forwards one sub-port (p1) onto an RWire. + -- 'gate' is a value method whose readiness (RDY) is the *value* carried on + -- that RWire, so RDY_gate combinationally depends on the split input port + -- put_1_p1 (and not on put_1_p2, which is never forwarded). + put :: ShallowSplit Pair -> Action + gate :: Bool + +{-# synthesize mkEnRdyInToRdy #-} +mkEnRdyInToRdy :: Module Ifc +mkEnRdyInToRdy = + module + w :: RWire Bool <- mkRWire + interface + put (ShallowSplit a) = w.wset a.p1 + gate = False when fromMaybe False (w.wget) diff --git a/testsuite/bsc.scheduler/paths/EnRdyTwoEnSplit.bs b/testsuite/bsc.scheduler/paths/EnRdyTwoEnSplit.bs new file mode 100644 index 000000000..170440029 --- /dev/null +++ b/testsuite/bsc.scheduler/paths/EnRdyTwoEnSplit.bs @@ -0,0 +1,29 @@ +package EnRdyTwoEnSplit where + +import SplitPorts + +struct Pair = + p1 :: Bool + p2 :: Bool + deriving (Bits) + +interface Ifc = + -- Two independent Action methods, each forwarding onto its own RWire. A + -- value method 'rd' has a split result where p1 is gated by setA's enable and + -- p2 is gated by setB's enable. Path analysis should report EN_setA only to + -- rd_p1 and EN_setB only to rd_p2 (no crossed edges), demonstrating per-port + -- routing of distinct method enables. + setA :: Action + setB :: Action + rd :: ShallowSplit Pair + +{-# synthesize mkEnRdyTwoEnSplit #-} +mkEnRdyTwoEnSplit :: Module Ifc +mkEnRdyTwoEnSplit = + module + wa :: RWire Bool <- mkRWire + wb :: RWire Bool <- mkRWire + interface + setA = wa.wset True + setB = wb.wset True + rd = ShallowSplit (Pair { p1 = isValid (wa.wget); p2 = isValid (wb.wget) }) diff --git a/testsuite/bsc.scheduler/paths/GranDeepNested.bs b/testsuite/bsc.scheduler/paths/GranDeepNested.bs new file mode 100644 index 000000000..6b214c64d --- /dev/null +++ b/testsuite/bsc.scheduler/paths/GranDeepNested.bs @@ -0,0 +1,31 @@ +package GranDeepNested where + +import SplitPorts + +struct Inner = + a :: Bool + b :: Bool + deriving (Bits) + +struct Outer = + x :: Inner + y :: Bool + deriving (Bits) + +-- DeepSplit recurses into the nested struct: the field `x` becomes leaf ports +-- `get_x_a` / `get_x_b` (inputs `get_1_x_a` / `get_1_x_b`), giving per-leaf +-- path granularity. Only x.a is combinational from input x.a, so the path is +-- exactly `get_1_x_a -> get_x_a` and nothing flows to get_x_b or get_y. +-- Contrast with GranShallowNested, where the same struct gives the coarse +-- packed path get_1_x -> get_x. +interface Ifc = + get :: DeepSplit Outer -> DeepSplit Outer + +{-# synthesize mkGranDeepNested #-} +mkGranDeepNested :: Module Ifc +mkGranDeepNested = + module + r :: Reg Bool <- mkReg False + interface + get (DeepSplit o) = + DeepSplit (Outer { x = Inner { a = o.x.a; b = r }; y = r }) diff --git a/testsuite/bsc.scheduler/paths/GranNoSplit.bs b/testsuite/bsc.scheduler/paths/GranNoSplit.bs new file mode 100644 index 000000000..2d4bd738a --- /dev/null +++ b/testsuite/bsc.scheduler/paths/GranNoSplit.bs @@ -0,0 +1,30 @@ +package GranNoSplit where + +import SplitPorts + +struct Inner = + a :: Bool + b :: Bool + deriving (Bits) + +-- The field `x` is wrapped in NoSplit, which terminates the DeepSplit +-- recursion: instead of leaf ports x_a / x_b, x stays as ONE packed port +-- get_x (input get_1_x). The field `y` is an ordinary leaf. So this is a +-- middle ground between Shallow and Deep: DeepSplit everywhere except where +-- NoSplit caps it. +struct Outer = + x :: NoSplit Inner + y :: Bool + deriving (Bits) + +interface Ifc = + get :: DeepSplit Outer -> DeepSplit Outer + +{-# synthesize mkGranNoSplit #-} +mkGranNoSplit :: Module Ifc +mkGranNoSplit = + module + r :: Reg Bool <- mkReg False + interface + get (DeepSplit o) = + DeepSplit (Outer { x = o.x; y = r }) diff --git a/testsuite/bsc.scheduler/paths/GranShallowNested.bs b/testsuite/bsc.scheduler/paths/GranShallowNested.bs new file mode 100644 index 000000000..11f2eb69d --- /dev/null +++ b/testsuite/bsc.scheduler/paths/GranShallowNested.bs @@ -0,0 +1,30 @@ +package GranShallowNested where + +import SplitPorts + +struct Inner = + a :: Bool + b :: Bool + deriving (Bits) + +struct Outer = + x :: Inner + y :: Bool + deriving (Bits) + +-- ShallowSplit splits only the TOP level: the nested struct field `x` stays +-- PACKED as a single port `get_x` (and input `get_1_x`), while `y` is its own +-- port. So even though only x.a is combinational from the input, the whole +-- packed `x` port carries the path; there is no per-leaf granularity. +interface Ifc = + get :: ShallowSplit Outer -> ShallowSplit Outer + +{-# synthesize mkGranShallowNested #-} +mkGranShallowNested :: Module Ifc +mkGranShallowNested = + module + r :: Reg Bool <- mkReg False + interface + -- x.a is combinational from input x.a; x.b is registered; y is registered + get (ShallowSplit o) = + ShallowSplit (Outer { x = Inner { a = o.x.a; b = r }; y = r }) diff --git a/testsuite/bsc.scheduler/paths/GranTwoArgs.bs b/testsuite/bsc.scheduler/paths/GranTwoArgs.bs new file mode 100644 index 000000000..6eb658176 --- /dev/null +++ b/testsuite/bsc.scheduler/paths/GranTwoArgs.bs @@ -0,0 +1,27 @@ +package GranTwoArgs where + +import SplitPorts + +struct Pair = + p1 :: Bool + p2 :: Bool + deriving (Bits) + +-- A value method with TWO split arguments, named "lhs"/"rhs" via the arg_names +-- pragma. Each argument is split into its own field ports (combine_lhs_p1, +-- combine_rhs_p2, ...) and the result is split too. The result field p1 is +-- combinational from the lhs argument's p1, and result field p2 is +-- combinational from the rhs argument's p2. Path analysis must distinguish +-- sub-ports of arg lhs vs arg rhs: the path goes lhs_p1 -> p1 and rhs_p2 -> p2, +-- but NOT the cross edges lhs_p2 -> p2 or rhs_p1 -> p1. +interface Ifc = + combine :: ShallowSplit Pair -> ShallowSplit Pair -> ShallowSplit Pair + {-# arg_names = ["lhs", "rhs"] #-} + +{-# synthesize mkGranTwoArgs #-} +mkGranTwoArgs :: Module Ifc +mkGranTwoArgs = + module + interface + combine (ShallowSplit l) (ShallowSplit r) = + ShallowSplit (Pair { p1 = l.p1; p2 = r.p2 }) diff --git a/testsuite/bsc.scheduler/paths/GranVec.bs b/testsuite/bsc.scheduler/paths/GranVec.bs new file mode 100644 index 000000000..d4f2d669e --- /dev/null +++ b/testsuite/bsc.scheduler/paths/GranVec.bs @@ -0,0 +1,22 @@ +package GranVec where + +import SplitPorts +import Vector + +-- DeepSplit of a (Vector 3 Bool) result produces one output port per element +-- (get_0, get_1, get_2), and the split argument produces one input port per +-- element (get_1_0, get_1_1, get_1_2; the leading 1 is the argument number). +-- Element 2 of the result is combinational from element 2 of the input; the +-- other elements come from a register. Path analysis should report exactly +-- the element-2 edge get_1_2 -> get_2 and no path to get_0 / get_1. +interface Ifc = + get :: DeepSplit (Vector 3 Bool) -> DeepSplit (Vector 3 Bool) + +{-# synthesize mkGranVec #-} +mkGranVec :: Module Ifc +mkGranVec = + module + r :: Reg Bool <- mkReg False + interface + get (DeepSplit v) = + DeepSplit (update (replicate r) 2 (v !! 2)) diff --git a/testsuite/bsc.scheduler/paths/IOMatrixCombine.bs b/testsuite/bsc.scheduler/paths/IOMatrixCombine.bs new file mode 100644 index 000000000..148e31ef0 --- /dev/null +++ b/testsuite/bsc.scheduler/paths/IOMatrixCombine.bs @@ -0,0 +1,23 @@ +package IOMatrixCombine where + +import SplitPorts + +struct Pair = + p1 :: Bool + p2 :: Bool + deriving (Bits) + +interface Ifc = + -- A value method whose split output field p1 COMBINES both split input + -- fields (p1 && p2), while output field p2 comes from a register. Path + -- analysis must report TWO edges fanning into get_p1 (from both input + -- ports) and NO edge into get_p2. + get :: ShallowSplit Pair -> ShallowSplit Pair + +{-# synthesize mkIOMatrixCombine #-} +mkIOMatrixCombine :: Module Ifc +mkIOMatrixCombine = + module + r :: Reg Bool <- mkReg False + interface + get (ShallowSplit a) = ShallowSplit (Pair { p1 = a.p1 && a.p2; p2 = r }) diff --git a/testsuite/bsc.scheduler/paths/IOMatrixCross.bs b/testsuite/bsc.scheduler/paths/IOMatrixCross.bs new file mode 100644 index 000000000..734b05674 --- /dev/null +++ b/testsuite/bsc.scheduler/paths/IOMatrixCross.bs @@ -0,0 +1,22 @@ +package IOMatrixCross where + +import SplitPorts + +struct Pair = + p1 :: Bool + p2 :: Bool + deriving (Bits) + +interface Ifc = + -- A value method whose split result CROSSES the split input: output field + -- p1 is wired from input field p2, and output field p2 is wired from input + -- field p1. Path analysis must report exactly the crossed edges and NONE + -- of the straight-through edges. + get :: ShallowSplit Pair -> ShallowSplit Pair + +{-# synthesize mkIOMatrixCross #-} +mkIOMatrixCross :: Module Ifc +mkIOMatrixCross = + module + interface + get (ShallowSplit a) = ShallowSplit (Pair { p1 = a.p2; p2 = a.p1 }) diff --git a/testsuite/bsc.scheduler/paths/IOMatrixDeepCombine.bs b/testsuite/bsc.scheduler/paths/IOMatrixDeepCombine.bs new file mode 100644 index 000000000..c15db1ba8 --- /dev/null +++ b/testsuite/bsc.scheduler/paths/IOMatrixDeepCombine.bs @@ -0,0 +1,31 @@ +package IOMatrixDeepCombine where + +import SplitPorts + +struct Inner = + a :: Bool + b :: Bool + deriving (Bits) + +struct Outer = + x :: Inner + y :: Bool + deriving (Bits) + +interface Ifc = + -- DeepSplit recurses into Inner. The two inner output leaves each COMBINE + -- disjoint pairs of input leaves: out x_a <= (in x_a && in y), and + -- out x_b <= (in x_b && in y). The top-level output y comes from a + -- register, so it has NO incoming combinational path. Path analysis must + -- report the two combined deep edges into x_a and x_b and NO edge into y. + get :: DeepSplit Outer -> DeepSplit Outer + +{-# synthesize mkIOMatrixDeepCombine #-} +mkIOMatrixDeepCombine :: Module Ifc +mkIOMatrixDeepCombine = + module + r :: Reg Bool <- mkReg False + interface + get (DeepSplit o) = + DeepSplit (Outer { x = Inner { a = o.x.a && o.y; b = o.x.b && o.y } + ; y = r }) diff --git a/testsuite/bsc.scheduler/paths/IOMatrixDeepCross.bs b/testsuite/bsc.scheduler/paths/IOMatrixDeepCross.bs new file mode 100644 index 000000000..15fc9ae9b --- /dev/null +++ b/testsuite/bsc.scheduler/paths/IOMatrixDeepCross.bs @@ -0,0 +1,30 @@ +package IOMatrixDeepCross where + +import SplitPorts + +struct Inner = + a :: Bool + b :: Bool + deriving (Bits) + +struct Outer = + x :: Inner + y :: Bool + deriving (Bits) + +interface Ifc = + -- DeepSplit recurses into the nested Inner struct, giving leaf ports + -- get_1_x_a, get_1_x_b, get_1_y on the input and get_x_a, get_x_b, get_y + -- on the output. The wiring CROSSES the two inner leaves (out x_a <= in + -- x_b, out x_b <= in x_a) and passes the top-level y straight through. + -- Path analysis must report the crossed deep edges and the straight y edge, + -- and NONE of the straight inner edges. + get :: DeepSplit Outer -> DeepSplit Outer + +{-# synthesize mkIOMatrixDeepCross #-} +mkIOMatrixDeepCross :: Module Ifc +mkIOMatrixDeepCross = + module + interface + get (DeepSplit o) = + DeepSplit (Outer { x = Inner { a = o.x.b; b = o.x.a }; y = o.y }) diff --git a/testsuite/bsc.scheduler/paths/IOMatrixFanout.bs b/testsuite/bsc.scheduler/paths/IOMatrixFanout.bs new file mode 100644 index 000000000..27af864ca --- /dev/null +++ b/testsuite/bsc.scheduler/paths/IOMatrixFanout.bs @@ -0,0 +1,22 @@ +package IOMatrixFanout where + +import SplitPorts + +struct Pair = + p1 :: Bool + p2 :: Bool + deriving (Bits) + +interface Ifc = + -- A value method whose single split input field p1 FANS OUT to BOTH split + -- output fields (p1 = a.p1, p2 = not a.p1), while input field p2 feeds + -- nothing. Path analysis must report two edges OUT of get_1_p1 (to both + -- output ports) and NO edge from get_1_p2. + get :: ShallowSplit Pair -> ShallowSplit Pair + +{-# synthesize mkIOMatrixFanout #-} +mkIOMatrixFanout :: Module Ifc +mkIOMatrixFanout = + module + interface + get (ShallowSplit a) = ShallowSplit (Pair { p1 = a.p1; p2 = not a.p1 }) diff --git a/testsuite/bsc.scheduler/paths/LoopAVPortLoop.bs b/testsuite/bsc.scheduler/paths/LoopAVPortLoop.bs new file mode 100644 index 000000000..c776a0d3e --- /dev/null +++ b/testsuite/bsc.scheduler/paths/LoopAVPortLoop.bs @@ -0,0 +1,41 @@ +package LoopAVPortLoop where + +import SplitPorts + +struct Pair = + p1 :: Bool + p2 :: Bool + deriving (Bits) + +-- An ActionValue method with a split argument and a split result whose output +-- port p1 is combinational from input port p1. (p2 comes from a register.) +interface AVIfc = + upd :: ShallowSplit Pair -> ActionValue (ShallowSplit Pair) + +{-# synthesize mkLoopAVPortLoopSub #-} +mkLoopAVPortLoopSub :: Module AVIfc +mkLoopAVPortLoopSub = + module + r :: Reg Bool <- mkReg False + interface + upd (ShallowSplit a) = + do r := a.p2 + return (ShallowSplit (Pair { p1 = a.p1; p2 = r })) + +-- Close a combinational loop through the ActionValue method's split ports: +-- rw.wget -> upd's split input p1 -> upd's split output p1 -> rw.wset +-- The AV result is consumed combinationally and drives the same RWire whose +-- value feeds the AV input, so the cycle runs through "Argument 1" and +-- "Return value 1" of the ActionValue method `upd` => G0032. +{-# synthesize mkLoopAVPortLoop #-} +mkLoopAVPortLoop :: Module Empty +mkLoopAVPortLoop = + module + s <- mkLoopAVPortLoopSub + rw :: RWire Bool <- mkRWire + let fb = isValid (rw.wget) + rules + "close": when True ==> + do res <- s.upd (ShallowSplit (Pair { p1 = fb; p2 = False })) + case res of + ShallowSplit v -> if v.p1 then rw.wset True else noAction diff --git a/testsuite/bsc.scheduler/paths/LoopConfinedArg2.bs b/testsuite/bsc.scheduler/paths/LoopConfinedArg2.bs new file mode 100644 index 000000000..153a8481e --- /dev/null +++ b/testsuite/bsc.scheduler/paths/LoopConfinedArg2.bs @@ -0,0 +1,47 @@ +package LoopConfinedArg2 where + +import SplitPorts + +struct Pair = + p1 :: Bool + p2 :: Bool + deriving (Bits) + +-- A TWO-argument method. Each argument is a split Pair, so the method has +-- split input ports op_1_p1/op_1_p2 (argument 1) and op_2_p1/op_2_p2 +-- (argument 2). The split result field p1 is combinational ONLY from the +-- SECOND argument's field p1; result field p2 just passes the first argument's +-- field p1 through. +interface SubIfc = + op :: ShallowSplit Pair -> ShallowSplit Pair -> ShallowSplit Pair + +{-# synthesize mkLoopConfinedArg2Sub #-} +mkLoopConfinedArg2Sub :: Module SubIfc +mkLoopConfinedArg2Sub = + module + interface + op (ShallowSplit x) (ShallowSplit y) = + ShallowSplit (Pair { p1 = y.p1; p2 = x.p1 }) + +-- Close a genuine combinational loop confined to the SECOND argument: +-- rw.wget -> op's argument-2 split input p1 -> op's split output p1 -> rw.wset +-- Argument 1 is fed a constant and its contribution (result p2) is sunk into a +-- register, so argument 1's ports are NOT part of the cycle. G0032 must name +-- "Argument 2"/"Return value 1" of method `op' and NOT "Argument 1". This +-- exercises per-port precision on the ARGUMENT index (with multiple split +-- arguments), the counterpart to the single-argument no-loop tests. +{-# synthesize mkLoopConfinedArg2 #-} +mkLoopConfinedArg2 :: Module Empty +mkLoopConfinedArg2 = + module + s <- mkLoopConfinedArg2Sub + rw :: RWire Bool <- mkRWire + sink :: Reg Bool <- mkReg False + let fb = isValid (rw.wget) + rules + "close_arg2_only": when True ==> + case s.op (ShallowSplit (Pair { p1 = False; p2 = False })) + (ShallowSplit (Pair { p1 = fb; p2 = False })) of + ShallowSplit res -> + do (if res.p1 then rw.wset True else noAction) + sink := res.p2 diff --git a/testsuite/bsc.scheduler/paths/LoopConfinedP1.bs b/testsuite/bsc.scheduler/paths/LoopConfinedP1.bs new file mode 100644 index 000000000..8b2935391 --- /dev/null +++ b/testsuite/bsc.scheduler/paths/LoopConfinedP1.bs @@ -0,0 +1,44 @@ +package LoopConfinedP1 where + +import SplitPorts + +struct Pair = + p1 :: Bool + p2 :: Bool + deriving (Bits) + +-- A submodule whose split output port p1 is combinational from split input +-- port p1, while output port p2 is combinational from input port p2 -- the +-- two split fields are kept on INDEPENDENT combinational paths (no crossing). +interface SubIfc = + get :: ShallowSplit Pair -> ShallowSplit Pair + +{-# synthesize mkLoopConfinedP1Sub #-} +mkLoopConfinedP1Sub :: Module SubIfc +mkLoopConfinedP1Sub = + module + interface + get (ShallowSplit a) = ShallowSplit (Pair { p1 = a.p1; p2 = a.p2 }) + +-- Close a genuine combinational loop through ONLY split field p1: +-- rw1.wget -> get's split input p1 -> get's split output p1 -> rw1.wset +-- Split field p2 is driven by a CONSTANT into the input and its output is +-- consumed by a register write (no feedback), so p2's ports cannot be part of +-- any cycle. The cycle therefore runs through "Argument 1"/"Return value 1" +-- of method `get' but NOT "Argument 2"/"Return value 2". This is the per-port +-- precision counterpart to the passing no-loop tests: G0032 must name exactly +-- the p1 port and never the p2 port. +{-# synthesize mkLoopConfinedP1 #-} +mkLoopConfinedP1 :: Module Empty +mkLoopConfinedP1 = + module + s <- mkLoopConfinedP1Sub + rw1 :: RWire Bool <- mkRWire + sink :: Reg Bool <- mkReg False + let fb = isValid (rw1.wget) + rules + "close_p1_only": when True ==> + case s.get (ShallowSplit (Pair { p1 = fb; p2 = False })) of + ShallowSplit res -> + do (if res.p1 then rw1.wset True else noAction) + sink := res.p2 diff --git a/testsuite/bsc.scheduler/paths/LoopConfinedP2.bs b/testsuite/bsc.scheduler/paths/LoopConfinedP2.bs new file mode 100644 index 000000000..9e2646a08 --- /dev/null +++ b/testsuite/bsc.scheduler/paths/LoopConfinedP2.bs @@ -0,0 +1,43 @@ +package LoopConfinedP2 where + +import SplitPorts + +struct Pair = + p1 :: Bool + p2 :: Bool + deriving (Bits) + +-- Same independent-paths submodule as the p1 case: output p1 from input p1, +-- output p2 from input p2 (no field crossing). +interface SubIfc = + get :: ShallowSplit Pair -> ShallowSplit Pair + +{-# synthesize mkLoopConfinedP2Sub #-} +mkLoopConfinedP2Sub :: Module SubIfc +mkLoopConfinedP2Sub = + module + interface + get (ShallowSplit a) = ShallowSplit (Pair { p1 = a.p1; p2 = a.p2 }) + +-- Mirror image of LoopConfinedP1: close the genuine combinational loop through +-- ONLY split field p2: +-- rw2.wget -> get's split input p2 -> get's split output p2 -> rw2.wset +-- Field p1 is fed a constant and its output is sunk to a register, so p1's +-- ports are NOT part of the cycle. G0032 must name "Argument 2"/"Return +-- value 2" of method `get' and NOT "Return value 1". Together with +-- LoopConfinedP1 this proves the positional port index in the cycle report +-- genuinely discriminates the offending split field (it is not always "1"). +{-# synthesize mkLoopConfinedP2 #-} +mkLoopConfinedP2 :: Module Empty +mkLoopConfinedP2 = + module + s <- mkLoopConfinedP2Sub + rw2 :: RWire Bool <- mkRWire + sink :: Reg Bool <- mkReg False + let fb = isValid (rw2.wget) + rules + "close_p2_only": when True ==> + case s.get (ShallowSplit (Pair { p1 = False; p2 = fb })) of + ShallowSplit res -> + do (if res.p2 then rw2.wset True else noAction) + sink := res.p1 diff --git a/testsuite/bsc.scheduler/paths/LoopInputArgLoop.bs b/testsuite/bsc.scheduler/paths/LoopInputArgLoop.bs new file mode 100644 index 000000000..ae22a71a0 --- /dev/null +++ b/testsuite/bsc.scheduler/paths/LoopInputArgLoop.bs @@ -0,0 +1,37 @@ +package LoopInputArgLoop where + +import SplitPorts + +struct Pair = + p1 :: Bool + p2 :: Bool + deriving (Bits) + +-- A submodule that combinationally SWAPS its split fields: +-- out_p1 = in_p2 and out_p2 = in_p1 +-- So output port p2 depends on input port p1 (and vice versa). +interface SubIfc = + get :: ShallowSplit Pair -> ShallowSplit Pair + +{-# synthesize mkLoopInputArgLoopSub #-} +mkLoopInputArgLoopSub :: Module SubIfc +mkLoopInputArgLoopSub = + module + interface + get (ShallowSplit a) = ShallowSplit (Pair { p1 = a.p2; p2 = a.p1 }) + +-- Close a combinational loop that re-enters the SPLIT INPUT arg port p1: +-- rw.wget -> get's split input p1 -> (swap) -> get's split output p2 -> rw.wset +-- The cycle passes through "Argument 1 ... get" (the split p1 input port) and +-- the swapped output p2. Per-port input tracking must detect it => G0032. +{-# synthesize mkLoopInputArgLoop #-} +mkLoopInputArgLoop :: Module Empty +mkLoopInputArgLoop = + module + s <- mkLoopInputArgLoopSub + rw :: RWire Bool <- mkRWire + let fb = isValid (rw.wget) + rules + "close": when True ==> + case s.get (ShallowSplit (Pair { p1 = fb; p2 = False })) of + ShallowSplit res -> if res.p2 then rw.wset True else noAction diff --git a/testsuite/bsc.scheduler/paths/LoopNoFalseLoop.bs b/testsuite/bsc.scheduler/paths/LoopNoFalseLoop.bs new file mode 100644 index 000000000..2f70b1dc4 --- /dev/null +++ b/testsuite/bsc.scheduler/paths/LoopNoFalseLoop.bs @@ -0,0 +1,46 @@ +package LoopNoFalseLoop where + +import SplitPorts + +struct Pair = + p1 :: Bool + p2 :: Bool + deriving (Bits) + +-- Submodule split output: p1 is combinational from split input p1, p2 from a +-- register. Crucially, output p1 depends ONLY on input p1 (not on input p2). +interface SubIfc = + get :: ShallowSplit Pair -> ShallowSplit Pair + +{-# synthesize mkLoopNoFalseLoopSub #-} +mkLoopNoFalseLoopSub :: Module SubIfc +mkLoopNoFalseLoopSub = + module + r :: Reg Bool <- mkReg False + interface + get (ShallowSplit a) = ShallowSplit (Pair { p1 = a.p1; p2 = r }) + +interface TopIfc = + top :: Bool -> Bool + +-- The top's value method feeds its input into submodule g1's split input p1, +-- then feeds g1's combinational split OUTPUT p1 into submodule g2's split INPUT +-- p2, returning g2's split output p1. Because out-p1 depends only on in-p1 +-- (never in-p2), routing a value into g2.in_p2 cannot close a cycle: the chain +-- top -> g1.in_p1 -> g1.out_p1 -> g2.in_p2 (dead end; out never reads in_p2) +-- and the returned value comes from g2.in_p1 = x, so the only real path is +-- top -> top. Per-port tracking proves there is NO combinational loop; with +-- packed ports the whole-struct feedback would risk a false loop. +{-# synthesize mkLoopNoFalseLoop #-} +mkLoopNoFalseLoop :: Module TopIfc +mkLoopNoFalseLoop = + module + g1 <- mkLoopNoFalseLoopSub + g2 <- mkLoopNoFalseLoopSub + interface + top x = + let firstOut = case g1.get (ShallowSplit (Pair { p1 = x; p2 = False })) of + ShallowSplit r1 -> r1.p1 + secondOut = case g2.get (ShallowSplit (Pair { p1 = x; p2 = firstOut })) of + ShallowSplit r2 -> r2.p1 + in secondOut diff --git a/testsuite/bsc.scheduler/paths/LoopSwapNoLoop.bs b/testsuite/bsc.scheduler/paths/LoopSwapNoLoop.bs new file mode 100644 index 000000000..ede72d750 --- /dev/null +++ b/testsuite/bsc.scheduler/paths/LoopSwapNoLoop.bs @@ -0,0 +1,40 @@ +package LoopSwapNoLoop where + +import SplitPorts + +struct Pair = + p1 :: Bool + p2 :: Bool + deriving (Bits) + +-- The same combinational SWAP submodule as the input-arg loop test: +-- out_p1 = in_p2 and out_p2 = in_p1 +interface SubIfc = + get :: ShallowSplit Pair -> ShallowSplit Pair + +{-# synthesize mkLoopSwapNoLoopSub #-} +mkLoopSwapNoLoopSub :: Module SubIfc +mkLoopSwapNoLoopSub = + module + interface + get (ShallowSplit a) = ShallowSplit (Pair { p1 = a.p2; p2 = a.p1 }) + +interface TopIfc = + top :: Bool -> Bool + +-- Feed the top input into the swap submodule's split INPUT p1, but RETURN the +-- swap submodule's split OUTPUT p1. Because out_p1 = in_p2 (NOT in_p1), the +-- value that came in on in_p1 only reaches out_p2, which is discarded here. +-- So the only real combinational path is from the constant on in_p2... and the +-- top input that drives in_p1 reaches NO output port. Per-port tracking +-- discriminates the swapped ports, so there is NO path top_1 -> top and (had a +-- feedback been wired) NO loop. Sibling to LoopInputArgLoop, which DOES loop +-- because it reads the swapped out_p2. +{-# synthesize mkLoopSwapNoLoop #-} +mkLoopSwapNoLoop :: Module TopIfc +mkLoopSwapNoLoop = + module + s <- mkLoopSwapNoLoopSub + interface + top x = case s.get (ShallowSplit (Pair { p1 = x; p2 = False })) of + ShallowSplit res -> res.p1 diff --git a/testsuite/bsc.scheduler/paths/MaybeDeep.bs b/testsuite/bsc.scheduler/paths/MaybeDeep.bs new file mode 100644 index 000000000..e5be13a0b --- /dev/null +++ b/testsuite/bsc.scheduler/paths/MaybeDeep.bs @@ -0,0 +1,30 @@ +package MaybeDeep where + +import SplitPorts + +-- Outer struct that is DeepSplit. Its 'lo' field is a plain Bool (a leaf +-- port), and its 'mb' field is a Maybe Bool. DeepSplit recurses into the +-- struct fields, but Maybe has 2 constructors, so the DeepSplitPorts' +-- recursion TERMINATES at 'mb', producing a single packed port (tag+payload) +-- rather than separate tag/payload ports. +struct Outer = + lo :: Bool + mb :: Maybe Bool + deriving (Bits) + +interface Ifc = + get :: DeepSplit Outer -> DeepSplit Outer + +{-# synthesize mkMaybeDeep #-} +mkMaybeDeep :: Module Ifc +mkMaybeDeep = + module + r :: Reg Bool <- mkReg False + interface + get (DeepSplit a) = + -- The single packed union output (mb) is built combinationally from + -- the packed union input (mb): tag and payload both flow through. + -- The leaf output lo comes from a register, so it has no path, and the + -- leaf input lo is unused. + DeepSplit (Outer { lo = r + ; mb = if isValid a.mb then a.mb else Invalid }) diff --git a/testsuite/bsc.scheduler/paths/MaybeShallow.bs b/testsuite/bsc.scheduler/paths/MaybeShallow.bs new file mode 100644 index 000000000..e53fd2616 --- /dev/null +++ b/testsuite/bsc.scheduler/paths/MaybeShallow.bs @@ -0,0 +1,25 @@ +package MaybeShallow where + +import SplitPorts + +-- A struct with one plain field and one Maybe field. Maybe is a +-- 2-constructor (tagged-union) type, so even a ShallowSplit must keep it +-- packed as a single port (tag + payload together), rather than splitting it. +struct Rec = + flag :: Bool + mb :: Maybe Bool + deriving (Bits) + +interface Ifc = + get :: ShallowSplit Rec -> ShallowSplit Rec + +{-# synthesize mkMaybeShallow #-} +mkMaybeShallow :: Module Ifc +mkMaybeShallow = + module + r :: Reg (Maybe Bool) <- mkReg Nothing + interface + get (ShallowSplit a) = + -- flag is combinational from the (packed Maybe) input mb; + -- the output mb field comes from a register, so no path to it. + ShallowSplit (Rec { flag = isValid a.mb; mb = r }) diff --git a/testsuite/bsc.scheduler/paths/PackedInSplitOut.bs b/testsuite/bsc.scheduler/paths/PackedInSplitOut.bs new file mode 100644 index 000000000..cc7c4e1d3 --- /dev/null +++ b/testsuite/bsc.scheduler/paths/PackedInSplitOut.bs @@ -0,0 +1,23 @@ +package PackedInSplitOut where + +import SplitPorts + +struct Pair = + p1 :: Bool + p2 :: Bool + deriving (Bits) + +interface Ifc = + -- Mixed-kind method (reverse direction): a single PACKED Bool argument feeds + -- a SPLIT result. The plain input fans into the first split output field + -- (get_p1) combinationally; the second split output field (get_p2) comes from + -- a register. So analysis should report get_1 -> get_p1 but NOT get_1 -> get_p2. + get :: Bool -> ShallowSplit Pair + +{-# synthesize mkPackedInSplitOut #-} +mkPackedInSplitOut :: Module Ifc +mkPackedInSplitOut = + module + r :: Reg Bool <- mkReg False + interface + get b = ShallowSplit (Pair { p1 = b; p2 = r }) diff --git a/testsuite/bsc.scheduler/paths/RWireFanout.bs b/testsuite/bsc.scheduler/paths/RWireFanout.bs new file mode 100644 index 000000000..8c74d1119 --- /dev/null +++ b/testsuite/bsc.scheduler/paths/RWireFanout.bs @@ -0,0 +1,32 @@ +package RWireFanout where + +import SplitPorts + +struct Pair = + p1 :: Bool + p2 :: Bool + deriving (Bits) + +interface Ifc = + -- One Action method takes a split input (p1, p2) and forwards ONLY field + -- p1 onto a combinational RWire. Two distinct value methods (outA, outB) + -- both read that wire. So the single split input sub-port put_1_p1 fans out + -- combinationally to the outputs of TWO different methods, while its sibling + -- field put_1_p2 (never written to the wire) reaches neither output. + put :: ShallowSplit Pair -> Action + outA :: Bool + outB :: Bool + +{-# synthesize mkRWireFanout #-} +mkRWireFanout :: Module Ifc +mkRWireFanout = + module + w :: RWire Bool <- mkRWire + interface + put (ShallowSplit a) = w.wset a.p1 + outA = case w.wget of + Just v -> v + Nothing -> False + outB = case w.wget of + Just v -> not v + Nothing -> False diff --git a/testsuite/bsc.scheduler/paths/SelectorMuxPath.bs b/testsuite/bsc.scheduler/paths/SelectorMuxPath.bs new file mode 100644 index 000000000..1b481c045 --- /dev/null +++ b/testsuite/bsc.scheduler/paths/SelectorMuxPath.bs @@ -0,0 +1,55 @@ +package SelectorMuxPath where + +import SplitPorts +import Vector + +-- Split input has a selector field plus two data fields and one unused field. +-- The selector field (sel) chooses which of TWO combinational submodule reads +-- is forwarded to the (single, unsplit) output. +struct Cmd = + sel :: Bool + a :: Bit 4 + b :: Bit 4 + dead :: Bit 4 + deriving (Bits) + +-- A single-ported combinational lookup submodule (RegFile-like): the read is +-- combinational from the index argument. +interface LookupIfc = + lookup :: Bit 4 -> Bool + +{-# synthesize mkSelectorMuxSubA #-} +mkSelectorMuxSubA :: Module LookupIfc +mkSelectorMuxSubA = + module + rs :: Vector 16 (Reg Bool) <- replicateM (mkReg False) + interface + lookup i = (select rs i)._read + +{-# synthesize mkSelectorMuxSubB #-} +mkSelectorMuxSubB :: Module LookupIfc +mkSelectorMuxSubB = + module + rs :: Vector 16 (Reg Bool) <- replicateM (mkReg False) + interface + lookup i = (select rs i)._read + +interface TopIfc = + -- split input (Cmd -> 4 ports), single unsplit Bool output + run :: ShallowSplit Cmd -> Bool + +-- The split input field 'sel' index-selects between two distinct combinational +-- submodule reads: subA.lookup indexed by the 'a' data field, subB.lookup +-- indexed by the 'b' data field. Because the mux is data-dependent on the +-- split fields, the single output 'run' is combinationally reachable from the +-- selector port (run_1_sel) AND from BOTH selected data ports (run_1_a, +-- run_1_b). The 'dead' field drives nothing, so run_1_dead must NOT appear. +{-# synthesize mkSelectorMuxPath #-} +mkSelectorMuxPath :: Module TopIfc +mkSelectorMuxPath = + module + subA <- mkSelectorMuxSubA + subB <- mkSelectorMuxSubB + interface + run (ShallowSplit c) = + if c.sel then subA.lookup c.a else subB.lookup c.b diff --git a/testsuite/bsc.scheduler/paths/SelectorSplitOutPath.bs b/testsuite/bsc.scheduler/paths/SelectorSplitOutPath.bs new file mode 100644 index 000000000..b9b012d37 --- /dev/null +++ b/testsuite/bsc.scheduler/paths/SelectorSplitOutPath.bs @@ -0,0 +1,64 @@ +package SelectorSplitOutPath where + +import SplitPorts +import Vector + +-- Split input: a selector field plus two data fields and one unused field. +struct Cmd = + sel :: Bool + a :: Bit 4 + b :: Bit 4 + dead :: Bit 4 + deriving (Bits) + +-- Split output with two independent fields. +struct Out = + o1 :: Bool + o2 :: Bool + deriving (Bits) + +-- Single-ported combinational lookup submodule. +interface LookupIfc = + lookup :: Bit 4 -> Bool + +{-# synthesize mkSelectorSplitOutSubA #-} +mkSelectorSplitOutSubA :: Module LookupIfc +mkSelectorSplitOutSubA = + module + rs :: Vector 16 (Reg Bool) <- replicateM (mkReg False) + interface + lookup i = (select rs i)._read + +{-# synthesize mkSelectorSplitOutSubB #-} +mkSelectorSplitOutSubB :: Module LookupIfc +mkSelectorSplitOutSubB = + module + rs :: Vector 16 (Reg Bool) <- replicateM (mkReg False) + interface + lookup i = (select rs i)._read + +interface TopIfc = + -- both split input (4 ports) and split output (2 ports) + run :: ShallowSplit Cmd -> ShallowSplit Out + +-- Each split OUTPUT port gets its own data-dependent mux driven by the SAME +-- selector field but DIFFERENT data fields: +-- o1 = sel ? subA.lookup a : False => depends on (sel, a) +-- o2 = sel ? r : subB.lookup b => depends on (sel, b) (r registered) +-- Per-(input,output)-port tracking should therefore report: +-- o1 reachable from run_1_sel and run_1_a but NOT run_1_b +-- o2 reachable from run_1_sel and run_1_b but NOT run_1_a +-- and 'dead' reaches neither output. This confirms the selector edge is +-- attributed per output port together with only the data field that output +-- actually consumes. +{-# synthesize mkSelectorSplitOutPath #-} +mkSelectorSplitOutPath :: Module TopIfc +mkSelectorSplitOutPath = + module + subA <- mkSelectorSplitOutSubA + subB <- mkSelectorSplitOutSubB + r :: Reg Bool <- mkReg False + interface + run (ShallowSplit c) = + ShallowSplit (Out { o1 = if c.sel then subA.lookup c.a else False + ; o2 = if c.sel then r else subB.lookup c.b }) diff --git a/testsuite/bsc.scheduler/paths/SiblingDisjointFanout.bs b/testsuite/bsc.scheduler/paths/SiblingDisjointFanout.bs new file mode 100644 index 000000000..632832b4e --- /dev/null +++ b/testsuite/bsc.scheduler/paths/SiblingDisjointFanout.bs @@ -0,0 +1,41 @@ +package SiblingDisjointFanout where + +import SplitPorts + +struct Pair = + p1 :: Bool + p2 :: Bool + deriving (Bits) + +interface Ifc = + -- An Action method takes a split input (p1, p2) and forwards EACH field onto + -- its OWN combinational wire. Field p1 fans out to two methods (outA, outB); + -- the sibling field p2 fans out to a DIFFERENT third method (outC) only. + -- Path analysis must keep the two sources disjoint across method boundaries: + -- put_1_p1 -> outA, put_1_p1 -> outB (and NOT put_1_p1 -> outC) + -- put_1_p2 -> outC (and NOT put_1_p2 -> outA/outB) + put :: ShallowSplit Pair -> Action + outA :: Bool + outB :: Bool + outC :: Bool + +{-# synthesize mkSiblingDisjointFanout #-} +mkSiblingDisjointFanout :: Module Ifc +mkSiblingDisjointFanout = + module + w1 :: RWire Bool <- mkRWire + w2 :: RWire Bool <- mkRWire + interface + put (ShallowSplit a) = + action + w1.wset a.p1 + w2.wset a.p2 + outA = case w1.wget of + Just v -> v + Nothing -> False + outB = case w1.wget of + Just v -> not v + Nothing -> False + outC = case w2.wget of + Just v -> v + Nothing -> False diff --git a/testsuite/bsc.scheduler/paths/SplitAVPath.bs b/testsuite/bsc.scheduler/paths/SplitAVPath.bs new file mode 100644 index 000000000..955fbb003 --- /dev/null +++ b/testsuite/bsc.scheduler/paths/SplitAVPath.bs @@ -0,0 +1,24 @@ +package SplitAVPath where + +import SplitPorts + +struct Pair = + p1 :: Bool + p2 :: Bool + deriving (Bits) + +interface AVIfc = + -- ActionValue method with a split result: p1 is combinational from the + -- (split) input, p2 is registered. Exercises the AIActionValue arm of the + -- per-port path edge construction. + upd :: ShallowSplit Pair -> ActionValue (ShallowSplit Pair) + +{-# synthesize mkSplitAVPath #-} +mkSplitAVPath :: Module AVIfc +mkSplitAVPath = + module + r :: Reg Bool <- mkReg False + interface + upd (ShallowSplit a) = + do r := a.p2 + return (ShallowSplit (Pair { p1 = a.p1; p2 = r })) diff --git a/testsuite/bsc.scheduler/paths/SplitInPackedCombine.bs b/testsuite/bsc.scheduler/paths/SplitInPackedCombine.bs new file mode 100644 index 000000000..dac4e42bd --- /dev/null +++ b/testsuite/bsc.scheduler/paths/SplitInPackedCombine.bs @@ -0,0 +1,22 @@ +package SplitInPackedCombine where + +import SplitPorts + +struct Pair = + p1 :: Bool + p2 :: Bool + deriving (Bits) + +interface Ifc = + -- Mixed-kind method: the ARGUMENT is split into ports (get_1_p1, get_1_p2) + -- but the RESULT is a single packed Bool port (get). Both split input + -- ports feed combinationally into the one packed output, so analysis should + -- report BOTH get_1_p1 -> get AND get_1_p2 -> get. + get :: ShallowSplit Pair -> Bool + +{-# synthesize mkSplitInPackedCombine #-} +mkSplitInPackedCombine :: Module Ifc +mkSplitInPackedCombine = + module + interface + get (ShallowSplit a) = a.p1 || a.p2 diff --git a/testsuite/bsc.scheduler/paths/SplitInPackedOneField.bs b/testsuite/bsc.scheduler/paths/SplitInPackedOneField.bs new file mode 100644 index 000000000..74bbd28cf --- /dev/null +++ b/testsuite/bsc.scheduler/paths/SplitInPackedOneField.bs @@ -0,0 +1,24 @@ +package SplitInPackedOneField where + +import SplitPorts + +struct Pair = + p1 :: Bool + p2 :: Bool + deriving (Bits) + +interface Ifc = + -- Mixed-kind method: SPLIT argument, single PACKED Bool result. The result + -- depends ONLY on the first split input field (p1); the second split input + -- field (p2) is ignored (instead the result mixes in a register). So the + -- packed output has a path from get_1_p1 but NOT from get_1_p2 -- finer + -- per-input tracking across the split/packed boundary. + get :: ShallowSplit Pair -> Bool + +{-# synthesize mkSplitInPackedOneField #-} +mkSplitInPackedOneField :: Module Ifc +mkSplitInPackedOneField = + module + r :: Reg Bool <- mkReg False + interface + get (ShallowSplit a) = a.p1 || r diff --git a/testsuite/bsc.scheduler/paths/SplitOutputLoop.bs b/testsuite/bsc.scheduler/paths/SplitOutputLoop.bs new file mode 100644 index 000000000..58c3c57c4 --- /dev/null +++ b/testsuite/bsc.scheduler/paths/SplitOutputLoop.bs @@ -0,0 +1,34 @@ +package SplitOutputLoop where + +import SplitPorts + +struct Pair = + p1 :: Bool + p2 :: Bool + deriving (Bits) + +interface SubIfc = + -- both result fields are combinational from the (split) input + get :: ShallowSplit Pair -> ShallowSplit Pair + +{-# synthesize mkSplitLoopSub #-} +mkSplitLoopSub :: Module SubIfc +mkSplitLoopSub = + module + interface + get (ShallowSplit a) = ShallowSplit (Pair { p1 = a.p1; p2 = a.p2 }) + +-- Close a combinational loop through the submodule's split output port p1: +-- rw.wget -> get's split input p1 -> get's split output p1 -> rw.wset +-- Path analysis must detect this through the per-port result node. +{-# synthesize sysSplitOutputLoop #-} +sysSplitOutputLoop :: Module Empty +sysSplitOutputLoop = + module + s <- mkSplitLoopSub + rw :: RWire Bool <- mkRWire + let fb = isValid (rw.wget) + rules + "close_loop": when True ==> + case s.get (ShallowSplit (Pair { p1 = fb; p2 = False })) of + ShallowSplit res -> if res.p1 then rw.wset True else noAction diff --git a/testsuite/bsc.scheduler/paths/SplitOutputPath.bs b/testsuite/bsc.scheduler/paths/SplitOutputPath.bs new file mode 100644 index 000000000..132064690 --- /dev/null +++ b/testsuite/bsc.scheduler/paths/SplitOutputPath.bs @@ -0,0 +1,23 @@ +package SplitOutputPath where + +import SplitPorts + +struct Pair = + p1 :: Bool + p2 :: Bool + deriving (Bits) + +interface Ifc = + -- A value method whose result is split into separate output ports. + -- The first field is combinational from the (split) input argument, + -- the second field comes from a register. Path analysis should therefore + -- report a combinational path to the first output port only. + get :: ShallowSplit Pair -> ShallowSplit Pair + +{-# synthesize mkSplitOutputPath #-} +mkSplitOutputPath :: Module Ifc +mkSplitOutputPath = + module + r :: Reg Bool <- mkReg False + interface + get (ShallowSplit a) = ShallowSplit (Pair { p1 = a.p1; p2 = r }) diff --git a/testsuite/bsc.scheduler/paths/SplitSubmodPath.bs b/testsuite/bsc.scheduler/paths/SplitSubmodPath.bs new file mode 100644 index 000000000..5ebe035ec --- /dev/null +++ b/testsuite/bsc.scheduler/paths/SplitSubmodPath.bs @@ -0,0 +1,47 @@ +package SplitSubmodPath where + +import SplitPorts + +struct Pair = + p1 :: Bool + p2 :: Bool + deriving (Bits) + +interface SubIfc = + -- result is split into ports; p1 is combinational from the input, p2 is registered + get :: ShallowSplit Pair -> ShallowSplit Pair + +{-# synthesize mkSplitSubmod #-} +mkSplitSubmod :: Module SubIfc +mkSplitSubmod = + module + r :: Reg Bool <- mkReg False + interface + get (ShallowSplit a) = ShallowSplit (Pair { p1 = a.p1; p2 = r }) + +interface TopIfc = + top :: Bool -> Bool + +-- Routes the top input through the submodule's *combinational* split output +-- field (p1). There should be a combinational path from the input to the +-- output, established via the submodule's per-port result node. +{-# synthesize mkSubmodPathComb #-} +mkSubmodPathComb :: Module TopIfc +mkSubmodPathComb = + module + s <- mkSplitSubmod + interface + top x = case s.get (ShallowSplit (Pair { p1 = x; p2 = False })) of + ShallowSplit res -> res.p1 + +-- Routes the top input through the submodule's *registered* split output +-- field (p2). There should be no combinational path, even though the input +-- still feeds the submodule's (combinational) p1 input port. +{-# synthesize mkSubmodPathReg #-} +mkSubmodPathReg :: Module TopIfc +mkSubmodPathReg = + module + s <- mkSplitSubmod + interface + top x = case s.get (ShallowSplit (Pair { p1 = x; p2 = False })) of + ShallowSplit res -> res.p2 diff --git a/testsuite/bsc.scheduler/paths/SubmodCrossbarPath.bs b/testsuite/bsc.scheduler/paths/SubmodCrossbarPath.bs new file mode 100644 index 000000000..af54c53a4 --- /dev/null +++ b/testsuite/bsc.scheduler/paths/SubmodCrossbarPath.bs @@ -0,0 +1,50 @@ +package SubmodCrossbarPath where + +import SplitPorts + +struct Triple = + p1 :: Bool + p2 :: Bool + p3 :: Bool + deriving (Bits) + +struct Pair = + q1 :: Bool + q2 :: Bool + deriving (Bits) + +interface SubIfc = + -- submodule result split into three ports: p1, p2 combinational from the + -- matching input arg ports; p3 registered. + get :: ShallowSplit Triple -> ShallowSplit Triple + +{-# synthesize mkSubmodCrossbarSub #-} +mkSubmodCrossbarSub :: Module SubIfc +mkSubmodCrossbarSub = + module + r :: Reg Bool <- mkReg False + interface + get (ShallowSplit a) = + ShallowSplit (Triple { p1 = a.p1; p2 = a.p2; p3 = r }) + +interface TopIfc = + -- top argument and result are both split (into two ports each) + top :: ShallowSplit Pair -> ShallowSplit Pair + +-- Routes DISTINCT submodule split output ports to DISTINCT top output ports, +-- crossed over: +-- top_q1 <- submodule get_p2 (fed by top_1_q2) => top_1_q2 -> top_q1 +-- top_q2 <- submodule get_p1 (fed by top_1_q1) => top_1_q1 -> top_q2 +-- The submodule's registered output get_p3 is selected by neither, so it +-- contributes no path. This shows path analysis distinguishes individual +-- submodule split output ports and maps them to individual top output ports +-- (a crossbar), with no straight-through top_1_q1 -> top_q1 edge. +{-# synthesize mkSubmodCrossbarPath #-} +mkSubmodCrossbarPath :: Module TopIfc +mkSubmodCrossbarPath = + module + s <- mkSubmodCrossbarSub + interface + top (ShallowSplit a) = + case s.get (ShallowSplit (Triple { p1 = a.q1; p2 = a.q2; p3 = False })) of + ShallowSplit res -> ShallowSplit (Pair { q1 = res.p2; q2 = res.p1 }) diff --git a/testsuite/bsc.scheduler/paths/SubmodDeepLeafPath.bs b/testsuite/bsc.scheduler/paths/SubmodDeepLeafPath.bs new file mode 100644 index 000000000..81e3b0d65 --- /dev/null +++ b/testsuite/bsc.scheduler/paths/SubmodDeepLeafPath.bs @@ -0,0 +1,49 @@ +package SubmodDeepLeafPath where + +import SplitPorts + +struct Inner = + a :: Bool + b :: Bool + deriving (Bits) + +struct Outer = + x :: Inner + y :: Bool + deriving (Bits) + +interface SubIfc = + -- DEEP split: nested Inner is recursed to leaf ports. + -- result x.a is combinational from input arg x.a (comb leaf) + -- result x.b comes from a register (reg leaf) + -- result y is combinational from input arg y + get :: DeepSplit Outer -> DeepSplit Outer + +{-# synthesize mkSubmodDeepLeafSub #-} +mkSubmodDeepLeafSub :: Module SubIfc +mkSubmodDeepLeafSub = + module + r :: Reg Bool <- mkReg False + interface + get (DeepSplit o) = + DeepSplit (Outer { x = Inner { a = o.x.a; b = r }; y = o.y }) + +interface TopIfc = + top :: DeepSplit Outer -> DeepSplit Outer + +-- Threads the top's deep-split leaf input ports through the submodule's +-- deep-split leaf argument/result ports. At leaf granularity: +-- top_1_x_a -> top_x_a exists (comb leaf through the submodule) +-- top_1_y -> top_y exists (comb leaf through the submodule) +-- nothing reaches top_x_b (the submodule's registered leaf) +-- This shows path tracking recurses to leaves rather than treating the nested +-- Inner struct as one port. +{-# synthesize mkSubmodDeepLeafPath #-} +mkSubmodDeepLeafPath :: Module TopIfc +mkSubmodDeepLeafPath = + module + s <- mkSubmodDeepLeafSub + interface + top (DeepSplit o) = + case s.get (DeepSplit (Outer { x = Inner { a = o.x.a; b = o.x.b }; y = o.y })) of + DeepSplit res -> DeepSplit res diff --git a/testsuite/bsc.scheduler/paths/SubmodInputArgPath.bs b/testsuite/bsc.scheduler/paths/SubmodInputArgPath.bs new file mode 100644 index 000000000..3522b9158 --- /dev/null +++ b/testsuite/bsc.scheduler/paths/SubmodInputArgPath.bs @@ -0,0 +1,41 @@ +package SubmodInputArgPath where + +import SplitPorts + +struct Pair = + p1 :: Bool + p2 :: Bool + deriving (Bits) + +interface SubIfc = + -- result p1 is combinational from the input arg p1, result p2 is registered. + get :: ShallowSplit Pair -> ShallowSplit Pair + +{-# synthesize mkSubmodInputArgSub #-} +mkSubmodInputArgSub :: Module SubIfc +mkSubmodInputArgSub = + module + r :: Reg Bool <- mkReg False + interface + get (ShallowSplit a) = ShallowSplit (Pair { p1 = a.p1; p2 = r }) + +interface TopIfc = + -- top method's argument AND result are both split into ports + top :: ShallowSplit Pair -> ShallowSplit Pair + +-- Threads the top's split input ports straight into the submodule's split +-- *argument* ports, and the submodule's split result ports straight out to the +-- top's split output ports. Because the submodule's result p1 is +-- combinational from its arg p1 (and result p2 is registered), the only path +-- is top_1_p1 -> top_p1, exercised THROUGH the submodule's per-port argument +-- node get_1_p1. There is no top_1_p2 -> top_p1 cross-edge and no path to +-- top_p2. +{-# synthesize mkSubmodInputArgPath #-} +mkSubmodInputArgPath :: Module TopIfc +mkSubmodInputArgPath = + module + s <- mkSubmodInputArgSub + interface + top (ShallowSplit a) = + case s.get (ShallowSplit (Pair { p1 = a.p1; p2 = a.p2 })) of + ShallowSplit res -> ShallowSplit (Pair { p1 = res.p1; p2 = res.p2 }) diff --git a/testsuite/bsc.scheduler/paths/SubmodSelectOutPath.bs b/testsuite/bsc.scheduler/paths/SubmodSelectOutPath.bs new file mode 100644 index 000000000..b0f196fa5 --- /dev/null +++ b/testsuite/bsc.scheduler/paths/SubmodSelectOutPath.bs @@ -0,0 +1,43 @@ +package SubmodSelectOutPath where + +import SplitPorts + +struct Triple = + p1 :: Bool + p2 :: Bool + p3 :: Bool + deriving (Bits) + +interface SubIfc = + -- result is split into three ports; p1 and p2 are combinational from the + -- corresponding input arg ports, p3 comes from a register. + get :: ShallowSplit Triple -> ShallowSplit Triple + +{-# synthesize mkSubmodSelectOutSub #-} +mkSubmodSelectOutSub :: Module SubIfc +mkSubmodSelectOutSub = + module + r :: Reg Bool <- mkReg False + interface + get (ShallowSplit a) = + ShallowSplit (Triple { p1 = a.p1; p2 = a.p2; p3 = r }) + +interface TopIfc = + -- single (unsplit) Bool output, plus a select input + top :: Bool -> Bool -> Bool + +-- Muxes between TWO of the submodule's split *output* ports (get_p1 and +-- get_p2) under a select input, then drives a single top output. Both +-- selected submodule output ports are combinational, so the top output is +-- combinationally reachable from BOTH data inputs (top_1, the data feeding +-- both submodule arg ports) AND the select input (top_2). The submodule's +-- registered output port get_p3 is never selected, so it contributes no path. +{-# synthesize mkSubmodSelectOutPath #-} +mkSubmodSelectOutPath :: Module TopIfc +mkSubmodSelectOutPath = + module + s <- mkSubmodSelectOutSub + interface + top d sel = + case s.get (ShallowSplit (Triple { p1 = d; p2 = d; p3 = False })) of + ShallowSplit res -> if sel then res.p1 else res.p2 diff --git a/testsuite/bsc.scheduler/paths/UnionPayload.bs b/testsuite/bsc.scheduler/paths/UnionPayload.bs new file mode 100644 index 000000000..f0811692b --- /dev/null +++ b/testsuite/bsc.scheduler/paths/UnionPayload.bs @@ -0,0 +1,37 @@ +package UnionPayload where + +import SplitPorts + +-- A user-defined 2-constructor tagged union with a payload. Like Maybe, it +-- has n /= 1 constructors, so SplitPorts keeps it packed as ONE port (tag + +-- payload) under both ShallowSplit and DeepSplit. +data Cmd = Nop | Run Bool + deriving (Bits) + +-- Two-field struct, ShallowSplit: a plain Bool field and the union field. +struct In = + sel :: Bool + cmd :: Cmd + deriving (Bits) + +struct Out = + echo :: Cmd + ack :: Bool + deriving (Bits) + +interface Ifc = + step :: ShallowSplit In -> ShallowSplit Out + +{-# synthesize mkUnionPayload #-} +mkUnionPayload :: Module Ifc +mkUnionPayload = + module + r :: Reg Bool <- mkReg False + interface + step (ShallowSplit a) = + -- The packed union input (cmd) flows combinationally to the packed + -- union output (echo) only. The plain Bool output (ack) comes from a + -- register, so the union input does NOT reach it: this shows per-port + -- granularity where an input touching only the union port produces a + -- single path to that one packed output port. + ShallowSplit (Out { echo = a.cmd; ack = r }) diff --git a/testsuite/bsc.scheduler/paths/VecNestedDeep.bs b/testsuite/bsc.scheduler/paths/VecNestedDeep.bs new file mode 100644 index 000000000..596e3ec76 --- /dev/null +++ b/testsuite/bsc.scheduler/paths/VecNestedDeep.bs @@ -0,0 +1,49 @@ +package VecNestedDeep where + +import SplitPorts +import Vector + +struct Inner = + a :: Bool + b :: Bool + deriving (Bits) + +-- Cell has a nested struct field `c` (DeepSplit recurses into it) and a field `d` +-- wrapped in NoSplit so the DeepSplit recursion TERMINATES there, leaving `d` +-- packed even at the leaf level. +struct Cell = + c :: Inner + d :: NoSplit Bool + deriving (Bits) + +-- DeepSplit of a (Vector 2 Cell): each vector element recurses through Cell into +-- Inner, producing multi-level leaf names under a vector index: +-- outputs: get_0_c_a get_0_c_b get_0_d get_1_c_a get_1_c_b get_1_d +-- inputs : get_1_0_c_a ... get_1_1_d +-- (the NoSplit field d stays a single port get_0_d, NOT recursed further). +-- +-- Combinational edges chosen to exercise multi-level leaves AND cross-index +-- isolation: +-- element 0 deep leaf c.a straight-through from input elem 0 c.a +-- get_1_0_c_a -> get_0_c_a +-- element 1 NoSplit-packed leaf d crossed from input elem 0 d +-- get_1_0_d -> get_1_d +-- everything else registered: no get_0_c_b path, no get_1_c_a path, and the +-- crossed d edge proves index isolation (source elem 0, dest elem 1). +interface Ifc = + get :: DeepSplit (Vector 2 Cell) -> DeepSplit (Vector 2 Cell) + +{-# synthesize mkVecNestedDeep #-} +mkVecNestedDeep :: Module Ifc +mkVecNestedDeep = + module + r :: Reg Bool <- mkReg False + interface + get (DeepSplit v) = + let unD :: NoSplit Bool -> Bool + unD (NoSplit x) = x + c0 = Cell { c = Inner { a = (v !! 0).c.a; b = r } -- c0.c.a comb from in elem 0 + ; d = NoSplit r } + c1 = Cell { c = Inner { a = r; b = r } -- registered + ; d = NoSplit (unD ((v !! 0).d)) } -- c1.d comb from in elem 0 d + in DeepSplit (c0 :> c1 :> nil) diff --git a/testsuite/bsc.scheduler/paths/VecStructDeepMulti.bs b/testsuite/bsc.scheduler/paths/VecStructDeepMulti.bs new file mode 100644 index 000000000..4ba0698ff --- /dev/null +++ b/testsuite/bsc.scheduler/paths/VecStructDeepMulti.bs @@ -0,0 +1,35 @@ +package VecStructDeepMulti where + +import SplitPorts +import Vector + +struct Pair = + p1 :: Bool + p2 :: Bool + deriving (Bits) + +-- DeepSplit of a (Vector 3 Pair): each element recurses to leaf ports, so the +-- result ports are get_0_p1 get_0_p2 get_1_p1 get_1_p2 get_2_p1 get_2_p2 and the +-- argument ports are get_1_0_p1 ... get_1_2_p2 (leading 1 = argument number). +-- +-- Several distinct elements are simultaneously combinational, with one CROSSED +-- across vector indices: +-- element 0 : p1 straight-through from input element 0 p1 (get_1_0_p1 -> get_0_p1) +-- element 2 : p2 crossed from input element 1 p2 (get_1_1_p2 -> get_2_p2) +-- everything else is registered, so there must be NO other edges -- in +-- particular no same-index sibling like get_1_0_p2 -> get_0_p1 and no +-- get_1_2_p2 -> get_2_p2 (the source is element 1, not element 2). +interface Ifc = + get :: DeepSplit (Vector 3 Pair) -> DeepSplit (Vector 3 Pair) + +{-# synthesize mkVecStructDeepMulti #-} +mkVecStructDeepMulti :: Module Ifc +mkVecStructDeepMulti = + module + r :: Reg Bool <- mkReg False + interface + get (DeepSplit v) = + let e0 = Pair { p1 = (v !! 0).p1; p2 = r } -- e0.p1 comb from in elem 0 + e1 = Pair { p1 = r; p2 = r } -- all registered + e2 = Pair { p1 = r; p2 = (v !! 1).p2 } -- e2.p2 comb from in elem 1 + in DeepSplit (e0 :> e1 :> e2 :> nil) diff --git a/testsuite/bsc.scheduler/paths/VecStructShallow.bs b/testsuite/bsc.scheduler/paths/VecStructShallow.bs new file mode 100644 index 000000000..ae1950be1 --- /dev/null +++ b/testsuite/bsc.scheduler/paths/VecStructShallow.bs @@ -0,0 +1,36 @@ +package VecStructShallow where + +import SplitPorts +import Vector + +struct Pair = + p1 :: Bool + p2 :: Bool + deriving (Bits) + +-- ShallowSplit of a (Vector 3 Pair): the TOP level (the vector) is unpacked into +-- one port per element, but each element's Pair stays PACKED -- so the ports are +-- get_0 get_1 get_2 (outputs) and get_1_0 get_1_1 get_1_2 (inputs), NOT per-leaf +-- get_0_p1 etc. Contrast with VecStructDeepMulti, where DeepSplit gives leaf +-- ports get_0_p1 / get_0_p2. +-- +-- Two distinct elements are combinational, one crossed across indices: +-- element 0 packed value is combinational from input element 0 (get_1_0 -> get_0) +-- element 2 packed value is combinational from input element 1 (get_1_1 -> get_2) +-- element 1 is fully registered. Because the struct is packed, even a single +-- combinational field makes the whole element's port combinational, and there is +-- no per-field granularity (no get_0_p1). +interface Ifc = + get :: ShallowSplit (Vector 3 Pair) -> ShallowSplit (Vector 3 Pair) + +{-# synthesize mkVecStructShallow #-} +mkVecStructShallow :: Module Ifc +mkVecStructShallow = + module + r :: Reg Bool <- mkReg False + interface + get (ShallowSplit v) = + let e0 = Pair { p1 = (v !! 0).p1; p2 = r } -- only p1 comb, but whole elem 0 port carries it + e1 = Pair { p1 = r; p2 = r } -- fully registered + e2 = Pair { p1 = r; p2 = (v !! 1).p2 } -- p2 comb from input elem 1 + in ShallowSplit (e0 :> e1 :> e2 :> nil) diff --git a/testsuite/bsc.scheduler/paths/paths.exp b/testsuite/bsc.scheduler/paths/paths.exp index 131f684e4..8f2c61f8f 100644 --- a/testsuite/bsc.scheduler/paths/paths.exp +++ b/testsuite/bsc.scheduler/paths/paths.exp @@ -28,6 +28,45 @@ find_regexp sysMethodEnableToArgMux.v { compile_verilog_fail_error PortPath.bsv G0032 +# -------------------------------------------------- +# Tests for path analysis through split (multi-port) method inputs/outputs. +# Each method result is split into one port per struct field, so paths are +# tracked per output port rather than per method. + +# A value method whose result is split into ports: a combinational path is +# reported only to the output port (p1) that depends on the input; the port +# fed from a register (p2) has no path. +compile_verilog_pass SplitOutputPath.bs +find_regexp mkSplitOutputPath.v { +// Combinational paths from inputs to outputs: +// get_1_p1 -> get_p1 +} +find_regexp_fail mkSplitOutputPath.v {-> get_p2} + +# Paths through a submodule's split output method: routing through the +# submodule's combinational result field (p1) yields a path; routing through +# its registered field (p2) does not. +compile_verilog_pass SplitSubmodPath.bs +find_regexp mkSubmodPathComb.v { +// Combinational paths from inputs to outputs: +// top_1 -> top +} +find_regexp mkSubmodPathReg.v { +// No combinational paths from inputs to outputs +} + +# An ActionValue method with a split result: combinational path only to the +# input-dependent output port (p1). +compile_verilog_pass SplitAVPath.bs +find_regexp mkSplitAVPath.v { +// Combinational paths from inputs to outputs: +// upd_1_p1 -> upd_p1 +} +find_regexp_fail mkSplitAVPath.v {-> upd_p2} + +# A combinational loop through a submodule's split output port is detected. +compile_verilog_fail_error SplitOutputLoop.bs G0032 + # -------------------------------------------------- # When methods are allowed to be less urgent than rules, # we will need tests here that check that the "&& !CF_rl" @@ -36,4 +75,645 @@ compile_verilog_fail_error PortPath.bsv G0032 #... # -------------------------------------------------- + +# ================================================== +# Additional path-analysis tests for split (multi-port) method ports +# (deep/shallow, value & ActionValue, submodule, loops, granularity, EN/RDY) +# ================================================== + + +# -------------------------------------------------- +# Deep-split path analysis through NESTED structs (struct whose field is a +# struct). Deep splitting recurses to leaf ports (__), and path +# analysis tracks paths per deep-leaf (input-port, output-port) pair. + +# Outer{x::Inner, y::Inner}: a deep-split value method where each output leaf +# that is combinational from an input leaf shows that exact edge, while leaves +# fed from a register show none. Per-leaf isolation: get_x_a comes from +# get_1_x_a and get_y_b from get_1_y_b; the registered leaves get_x_b / get_y_a +# have no incoming path, and no cross-leaf (e.g. get_1_x_a -> get_x_b) edge. +compile_verilog_pass DeepLeafBasic.bs +find_regexp mkDeepLeafBasic.v { +// Combinational paths from inputs to outputs: +// get_1_x_a -> get_x_a +// get_1_y_b -> get_y_b +} +find_regexp_fail mkDeepLeafBasic.v {-> get_x_b} +find_regexp_fail mkDeepLeafBasic.v {-> get_y_a} + +# Deep-split leaves wired from a DIFFERENT input leaf than the same-named one, +# so path analysis must follow actual data flow, not port-name matching: +# get_x_a <- a.y.b => get_1_y_b -> get_x_a +# get_y_b <- a.x.a => get_1_x_a -> get_y_b +# The naive name-matching edges (get_1_x_a -> get_x_a, get_1_y_b -> get_y_b) +# must NOT appear. +compile_verilog_pass DeepLeafCross.bs +find_regexp mkDeepLeafCross.v { +// Combinational paths from inputs to outputs: +// get_1_x_a -> get_y_b +// get_1_y_b -> get_x_a +} +find_regexp_fail mkDeepLeafCross.v {get_1_x_a -> get_x_a} +find_regexp_fail mkDeepLeafCross.v {get_1_y_b -> get_y_b} + +# Two levels of nesting: Top{m::Mid, n::Mid}, Mid{p::Leaf, q::Leaf}. Deep +# split produces three-component leaf ports (get_1_m_p_lo -> get_m_p_lo). Only +# two of the eight leaves are combinational from their matching input leaf; the +# rest come from a register, isolating the two-levels-deep leaves. +compile_verilog_pass DeepLeafTwoLevels.bs +find_regexp mkDeepLeafTwoLevels.v { +// Combinational paths from inputs to outputs: +// get_1_m_p_lo -> get_m_p_lo +// get_1_n_q_hi -> get_n_q_hi +} +find_regexp_fail mkDeepLeafTwoLevels.v {-> get_m_p_hi} +find_regexp_fail mkDeepLeafTwoLevels.v {get_1_m_q_lo ->} + +# Each deep leaf of Outer{x::Inner, y::Inner} is driven by a different source: +# combinational input (get_x_a <- a.x.a), constant (get_x_b <- True, +# get_y_b <- False), and register (get_y_a <- r). Only the combinational leaf +# yields a path; constant- and register-fed leaves do not, and no unused input +# leaf (get_1_x_b / get_1_y_a / get_1_y_b) appears as a path source. +compile_verilog_pass DeepLeafConst.bs +find_regexp mkDeepLeafConst.v { +// Combinational paths from inputs to outputs: +// get_1_x_a -> get_x_a +} +find_regexp_fail mkDeepLeafConst.v {-> get_x_b} +find_regexp_fail mkDeepLeafConst.v {-> get_y_a} +find_regexp_fail mkDeepLeafConst.v {get_1_y_b ->} + +# A combinational loop closed through a submodule's DEEP leaf port (the x.a leaf +# is combinational input->output in the submodule, and an RWire feeds its output +# leaf back to its input leaf). Path analysis detects the cycle through the +# per-leaf result node, so compilation fails with G0032. +compile_verilog_fail_error DeepLeafLoop.bs G0032 + + +# IOMatrixCross: value method, ShallowSplit Pair in+out, output fields are +# CROSSED from the inputs (out p1 <= in p2, out p2 <= in p1). Asserts both +# crossed edges exist and neither straight-through edge does. +compile_verilog_pass IOMatrixCross.bs +find_regexp mkIOMatrixCross.v { +// get_1_p1 -> get_p2 +// get_1_p2 -> get_p1 +} +find_regexp_fail mkIOMatrixCross.v {get_1_p1 -> get_p1} +find_regexp_fail mkIOMatrixCross.v {get_1_p2 -> get_p2} + +# IOMatrixCombine: value method, ShallowSplit Pair in+out, output field p1 +# COMBINES both split inputs (a.p1 && a.p2); output field p2 is registered. +# Asserts the single combined edge (both inputs -> get_p1) exists and that +# nothing reaches get_p2. +compile_verilog_pass IOMatrixCombine.bs +find_regexp mkIOMatrixCombine.v {\(get_1_p1, get_1_p2\) -> get_p1} +find_regexp_fail mkIOMatrixCombine.v {-> get_p2} + +# IOMatrixFanout: value method, ShallowSplit Pair in+out, single input field +# p1 FANS OUT to both output fields (p1 = a.p1, p2 = not a.p1); input field p2 +# feeds nothing. Asserts both fan-out edges exist and that get_1_p2 drives no +# output. +compile_verilog_pass IOMatrixFanout.bs +find_regexp mkIOMatrixFanout.v { +// get_1_p1 -> get_p1 +// get_1_p1 -> get_p2 +} +find_regexp_fail mkIOMatrixFanout.v {get_1_p2 ->} + +# IOMatrixDeepCross: value method, DeepSplit of a nested struct (Outer with an +# Inner field). DeepSplit recurses to leaf ports get_1_x_a/get_1_x_b/get_1_y. +# The two inner leaves are CROSSED (out x_a <= in x_b, out x_b <= in x_a) and +# the top-level y passes straight through. Asserts the crossed deep edges and +# the straight y edge, and that neither straight inner edge exists. +compile_verilog_pass IOMatrixDeepCross.bs +find_regexp mkIOMatrixDeepCross.v { +// get_1_x_a -> get_x_b +// get_1_x_b -> get_x_a +// get_1_y -> get_y +} +find_regexp_fail mkIOMatrixDeepCross.v {get_1_x_a -> get_x_a} +find_regexp_fail mkIOMatrixDeepCross.v {get_1_x_b -> get_x_b} + +# IOMatrixDeepCombine: value method, DeepSplit nested struct. Each inner +# output leaf COMBINES a disjoint pair of input leaves (x_a <= x_a && y, +# x_b <= x_b && y); the top-level output y is registered. Asserts both +# combined deep edges exist and that nothing reaches get_y. +compile_verilog_pass IOMatrixDeepCombine.bs +find_regexp mkIOMatrixDeepCombine.v {\(get_1_x_a, get_1_y\) -> get_x_a} +find_regexp mkIOMatrixDeepCombine.v {\(get_1_x_b, get_1_y\) -> get_x_b} +find_regexp_fail mkIOMatrixDeepCombine.v {-> get_y} + + +# -------------------------------------------------- +# AV dimension: ActionValue methods with SPLIT INPUT args. + +# An ActionValue method with both a split input arg and a split result, +# wired "crossed": output upd_p1 is combinational from input upd_1_p2 and +# output upd_p2 from input upd_1_p1. Demonstrates per-INPUT-port tracking: +# each split output depends on exactly one specific split input, and the +# "diagonal" edges (upd_1_p1 -> upd_p1, upd_1_p2 -> upd_p2) are absent. +compile_verilog_pass AVSplitInPath.bs +find_regexp mkAVSplitInPath.v { +// Combinational paths from inputs to outputs: +// upd_1_p1 -> upd_p2 +// upd_1_p2 -> upd_p1 +} +find_regexp_fail mkAVSplitInPath.v {upd_1_p1 -> upd_p1} +find_regexp_fail mkAVSplitInPath.v {upd_1_p2 -> upd_p2} + +# An ActionValue method whose split input arg is threaded straight through a +# submodule's split input/output. Only input upd_1_p1 reaches the +# submodule's combinational result field, so the single path is +# upd_1_p1 -> upd_p1; input upd_1_p2 feeds only the submodule's registered +# field (no path), and output upd_p2 (registered) has no path. +compile_verilog_pass AVSubmodInPath.bs +find_regexp mkAVSubmodInPath.v { +// Combinational paths from inputs to outputs: +// upd_1_p1 -> upd_p1 +} +find_regexp_fail mkAVSubmodInPath.v {upd_1_p2 ->} +find_regexp_fail mkAVSubmodInPath.v {-> upd_p2} + +# An ActionValue method whose split input port indexes a single-ported +# combinational submodule read, with a rule using the same read port (so the +# index is muxed by EN_upd). The data path upd_1_p1 -> upd_p1 is reported; +# the analysis does NOT add a spurious EN_upd -> upd_p1 edge, and the +# registered field upd_p2 has no path. Exercises split AV input through a +# submodule's declared combinational result with an enable-muxed argument. +compile_verilog_pass AVEnArgMuxPath.bs +find_regexp mkAVEnArgMuxPath.v { +// Combinational paths from inputs to outputs: +// upd_1_p1 -> upd_p1 +} +find_regexp_fail mkAVEnArgMuxPath.v {EN_upd ->} +find_regexp_fail mkAVEnArgMuxPath.v {-> upd_p2} + + + +# -------------------------------------------------- +# Tests for path analysis through a SUBMODULE's split (multi-port) method +# ports. The top module threads its (possibly split) inputs through a +# submodule whose argument and/or result are split into per-field ports, and +# path analysis must track reachability at the per-port granularity through +# the submodule's argument and result nodes. + +# Routes the top's split input ports straight through the submodule's split +# *argument* ports and out the submodule's split result ports. The submodule +# result p1 is combinational from arg p1 while p2 is registered, so the only +# path is top_1_p1 -> top_p1 (established through the submodule's per-port +# argument node get_1_p1). There is no cross-edge into top_p2. +compile_verilog_pass SubmodInputArgPath.bs +find_regexp mkSubmodInputArgPath.v { +// Combinational paths from inputs to outputs: +// top_1_p1 -> top_p1 +} +find_regexp_fail mkSubmodInputArgPath.v {-> top_p2} + +# A DEEP-split submodule: the nested Inner struct is recursed to leaf ports. +# Leaf x.a and field y are combinational through the submodule while leaf x.b +# is registered, so paths are tracked at leaf granularity: +# top_1_x_a -> top_x_a and top_1_y -> top_y, with nothing reaching the +# registered leaf top_x_b. +compile_verilog_pass SubmodDeepLeafPath.bs +find_regexp mkSubmodDeepLeafPath.v { +// Combinational paths from inputs to outputs: +// top_1_x_a -> top_x_a +// top_1_y -> top_y +} +find_regexp_fail mkSubmodDeepLeafPath.v {-> top_x_b} + +# Muxes between TWO of the submodule's combinational split output ports +# (get_p1 / get_p2) under a select input, driving a single top output. Both +# the data input (top_1, feeding both submodule arg ports) and the select +# input (top_2) reach the output: (top_1, top_2) -> top. The submodule's +# registered output port get_p3 is never selected and contributes no path. +compile_verilog_pass SubmodSelectOutPath.bs +find_regexp mkSubmodSelectOutPath.v { +// Combinational paths from inputs to outputs: +// \(top_1\, top_2\) -> top +} + +# Crossbar through DISTINCT submodule split output ports: top output q1 is fed +# from submodule output get_p2 and top output q2 from get_p1, so the paths are +# crossed (top_1_q1 -> top_q2 and top_1_q2 -> top_q1) with NO straight-through +# top_1_q1 -> top_q1. The submodule's registered output get_p3 reaches +# neither top output port. +compile_verilog_pass SubmodCrossbarPath.bs +find_regexp mkSubmodCrossbarPath.v { +// Combinational paths from inputs to outputs: +// top_1_q1 -> top_q2 +// top_1_q2 -> top_q1 +} +find_regexp_fail mkSubmodCrossbarPath.v {top_1_q1 -> top_q1} + + +# -------------------------------------------------- +# Per-port combinational LOOP detection through SPLIT (multi-port) method ports. + + +# Splitting AVOIDS a false loop: the top feeds its input into a submodule's +# split input p1 and the submodule's combinational output p1 into a *second* +# submodule's split input p2. Since out-p1 depends only on in-p1 (never in-p2), +# the feedback into in-p2 is a dead end, so there is no loop -- only the real +# path top_1 -> top (from g2.in_p1) remains. Packed ports would risk a false +# loop here. +compile_verilog_pass LoopNoFalseLoop.bs +find_regexp mkLoopNoFalseLoop.v { +// Combinational paths from inputs to outputs: +// top_1 -> top +} + +# A combinational loop that re-enters the SPLIT INPUT arg port p1 of a submodule +# that combinationally SWAPS its fields (out_p1 = in_p2, out_p2 = in_p1). The +# feedback drives in_p1 and reads the swapped out_p2, closing the cycle through +# "Argument 1" of the split method => G0032. +compile_verilog_fail_error LoopInputArgLoop.bs G0032 + +# A combinational loop through an ActionValue method's SPLIT ports: the AV +# result's split output p1 (combinational from split input p1) is consumed and +# drives the RWire whose value feeds the AV's split input p1 => G0032. +compile_verilog_fail_error LoopAVPortLoop.bs G0032 + +# Sibling to LoopInputArgLoop: feed the top input into the same SWAP submodule's +# split input p1 but RETURN its split output p1. Because out_p1 = in_p2 (not +# in_p1), the input on p1 reaches only the discarded out_p2, so per-port +# discrimination reports NO combinational paths (and no loop). Reading the +# *wrong* swapped port is what made LoopInputArgLoop loop. +compile_verilog_pass LoopSwapNoLoop.bs +find_regexp mkLoopSwapNoLoop.v { +// No combinational paths from inputs to outputs +} + + +# -------------------------------------------------- +# Granularity + composition tests for split (multi-port) method ports. + +# Same nested struct as a ShallowSplit result: only the TOP level is split, so +# the nested field x stays PACKED as one port (get_x). The combinational path +# is reported at the coarse packed granularity: get_1_x -> get_x. No per-leaf +# ports (get_x_a) exist. Contrast with GranDeepNested below. +compile_verilog_pass GranShallowNested.bs +find_regexp mkGranShallowNested.v { +// Combinational paths from inputs to outputs: +// get_1_x -> get_x +} +find_regexp_fail mkGranShallowNested.v {get_x_a} + +# Same nested struct as a DeepSplit result: recursion splits the nested field +# into leaf ports (get_x_a, get_x_b). Only x.a is combinational from the input, +# so the path is reported at per-leaf granularity (get_1_x_a -> get_x_a) and the +# registered leaves get_x_b / get_y have no path. This shows the finer +# granularity of DeepSplit vs the packed ShallowSplit path above. +compile_verilog_pass GranDeepNested.bs +find_regexp mkGranDeepNested.v { +// Combinational paths from inputs to outputs: +// get_1_x_a -> get_x_a +} +find_regexp_fail mkGranDeepNested.v {-> get_x_b} +find_regexp_fail mkGranDeepNested.v {-> get_y} + +# Two split arguments named lhs/rhs via the arg_names pragma. Path analysis +# distinguishes sub-ports of arg lhs from arg rhs: result p1 is combinational +# from lhs.p1 and result p2 from rhs.p2, yielding exactly the edges +# combine_lhs_p1 -> combine_p1 and combine_rhs_p2 -> combine_p2, but NOT the +# cross edges combine_lhs_p2 -> combine_p2 or combine_rhs_p1 -> combine_p1. +compile_verilog_pass GranTwoArgs.bs +find_regexp mkGranTwoArgs.v { +// Combinational paths from inputs to outputs: +// combine_lhs_p1 -> combine_p1 +// combine_rhs_p2 -> combine_p2 +} +find_regexp_fail mkGranTwoArgs.v {combine_lhs_p2 -> combine_p2} +find_regexp_fail mkGranTwoArgs.v {combine_rhs_p1 -> combine_p1} + +# DeepSplit of a (Vector 3 Bool): each element becomes its own port (input +# get_1_0/get_1_1/get_1_2, output get_0/get_1/get_2). Result element 2 is +# combinational from input element 2, so the path is exactly get_1_2 -> get_2; +# the register-fed elements get_0 / get_1 have no incoming path. +compile_verilog_pass GranVec.bs +find_regexp mkGranVec.v { +// Combinational paths from inputs to outputs: +// get_1_2 -> get_2 +} +find_regexp_fail mkGranVec.v {-> get_0} + +# NoSplit terminates the DeepSplit recursion: the field x (wrapped in NoSplit) +# stays as ONE packed port (get_x) instead of leaf ports get_x_a / get_x_b, so +# the path is reported at the packed granularity get_1_x -> get_x. The leaf y +# is register-fed and has no path. +compile_verilog_pass GranNoSplit.bs +find_regexp mkGranNoSplit.v { +// Combinational paths from inputs to outputs: +// get_1_x -> get_x +} +find_regexp_fail mkGranNoSplit.v {get_x_a} +find_regexp_fail mkGranNoSplit.v {-> get_y} + + +# -------------------------------------------------- +# EN/RDY interaction with split (multi-port) method ports. + +# An Action method's enable (EN_doit) feeds a *split* value-output port: only the +# field driven by EN (rd_p1) has a combinational path; the constant field rd_p2 +# has none. Shows EN_ -> _ per split output port. +compile_verilog_pass EnRdyEnToSplitOut.bs +find_regexp mkEnRdyEnToSplitOut.v { +// Combinational paths from inputs to outputs: +// EN_doit -> rd_p1 +} +find_regexp_fail mkEnRdyEnToSplitOut.v {-> rd_p2} + +# A split INPUT sub-port feeds another method's RDY. 'put' forwards its split +# input field p1 onto an RWire whose value gates value-method 'gate', so the path +# is (put_1_p1, EN_put) -> RDY_gate. The other split input port (put_1_p2) is +# never forwarded, so it does not appear in any path; RDY_put has none either. +compile_verilog_pass EnRdyInToRdy.bs +find_regexp mkEnRdyInToRdy.v { +// Combinational paths from inputs to outputs: +// \(put_1_p1, EN_put\) -> RDY_gate +} +find_regexp_fail mkEnRdyInToRdy.v {put_1_p2 ->} +find_regexp_fail mkEnRdyInToRdy.v {-> RDY_put} + +# An Action method's enable reaches a DEEP-split leaf output port. rd's deep +# result has nested struct field x.a (port rd_x_a) driven by EN_fire; sibling +# leaves rd_x_b and rd_y come from registers, so only rd_x_a has a path. +compile_verilog_pass EnRdyDeepEnOut.bs +find_regexp mkEnRdyDeepEnOut.v { +// Combinational paths from inputs to outputs: +// EN_fire -> rd_x_a +} +find_regexp_fail mkEnRdyDeepEnOut.v {-> rd_x_b} +find_regexp_fail mkEnRdyDeepEnOut.v {-> rd_y} + +# An ActionValue method with a split result combined with an EN edge. Each split +# input port maps to its own split output port (upd_1_p1 -> upd_p1, +# upd_1_p2 -> upd_p2) with no crossed edges, and the method's enable reaches a +# separate value output (EN_upd -> busy). +compile_verilog_pass EnRdyAVEnResult.bs +find_regexp mkEnRdyAVEnResult.v { +// Combinational paths from inputs to outputs: +// upd_1_p1 -> upd_p1 +// upd_1_p2 -> upd_p2 +// EN_upd -> busy +} +find_regexp_fail mkEnRdyAVEnResult.v {upd_1_p1 -> upd_p2} +find_regexp_fail mkEnRdyAVEnResult.v {upd_1_p2 -> upd_p1} + +# Two distinct method enables route to two distinct split output ports: +# EN_setA -> rd_p1 and EN_setB -> rd_p2, with no crossed edges. Demonstrates +# per-port tracking of separate enables into a single split result. +compile_verilog_pass EnRdyTwoEnSplit.bs +find_regexp mkEnRdyTwoEnSplit.v { +// Combinational paths from inputs to outputs: +// EN_setA -> rd_p1 +// EN_setB -> rd_p2 +} +find_regexp_fail mkEnRdyTwoEnSplit.v {EN_setA -> rd_p2} +find_regexp_fail mkEnRdyTwoEnSplit.v {EN_setB -> rd_p1} + + +# MIXED-KIND: split argument, single PACKED result depending on ONE split input +# field. The packed output port (get) has a path from get_1_p1 only; the other +# split input field (get_1_p2) is ignored, so no get_1_p2 -> get edge. Verifies +# per-input tracking across the split->packed boundary. +compile_verilog_pass SplitInPackedOneField.bs +find_regexp mkSplitInPackedOneField.v { +// Combinational paths from inputs to outputs: +// get_1_p1 -> get +} +find_regexp_fail mkSplitInPackedOneField.v {get_1_p2 -> get} + +# MIXED-KIND (reverse): single PACKED Bool argument feeding a SPLIT result. The +# plain input fans into the first split output field (get_p1) combinationally; +# the second split output field (get_p2) is registered. So get_1 -> get_p1 is +# reported but get_1 -> get_p2 is not -- asymmetric edge across the packed->split +# boundary. +compile_verilog_pass PackedInSplitOut.bs +find_regexp mkPackedInSplitOut.v { +// Combinational paths from inputs to outputs: +// get_1 -> get_p1 +} +find_regexp_fail mkPackedInSplitOut.v {get_1 -> get_p2} + +# MIXED-KIND (merge): split argument (BOTH fields), single PACKED Bool result +# (a.p1 || a.p2). Both split input ports combine into the one packed output, so +# the analysis reports a single combined edge (get_1_p1, get_1_p2) -> get rather +# than two separate edges. Asserts the combined edge exists and the individual +# get_1_p1 -> get edge does NOT. +compile_verilog_pass SplitInPackedCombine.bs +find_regexp mkSplitInPackedCombine.v { +// Combinational paths from inputs to outputs: +// \(get_1_p1\, get_1_p2\) -> get +} +find_regexp_fail mkSplitInPackedCombine.v {get_1_p1 -> get} + + +# A single split INPUT sub-port fanning out across METHOD boundaries: one Action +# method forwards only field p1 of its split arg onto a combinational RWire, and +# two DISTINCT value methods (outA, outB) both read it. So put_1_p1 reaches the +# outputs of two different methods, while its sibling put_1_p2 (never written to +# the wire) reaches neither. +compile_verilog_pass RWireFanout.bs +find_regexp mkRWireFanout.v {// Combinational paths from inputs to outputs: +// \(put_1_p1\, EN_put\) -> outA +// \(put_1_p1\, EN_put\) -> outB} +find_regexp_fail mkRWireFanout.v {put_1_p2 ->} + +# DeepSplit version of the cross-method fanout: the shared source is a deep leaf +# sub-port (put_1_a_x) of a nested struct. One Action method forwards only that +# leaf onto a combinational wire; two distinct value methods read it, so the leaf +# fans out to outputs of two methods, while sibling leaves put_1_a_y and put_1_b +# reach neither. +compile_verilog_pass DeepWireFanout.bs +find_regexp mkDeepWireFanout.v {// Combinational paths from inputs to outputs: +// \(put_1_a_x\, EN_put\) -> outA +// \(put_1_a_x\, EN_put\) -> outB} +find_regexp_fail mkDeepWireFanout.v {put_1_a_y ->} +find_regexp_fail mkDeepWireFanout.v {put_1_b ->} + +# Disjoint per-source fanout across method boundaries: the Action method forwards +# each split input field onto its own wire. Field p1 fans out to TWO methods +# (outA, outB); the sibling field p2 reaches a DIFFERENT third method (outC) only. +# Path analysis keeps the two sources independent: no put_1_p1 -> outC edge and +# no put_1_p2 -> outA edge. +compile_verilog_pass SiblingDisjointFanout.bs +find_regexp mkSiblingDisjointFanout.v {// Combinational paths from inputs to outputs: +// \(put_1_p1\, EN_put\) -> outA +// \(put_1_p1\, EN_put\) -> outB +// \(put_1_p2\, EN_put\) -> outC} +find_regexp_fail mkSiblingDisjointFanout.v {put_1_p1\, EN_put\) -> outC} +find_regexp_fail mkSiblingDisjointFanout.v {put_1_p2\, EN_put\) -> outA} + + +# -------------------------------------------------- +# Tagged-union / multi-constructor split: a struct field that is a 2-constructor +# type (Maybe, or a user enum-with-payload) is kept PACKED as one port, even +# under ShallowSplit/DeepSplit, since SplitPorts only splits single-constructor +# structs/vectors. These verify the tag+payload port naming and that paths are +# tracked at the granularity of that single packed union port. + +# ShallowSplit: the Maybe field stays a single packed port (get_1_mb / get_mb). +# The plain output flag is combinational from the packed union input, so the +# only path is get_1_mb -> get_flag. The union output (get_mb) is register-fed +# (no path), and the flat input get_1_flag is unused (no path). +compile_verilog_pass MaybeShallow.bs +find_regexp mkMaybeShallow.v { +// Combinational paths from inputs to outputs: +// get_1_mb -> get_flag +} +find_regexp_fail mkMaybeShallow.v {-> get_mb} +find_regexp_fail mkMaybeShallow.v {get_1_flag ->} + +# DeepSplit: recursion splits the outer struct into leaf ports but TERMINATES +# at the 2-constructor Maybe field, so get_1_mb / get_mb are single packed ports +# (no get_1_mb_* subports). Tag and payload both flow through, giving the only +# path get_1_mb -> get_mb. The leaf output get_lo is register-fed (no path) and +# the leaf input get_1_lo is unused (no path). +compile_verilog_pass MaybeDeep.bs +find_regexp mkMaybeDeep.v { +// Combinational paths from inputs to outputs: +// get_1_mb -> get_mb +} +find_regexp_fail mkMaybeDeep.v {-> get_lo} +find_regexp_fail mkMaybeDeep.v {get_1_lo ->} +find_regexp_fail mkMaybeDeep.v {get_1_mb_} + +# A user-defined 2-constructor union WITH a payload (data Cmd = Nop | Run Bool): +# the same packing applies (step_1_cmd / step_echo are single packed ports). +# The packed union input flows only to the packed union output (step_1_cmd -> +# step_echo); the plain Bool output step_ack is register-fed and the plain input +# step_1_sel is unused, demonstrating per-port granularity. +compile_verilog_pass UnionPayload.bs +find_regexp mkUnionPayload.v { +// Combinational paths from inputs to outputs: +// step_1_cmd -> step_echo +} +find_regexp_fail mkUnionPayload.v {-> step_ack} +find_regexp_fail mkUnionPayload.v {step_1_sel ->} + + +# -------------------------------------------------- +# A split method-input SELECTOR field data-dependently muxes between two +# distinct single-ported combinational submodule reads (each read indexed by a +# separate split data field), driving one unsplit output. The selector edge +# must appear alongside both selected data fields, while the unused 'dead' field +# (still a real input port) contributes no path. +compile_verilog_pass SelectorMuxPath.bs +find_regexp mkSelectorMuxPath.v { +// Combinational paths from inputs to outputs: +// \(run_1_sel, run_1_a, run_1_b\) -> run +} +find_regexp_fail mkSelectorMuxPath.v {run_1_dead ->} + +# -------------------------------------------------- +# Same selector-mux pattern, but with a SPLIT output: each split output port is +# muxed by the SAME selector field but a DIFFERENT data field (o1 from a, o2 +# from b). Per-(input,output)-port tracking attributes the selector edge to +# each output port together with ONLY the data field that output consumes: +# (sel, a) -> o1 and (sel, b) -> o2, with no cross edges and no 'dead'. +compile_verilog_pass SelectorSplitOutPath.bs +find_regexp mkSelectorSplitOutPath.v { +// Combinational paths from inputs to outputs: +// \(run_1_sel, run_1_a\) -> run_o1 +// \(run_1_sel, run_1_b\) -> run_o2 +} +find_regexp_fail mkSelectorSplitOutPath.v {run_1_b\) -> run_o1} +find_regexp_fail mkSelectorSplitOutPath.v {run_1_a\) -> run_o2} +find_regexp_fail mkSelectorSplitOutPath.v {run_1_dead.*->} + +# -------------------------------------------------- +# A split method-input selector field muxes between a MODULE ARGUMENT (port +# input 'v') and a split data field, driving one unsplit output. The path +# enters via the split method input and exits through the module's own +# argument-driven logic, so the output depends on (run_1_sel, run_1_d, v); the +# unused split field 'dead' contributes no path. +compile_verilog_pass ArgSelectorPath.bs +find_regexp mkArgSelectorPath.v { +// Combinational paths from inputs to outputs: +// \(run_1_sel, run_1_d, v\) -> run +} +find_regexp_fail mkArgSelectorPath.v {run_1_dead ->} + + +# VecStructDeepMulti: DeepSplit (Vector 3 Pair) -> leaf ports per element +# (get_0_p1 .. get_2_p2). Two simultaneous combinational edges, one CROSSED across +# vector indices: elem0 p1 straight-through (get_1_0_p1 -> get_0_p1) and elem2 p2 +# sourced from input elem1 p2 (get_1_1_p2 -> get_2_p2). Asserts both edges exist +# and that no same-index sibling / wrong-source edge appears. +compile_verilog_pass VecStructDeepMulti.bs +find_regexp mkVecStructDeepMulti.v { +// Combinational paths from inputs to outputs: +// get_1_0_p1 -> get_0_p1 +// get_1_1_p2 -> get_2_p2 +} +find_regexp_fail mkVecStructDeepMulti.v {get_1_0_p2 -> get_0_p1} +find_regexp_fail mkVecStructDeepMulti.v {get_1_2_p2 -> get_2_p2} + +# VecStructShallow: ShallowSplit (Vector 3 Pair) -> the vector is unpacked into +# one PACKED port per element (get_0 get_1 get_2 / get_1_0 ..), with NO per-field +# leaf granularity (contrast VecStructDeepMulti). Two edges, one crossed across +# indices: get_1_0 -> get_0 and get_1_1 -> get_2. Asserts the packed edges exist and +# that no leaf port name like get_0_p1 ever appears. +compile_verilog_pass VecStructShallow.bs +find_regexp mkVecStructShallow.v { +// Combinational paths from inputs to outputs: +// get_1_0 -> get_0 +// get_1_1 -> get_2 +} +find_regexp_fail mkVecStructShallow.v {get_0_p1} +find_regexp_fail mkVecStructShallow.v {get_1_2 ->} + +# VecNestedDeep: DeepSplit (Vector 2 Cell) where Cell has a nested struct field +# c (recursed to multi-level leaves get_0_c_a / get_0_c_b) and a NoSplit field d that +# TERMINATES recursion (stays packed as get_0_d). Two edges, one crossed across +# indices: deep leaf get_1_0_c_a -> get_0_c_a and NoSplit-packed leaf get_1_0_d -> +# get_1_d (source elem0, dest elem1). Asserts both edges and absence of the +# registered / wrong-index siblings. +compile_verilog_pass VecNestedDeep.bs +find_regexp mkVecNestedDeep.v { +// Combinational paths from inputs to outputs: +// get_1_0_c_a -> get_0_c_a +// get_1_0_d -> get_1_d +} +find_regexp_fail mkVecNestedDeep.v {get_1_1_d -> get_1_d} +find_regexp_fail mkVecNestedDeep.v {-> get_0_c_b} + + +# Per-port loop discrimination: a genuine combinational loop confined to split +# field p1 of method `get'. The cycle MUST be detected (G0032) and the cycle +# report must name exactly the offending split port -- "Argument 1"/"Return +# value 1" of `get' -- and NOT the sibling field p2's ports. Counterpart to the +# passing no-loop tests, proving per-port (not whole-method) cycle reporting. +compile_verilog_fail_error LoopConfinedP1.bs G0032 +find_regexp LoopConfinedP1.bs.bsc-vcomp-out {Argument 1 of method `get'} +find_regexp LoopConfinedP1.bs.bsc-vcomp-out {Return value 1 of method `get'} +find_regexp_fail LoopConfinedP1.bs.bsc-vcomp-out {Argument 2 of method `get'} +find_regexp_fail LoopConfinedP1.bs.bsc-vcomp-out {Return value 2 of method `get'} + +# Mirror image of LoopConfinedP1: the loop is confined to split field p2, so the +# G0032 cycle report must name "Argument 2"/"Return value 2" of `get' and NOT +# "Argument 1"/"Return value 1". Together with LoopConfinedP1 this proves the +# positional split-port index in the cycle report genuinely discriminates the +# offending field (it is not always reported as port "1"). +compile_verilog_fail_error LoopConfinedP2.bs G0032 +find_regexp LoopConfinedP2.bs.bsc-vcomp-out {Argument 2 of method `get'} +find_regexp LoopConfinedP2.bs.bsc-vcomp-out {Return value 2 of method `get'} +find_regexp_fail LoopConfinedP2.bs.bsc-vcomp-out {Argument 1 of method `get'} +find_regexp_fail LoopConfinedP2.bs.bsc-vcomp-out {Return value 1 of method `get'} + +# Per-split-port discrimination across MULTIPLE split arguments. Method `op' +# takes two split Pair arguments, so its input split ports are numbered 1,2 +# (arg1.p1, arg1.p2) and 3,4 (arg2.p1, arg2.p2). The loop is confined to +# arg2's field p1 == split input port 3, reaching result field p1 == return +# value 1. G0032 must name "Argument 3"/"Return value 1" of `op' and NOT +# "Argument 1", "Argument 2", or "Return value 2" -- demonstrating that the +# cycle report indexes the precise split port, not the whole method argument. +compile_verilog_fail_error LoopConfinedArg2.bs G0032 +find_regexp LoopConfinedArg2.bs.bsc-vcomp-out {Argument 3 of method `op'} +find_regexp LoopConfinedArg2.bs.bsc-vcomp-out {Return value 1 of method `op'} +find_regexp_fail LoopConfinedArg2.bs.bsc-vcomp-out {Argument 1 of method `op'} +find_regexp_fail LoopConfinedArg2.bs.bsc-vcomp-out {Argument 2 of method `op'} +find_regexp_fail LoopConfinedArg2.bs.bsc-vcomp-out {Return value 2 of method `op'} + } diff --git a/testsuite/bsc.syntax/bsv05/statename/sysStateNameTest.atsexpand.expected b/testsuite/bsc.syntax/bsv05/statename/sysStateNameTest.atsexpand.expected index d17fd6768..f8a25e7e7 100644 --- a/testsuite/bsc.syntax/bsv05/statename/sysStateNameTest.atsexpand.expected +++ b/testsuite/bsc.syntax/bsv05/statename/sysStateNameTest.atsexpand.expected @@ -26,7 +26,7 @@ b :: ABSTRACT: Prelude.VReg = RegN []) [clock { osc: CLK gate: 1'd1 }, reset { wire: RST_N }, 32'd16, 16'd11] [] - meth types=[([], Nothing, Just (Bit 16)), ([Bit 16], Just (Bit 1), Nothing)] + meth types=[([], Nothing, [Bit 16]), ([Bit 16], Just (Bit 1), [])] port types=D_IN -> Prelude.Bit 16 Q_OUT -> Prelude.Bit 16 -- AP rules diff --git a/testsuite/bsc.syntax/bsv05/statename/sysStateNameTest2.atsexpand.expected b/testsuite/bsc.syntax/bsv05/statename/sysStateNameTest2.atsexpand.expected index 927832b19..07d0442fc 100644 --- a/testsuite/bsc.syntax/bsv05/statename/sysStateNameTest2.atsexpand.expected +++ b/testsuite/bsc.syntax/bsv05/statename/sysStateNameTest2.atsexpand.expected @@ -26,7 +26,7 @@ b :: ABSTRACT: Prelude.VReg = RegN []) [clock { osc: CLK gate: 1'd1 }, reset { wire: RST_N }, 32'd16, 16'd11] [] - meth types=[([], Nothing, Just (Bit 16)), ([Bit 16], Just (Bit 1), Nothing)] + meth types=[([], Nothing, [Bit 16]), ([Bit 16], Just (Bit 1), [])] port types=D_IN -> Prelude.Bit 16 Q_OUT -> Prelude.Bit 16 -- AP rules diff --git a/testsuite/bsc.syntax/bsv05/statename/sysUseMod2.atsexpand.expected b/testsuite/bsc.syntax/bsv05/statename/sysUseMod2.atsexpand.expected index 0d67520e6..d1c6302b1 100644 --- a/testsuite/bsc.syntax/bsv05/statename/sysUseMod2.atsexpand.expected +++ b/testsuite/bsc.syntax/bsv05/statename/sysUseMod2.atsexpand.expected @@ -27,7 +27,7 @@ the_e_the_r :: ABSTRACT: Prelude.VReg = RegN []) [clock { osc: CLK gate: 1'd1 }, reset { wire: RST_N }, 32'd32, 32'd0] [] - meth types=[([], Nothing, Just (Bit 32)), ([Bit 32], Just (Bit 1), Nothing)] + meth types=[([], Nothing, [Bit 32]), ([Bit 32], Just (Bit 1), [])] port types=D_IN -> Prelude.Bit 32 Q_OUT -> Prelude.Bit 32 -- AP rules diff --git a/testsuite/bsc.syntax/bsv05/statename/sysUseMod2Arrow.atsexpand.expected b/testsuite/bsc.syntax/bsv05/statename/sysUseMod2Arrow.atsexpand.expected index 0112a34a6..392d85adb 100644 --- a/testsuite/bsc.syntax/bsv05/statename/sysUseMod2Arrow.atsexpand.expected +++ b/testsuite/bsc.syntax/bsv05/statename/sysUseMod2Arrow.atsexpand.expected @@ -27,7 +27,7 @@ e_r :: ABSTRACT: Prelude.VReg = RegN []) [clock { osc: CLK gate: 1'd1 }, reset { wire: RST_N }, 32'd32, 32'd0] [] - meth types=[([], Nothing, Just (Bit 32)), ([Bit 32], Just (Bit 1), Nothing)] + meth types=[([], Nothing, [Bit 32]), ([Bit 32], Just (Bit 1), [])] port types=D_IN -> Prelude.Bit 32 Q_OUT -> Prelude.Bit 32 -- AP rules diff --git a/testsuite/bsc.typechecker/dontcare/DummyInRuleQual.bs.bsc-vcomp-out.expected b/testsuite/bsc.typechecker/dontcare/DummyInRuleQual.bs.bsc-vcomp-out.expected index ae51d3faf..48db7e8b2 100644 --- a/testsuite/bsc.typechecker/dontcare/DummyInRuleQual.bs.bsc-vcomp-out.expected +++ b/testsuite/bsc.typechecker/dontcare/DummyInRuleQual.bs.bsc-vcomp-out.expected @@ -33,7 +33,7 @@ r :: ABSTRACT: Prelude.VReg = RegUN []) [clock { osc: CLK gate: 1'd1 }, 32'd12] [] - meth types=[([], Nothing, Just (Bit 12)), ([Bit 12], Just (Bit 1), Nothing)] + meth types=[([], Nothing, [Bit 12]), ([Bit 12], Just (Bit 1), [])] port types=D_IN -> Prelude.Bit 12 Q_OUT -> Prelude.Bit 12 -- AP local definitions diff --git a/testsuite/bsc.verilog/noinline/NoInline_ResNotInBits.bsv.bsc-vcomp-out.expected b/testsuite/bsc.verilog/noinline/NoInline_ResNotInBits.bsv.bsc-vcomp-out.expected index 4a6acf299..fb77799ff 100644 --- a/testsuite/bsc.verilog/noinline/NoInline_ResNotInBits.bsv.bsc-vcomp-out.expected +++ b/testsuite/bsc.verilog/noinline/NoInline_ResNotInBits.bsv.bsc-vcomp-out.expected @@ -4,12 +4,6 @@ Error: "NoInline_ResNotInBits.bsv", line 4, column 12: (T0043) Cannot synthesize `module_fnNoInline_ResNotInBits­': The interface method `fnNoInline_ResNotInBits' uses type(s) that are not in the Bits or SplitPorts typeclasses: NoInline_ResNotInBits::L -Error: "NoInline_ResNotInBits.bsv", line 4, column 12: (T0029) - Signature mismatch (given too general): - given: - function b__ f(Bit#(1) x1) provisos (Bits#(NoInline_ResNotInBits::L, a__)) - deduced: - function Bit#(c__) f(Bit#(1) x1) provisos (Bits#(NoInline_ResNotInBits::L, c__)) Error: Unknown position: (T0031) The provisos for this expression could not be resolved because there are no instances of the form: diff --git a/testsuite/bsc.verilog/splitports/DeepSplit.bs b/testsuite/bsc.verilog/splitports/DeepSplit.bs index 9cab5afea..0a133a22d 100644 --- a/testsuite/bsc.verilog/splitports/DeepSplit.bs +++ b/testsuite/bsc.verilog/splitports/DeepSplit.bs @@ -47,11 +47,19 @@ interface SplitTest = putBaz :: DeepSplit Baz -> Action putZug :: DeepSplit Zug -> Action + getFoo :: DeepSplit Foo + getBar :: DeepSplit Foo -> DeepSplit Bar {-# result = "GET_BAR" #-} + getZug :: DeepSplit Zug + + update :: DeepSplit Foo -> ActionValue (DeepSplit Bar) + {-# synthesize mkDeepSplitTest #-} mkDeepSplitTest :: Module SplitTest mkDeepSplitTest = module + theCond <- mkReg False + theFoo <- mkReg (Foo { x = 0; y = 0; }) interface putFoo (DeepSplit x) = $display "putFoo: " (cshow x) putBar (DeepSplit x) = $display "putBar: " (cshow x) @@ -59,6 +67,13 @@ mkDeepSplitTest = putFoos (DeepSplit x) = $display "putFoos: " (cshow x) putBaz (DeepSplit x) = $display "putBaz: " (cshow x) putZug (DeepSplit x) = $display "putZug: " (cshow x) + getFoo = DeepSplit $ Foo { x = 42; y = 43; } + getBar (DeepSplit f) = DeepSplit $ Bar { v = vec True False True; w = (False, 0x4321); z = f; } + getZug = DeepSplit $ Zug { qs = vec (Quix { q = negate 2; v = True }) (Quix { q = 2; v = False }); blob = True; } + update (DeepSplit f) = do + theCond := not theCond + theFoo := f + return $ DeepSplit $ Bar { v = vec (f.x == 33) theCond (not theCond); w = (theCond, 0xDEAD); z = theFoo; } {-# synthesize sysDeepSplit #-} sysDeepSplit :: Module Empty @@ -74,4 +89,13 @@ sysDeepSplit = when i == 3 ==> s.putFoos $ DeepSplit $ genWith $ \ j -> Foo { x = fromInteger $ 9 + j / 2; y = fromInteger $ 10 - 2*j / 3; } when i == 4 ==> s.putBaz $ DeepSplit $ Baz { a = Just $ Foo { x = 9; y = 10; }; b = Bar { v = vec True False False; w = (True, 0x1234); z = Foo { x = 3; y = 4; }; }; c = vec (vec (Foo { x = 11; y = 12; }) (Foo { x = 13; y = 14; }) (Foo { x = 15; y = 16; }) (Foo { x = 17; y = 18; }) (Foo { x = 19; y = 20; }) (Foo { x = 21; y = 22; }) (Foo { x = 23; y = 24; }) (Foo { x = 25; y = 26; }), Bar { v = vec True False True; w = (True, 0xBEEF); z = Foo { x = 3; y = 4; } }) (vec (Foo { x = 27; y = 28; }) (Foo { x = 29; y = 30; }) (Foo { x = 31; y = 32; }) (Foo { x = 33; y = 34; }) (Foo { x = 35; y = 36; }) (Foo { x = 37; y = 38; }) (Foo { x = 39; y = 40; }) (Foo { x = 41; y = 42; }), Bar { v = vec True False True; w = (True, 0x4321); z = Foo { x = 123; y = 42; } }) (vec (Foo { x = 43; y = 44; }) (Foo { x = 45; y = 46; }) (Foo { x = 47; y = 48; }) (Foo { x = 49; y = 50; }) (Foo { x = 51; y = 52; }) (Foo { x = 53; y = 54; }) (Foo { x = 55; y = 56; }) (Foo { x = 57; y = 58; }), Bar { v = vec True True True; w = (True, 0xAABB); z = Foo { x = 3; y = 4; } }); d = (); e = nil; } when i == 5 ==> s.putZug $ DeepSplit $ Zug { qs = vec (Quix { q = 1; v = True }) (Quix { q = 2; v = False }); blob = False; } - when i == 6 ==> $finish + when i == 6 ==> $display "getFoo: " (cshow s.getFoo) + when i == 7 ==> $display "getBar: " (cshow $ s.getBar s.getFoo) + when i == 8 ==> $display "getZug: " (cshow s.getZug) + when i == 9 ==> do + res <- s.update (DeepSplit $ Foo { x = 77; y = 88; }) + $display "update: " (cshow res) + when i == 10 ==> do + res <- s.update (DeepSplit $ Foo { x = 33; y = 44; }) + $display "update: " (cshow res) + when i == 11 ==> $finish diff --git a/testsuite/bsc.verilog/splitports/InstanceSplit.bs b/testsuite/bsc.verilog/splitports/InstanceSplit.bs index 83c2ce7da..2b2a537f8 100644 --- a/testsuite/bsc.verilog/splitports/InstanceSplit.bs +++ b/testsuite/bsc.verilog/splitports/InstanceSplit.bs @@ -22,7 +22,7 @@ struct Bar = deriving (Bits) -- XXX would be nice to be able to derive this -instance (ShallowSplitPorts Bar p) => SplitPorts Bar p where +instance SplitPorts Bar (ShallowPortsOf Bar) where splitPorts = shallowSplitPorts unsplitPorts = shallowUnsplitPorts portNames = shallowSplitPortNames @@ -36,7 +36,7 @@ struct Baz = -- No Bits instance needed -- XXX would be nice to be able to derive this -instance (ShallowSplitPorts Baz p) => SplitPorts Baz p where +instance SplitPorts Baz (ShallowPortsOf Baz) where splitPorts = shallowSplitPorts unsplitPorts = shallowUnsplitPorts portNames = shallowSplitPortNames @@ -48,17 +48,30 @@ interface SplitTest = putFoos :: (Vector 50 Foo) -> Action putBaz :: Baz -> Action + getFoo :: Foo + getBar :: Foo -> Bar {-# result = "GET_BAR" #-} + + update :: Foo -> ActionValue Bar + {-# synthesize mkInstanceSplitTest #-} mkInstanceSplitTest :: Module SplitTest mkInstanceSplitTest = module + theCond <- mkReg False + theFoo <- mkReg (Foo { x = 0; y = 0; }) interface putFoo x = $display "putFoo: " (cshow x) putBar x = $display "putBar: " (cshow x) putFooBar x y = $display "putFooBar: " (cshow x) " " (cshow y) putFoos x = $display "putFoos: " (cshow x) putBaz x = $display "putBaz: " (cshow x) + getFoo = Foo { x = 42; y = 43; } + getBar f = Bar { v = vec True False True; w = (False, 0x4321); z = f; } + update f = do + theCond := not theCond + theFoo := f + return $ Bar { v = vec (f.x == 33) theCond (not theCond); w = (theCond, 0xDEAD); z = theFoo; } {-# synthesize sysInstanceSplit #-} sysInstanceSplit :: Module Empty @@ -73,4 +86,12 @@ sysInstanceSplit = when i == 2 ==> s.putFooBar (Foo { x = 5; y = 6; }) (Bar { v = vec False True False; w = (False, 0x5678); z = Foo { x = 7; y = 8; } }) when i == 3 ==> s.putFoos $ genWith $ \ j -> Foo { x = fromInteger $ 9 + j / 2; y = fromInteger $ 10 - 2*j / 3; } when i == 4 ==> s.putBaz $ Baz { a = Just $ Foo { x = 9; y = 10; }; b = Bar { v = vec True False False; w = (True, 0x1234); z = Foo { x = 3; y = 4; }; }; c = vec (vec (Foo { x = 11; y = 12; }) (Foo { x = 13; y = 14; }) (Foo { x = 15; y = 16; }) (Foo { x = 17; y = 18; }) (Foo { x = 19; y = 20; }) (Foo { x = 21; y = 22; }) (Foo { x = 23; y = 24; }) (Foo { x = 25; y = 26; }), Bar { v = vec True False True; w = (True, 0xBEEF); z = Foo { x = 3; y = 4; } }) (vec (Foo { x = 27; y = 28; }) (Foo { x = 29; y = 30; }) (Foo { x = 31; y = 32; }) (Foo { x = 33; y = 34; }) (Foo { x = 35; y = 36; }) (Foo { x = 37; y = 38; }) (Foo { x = 39; y = 40; }) (Foo { x = 41; y = 42; }), Bar { v = vec True False True; w = (True, 0x4321); z = Foo { x = 123; y = 42; } }) (vec (Foo { x = 43; y = 44; }) (Foo { x = 45; y = 46; }) (Foo { x = 47; y = 48; }) (Foo { x = 49; y = 50; }) (Foo { x = 51; y = 52; }) (Foo { x = 53; y = 54; }) (Foo { x = 55; y = 56; }) (Foo { x = 57; y = 58; }), Bar { v = vec True True True; w = (True, 0xAABB); z = Foo { x = 3; y = 4; } }); d = (); e = nil; } - when i == 5 ==> $finish + when i == 5 ==> $display "getFoo: " (cshow s.getFoo) + when i == 6 ==> $display "getBar: " (cshow $ s.getBar (s.getFoo)) + when i == 7 ==> do + res <- s.update (Foo { x = 77; y = 88; }) + $display "update: " (cshow res) + when i == 8 ==> do + res <- s.update (Foo { x = 33; y = 44; }) + $display "update: " (cshow res) + when i == 9 ==> $finish diff --git a/testsuite/bsc.verilog/splitports/PortNameConflict.bs b/testsuite/bsc.verilog/splitports/PortNameConflict.bs index 145bb557c..ba3a70ee7 100644 --- a/testsuite/bsc.verilog/splitports/PortNameConflict.bs +++ b/testsuite/bsc.verilog/splitports/PortNameConflict.bs @@ -8,7 +8,7 @@ struct Foo = y :: Int 8 deriving (Bits) -instance (ShallowSplitPorts Foo p) => SplitPorts Foo p where +instance SplitPorts Foo (ShallowPortsOf Foo) where splitPorts = shallowSplitPorts unsplitPorts = shallowUnsplitPorts portNames = shallowSplitPortNames @@ -18,7 +18,7 @@ struct Bar = f_x :: Int 16 deriving (Bits) -instance (ShallowSplitPorts Bar p) => SplitPorts Bar p where +instance SplitPorts Bar (ShallowPortsOf Bar) where splitPorts = shallowSplitPorts unsplitPorts = shallowUnsplitPorts portNames = shallowSplitPortNames diff --git a/testsuite/bsc.verilog/splitports/ShallowSplit.bs b/testsuite/bsc.verilog/splitports/ShallowSplit.bs index 1c96ac47b..9c7f9e294 100644 --- a/testsuite/bsc.verilog/splitports/ShallowSplit.bs +++ b/testsuite/bsc.verilog/splitports/ShallowSplit.bs @@ -31,17 +31,30 @@ interface SplitTest = putFoos :: ShallowSplit (Vector 50 Foo) -> Action putBaz :: ShallowSplit Baz -> Action + getFoo :: ShallowSplit Foo + getBar :: ShallowSplit Foo -> ShallowSplit Bar {-# result = "GET_BAR" #-} + + update :: ShallowSplit Foo -> ActionValue (ShallowSplit Bar) + {-# synthesize mkShallowSplitTest #-} mkShallowSplitTest :: Module SplitTest mkShallowSplitTest = module + theCond <- mkReg False + theFoo <- mkReg (Foo { x = 0; y = 0; }) interface putFoo (ShallowSplit x) = $display "putFoo: " (cshow x) putBar (ShallowSplit x) = $display "putBar: " (cshow x) putFooBar (ShallowSplit x) (ShallowSplit y) = $display "putFooBar: " (cshow x) " " (cshow y) putFoos (ShallowSplit x) = $display "putFoos: " (cshow x) putBaz (ShallowSplit x) = $display "putBaz: " (cshow x) + getFoo = ShallowSplit $ Foo { x = 42; y = 43; } + getBar (ShallowSplit f) = ShallowSplit $ Bar { v = vec True False True; w = (False, 0x4321); z = f; } + update (ShallowSplit f) = do + theCond := not theCond + theFoo := f + return $ ShallowSplit $ Bar { v = vec (f.x == 33) theCond (not theCond); w = (theCond, 0xDEAD); z = theFoo; } {-# synthesize sysShallowSplit #-} sysShallowSplit :: Module Empty @@ -56,4 +69,12 @@ sysShallowSplit = when i == 2 ==> s.putFooBar (ShallowSplit $ Foo { x = 5; y = 6; }) (ShallowSplit $ Bar { v = vec False True False; w = (False, 0x5678); z = Foo { x = 7; y = 8; } }) when i == 3 ==> s.putFoos $ ShallowSplit $ genWith $ \ j -> Foo { x = fromInteger $ 9 + j / 2; y = fromInteger $ 10 - 2*j / 3; } when i == 4 ==> s.putBaz $ ShallowSplit $ Baz { a = Just $ Foo { x = 9; y = 10; }; b = Bar { v = vec True False False; w = (True, 0x1234); z = Foo { x = 3; y = 4; }; }; c = vec (vec (Foo { x = 11; y = 12; }) (Foo { x = 13; y = 14; }) (Foo { x = 15; y = 16; }) (Foo { x = 17; y = 18; }) (Foo { x = 19; y = 20; }) (Foo { x = 21; y = 22; }) (Foo { x = 23; y = 24; }) (Foo { x = 25; y = 26; }), Bar { v = vec True False True; w = (True, 0xBEEF); z = Foo { x = 3; y = 4; } }) (vec (Foo { x = 27; y = 28; }) (Foo { x = 29; y = 30; }) (Foo { x = 31; y = 32; }) (Foo { x = 33; y = 34; }) (Foo { x = 35; y = 36; }) (Foo { x = 37; y = 38; }) (Foo { x = 39; y = 40; }) (Foo { x = 41; y = 42; }), Bar { v = vec True False True; w = (True, 0x4321); z = Foo { x = 123; y = 42; } }) (vec (Foo { x = 43; y = 44; }) (Foo { x = 45; y = 46; }) (Foo { x = 47; y = 48; }) (Foo { x = 49; y = 50; }) (Foo { x = 51; y = 52; }) (Foo { x = 53; y = 54; }) (Foo { x = 55; y = 56; }) (Foo { x = 57; y = 58; }), Bar { v = vec True True True; w = (True, 0xAABB); z = Foo { x = 3; y = 4; } }); d = (); e = nil; } - when i == 5 ==> $finish + when i == 5 ==> $display "getFoo: " (cshow s.getFoo) + when i == 6 ==> $display "getBar: " (cshow $ s.getBar s.getFoo) + when i == 7 ==> do + res <- s.update (ShallowSplit $ Foo { x = 77; y = 88; }) + $display "update: " (cshow res) + when i == 8 ==> do + res <- s.update (ShallowSplit $ Foo { x = 33; y = 44; }) + $display "update: " (cshow res) + when i == 9 ==> $finish diff --git a/testsuite/bsc.verilog/splitports/SomeArgNames.bs b/testsuite/bsc.verilog/splitports/SomeArgNames.bs index fd2b871fe..af506a28b 100644 --- a/testsuite/bsc.verilog/splitports/SomeArgNames.bs +++ b/testsuite/bsc.verilog/splitports/SomeArgNames.bs @@ -8,7 +8,7 @@ struct Foo = y :: Int 8 deriving (Bits) -instance (ShallowSplitPorts Foo p) => SplitPorts Foo p where +instance SplitPorts Foo (ShallowPortsOf Foo) where splitPorts = shallowSplitPorts unsplitPorts = shallowUnsplitPorts portNames = shallowSplitPortNames @@ -18,7 +18,7 @@ struct Bar = b :: Bool deriving (Bits) -instance (ShallowSplitPorts Bar p) => SplitPorts Bar p where +instance SplitPorts Bar (ShallowPortsOf Bar) where splitPorts = shallowSplitPorts unsplitPorts = shallowUnsplitPorts portNames = shallowSplitPortNames diff --git a/testsuite/bsc.verilog/splitports/TooManyArgNames.bs b/testsuite/bsc.verilog/splitports/TooManyArgNames.bs index 9a97f196f..19a598f4d 100644 --- a/testsuite/bsc.verilog/splitports/TooManyArgNames.bs +++ b/testsuite/bsc.verilog/splitports/TooManyArgNames.bs @@ -8,7 +8,7 @@ struct Foo = y :: Int 8 deriving (Bits) -instance (ShallowSplitPorts Foo p) => SplitPorts Foo p where +instance SplitPorts Foo (ShallowPortsOf Foo) where splitPorts = shallowSplitPorts unsplitPorts = shallowUnsplitPorts portNames = shallowSplitPortNames @@ -18,7 +18,7 @@ struct Bar = b :: Bool deriving (Bits) -instance (ShallowSplitPorts Bar p) => SplitPorts Bar p where +instance SplitPorts Bar (ShallowPortsOf Bar) where splitPorts = shallowSplitPorts unsplitPorts = shallowUnsplitPorts portNames = shallowSplitPortNames diff --git a/testsuite/bsc.verilog/splitports/splitports.exp b/testsuite/bsc.verilog/splitports/splitports.exp index 0987ba1ba..12c8fa783 100644 --- a/testsuite/bsc.verilog/splitports/splitports.exp +++ b/testsuite/bsc.verilog/splitports/splitports.exp @@ -9,6 +9,17 @@ if { $vtest == 1 } { find_regexp mkShallowSplitTest.v {input \[15 : 0\] putFoos_1_49;} find_regexp mkShallowSplitTest.v {input \[16 : 0\] putBaz_1_a;} find_regexp mkShallowSplitTest.v {input \[491 : 0\] putBaz_1_c;} + find_regexp mkShallowSplitTest.v {output \[7 : 0\] getFoo_x;} + find_regexp mkShallowSplitTest.v {output \[7 : 0\] getFoo_y;} + find_regexp mkShallowSplitTest.v {output \[2 : 0\] GET_BAR_v;} + find_regexp mkShallowSplitTest.v {output \[15 : 0\] GET_BAR_z;} + find_regexp mkShallowSplitTest.v {input \[7 : 0\] update_1_x;} + find_regexp mkShallowSplitTest.v {input EN_update;} + find_regexp mkShallowSplitTest.v {output \[16 : 0\] update_w;} + find_regexp mkShallowSplitTest.v {output RDY_update;} + + find_regexp mkShallowSplitTest.v {\(getBar_1_x, getBar_1_y\) -> GET_BAR_z} + find_regexp mkShallowSplitTest.v {update_1_x -> update_v} } test_c_veri DeepSplit @@ -24,6 +35,23 @@ if { $vtest == 1 } { find_regexp mkDeepSplitTest.v {input \[7 : 0\] putBaz_1_c_2_1_7_y;} find_regexp mkDeepSplitTest.v {input \[15 : 0\] putBaz_1_c_2_2_w_2;} find_regexp mkDeepSplitTest.v {input \[3 : 0\] putZug_1_qs_1;} + find_regexp mkDeepSplitTest.v {output \[7 : 0\] getFoo_x;} + find_regexp mkDeepSplitTest.v {output \[7 : 0\] getFoo_y;} + find_regexp mkDeepSplitTest.v {output GET_BAR_v_0;} + find_regexp mkDeepSplitTest.v {output GET_BAR_v_2;} + find_regexp mkDeepSplitTest.v {output \[15 : 0\] GET_BAR_w_2;} + find_regexp mkDeepSplitTest.v {output \[7 : 0\] GET_BAR_z_y;} + find_regexp mkDeepSplitTest.v {output \[3 : 0\] getZug_qs_0;} + find_regexp mkDeepSplitTest.v {output \[3 : 0\] getZug_qs_1;} + find_regexp mkDeepSplitTest.v {output getZug_blob;} + find_regexp mkDeepSplitTest.v {input \[7 : 0\] update_1_x;} + find_regexp mkDeepSplitTest.v {input EN_update;} + find_regexp mkDeepSplitTest.v {output \[15 : 0\] update_w_2;} + find_regexp mkDeepSplitTest.v {output RDY_update;} + + find_regexp mkDeepSplitTest.v {getBar_1_x -> GET_BAR_z_x} + find_regexp mkDeepSplitTest.v {getBar_1_y -> GET_BAR_z_y} + find_regexp mkDeepSplitTest.v {update_1_x -> update_v_0} } test_c_veri InstanceSplit @@ -37,6 +65,20 @@ if { $vtest == 1 } { find_regexp mkInstanceSplitTest.v {input \[799 : 0\] putFoos_1;} find_regexp mkInstanceSplitTest.v {input \[16 : 0\] putBaz_1_a;} find_regexp mkInstanceSplitTest.v {input \[491 : 0\] putBaz_1_c;} + find_regexp mkInstanceSplitTest.v {output \[7 : 0\] getFoo_x;} + find_regexp mkInstanceSplitTest.v {output getFoo_ysign;} + find_regexp mkInstanceSplitTest.v {output \[6 : 0\] getFoo_yvalue;} + find_regexp mkInstanceSplitTest.v {output \[2 : 0\] GET_BAR_v;} + find_regexp mkInstanceSplitTest.v {output GET_BAR_z_ysign;} + find_regexp mkInstanceSplitTest.v {input \[7 : 0\] update_1_x;} + find_regexp mkInstanceSplitTest.v {input EN_update;} + find_regexp mkInstanceSplitTest.v {output \[6 : 0\] update_z_yvalue;} + find_regexp mkInstanceSplitTest.v {output RDY_update;} + + find_regexp mkInstanceSplitTest.v {getBar_1_x -> GET_BAR_z_x} + find_regexp mkInstanceSplitTest.v {\(getBar_1_ysign, getBar_1_yvalue\) -> GET_BAR_z_ysign} + find_regexp mkInstanceSplitTest.v {\(getBar_1_ysign, getBar_1_yvalue\) -> GET_BAR_z_yvalue} + find_regexp mkInstanceSplitTest.v {update_1_x -> update_v} } # Supplying an arg_names pragma that is shorter than the number of arguments diff --git a/testsuite/bsc.verilog/splitports/sysDeepSplit.out.expected b/testsuite/bsc.verilog/splitports/sysDeepSplit.out.expected index fa26cd6e1..af9d18ba2 100644 --- a/testsuite/bsc.verilog/splitports/sysDeepSplit.out.expected +++ b/testsuite/bsc.verilog/splitports/sysDeepSplit.out.expected @@ -4,3 +4,8 @@ putFooBar: Foo {x= 5; y= 6} Bar {v=[False, True, False]; w=(False, 22136); z putFoos: [Foo {x= 9; y= 10}, Foo {x= 9; y= 10}, Foo {x= 10; y= 9}, Foo {x= 10; y= 8}, Foo {x= 11; y= 8}, Foo {x= 11; y= 7}, Foo {x= 12; y= 6}, Foo {x= 12; y= 6}, Foo {x= 13; y= 5}, Foo {x= 13; y= 4}, Foo {x= 14; y= 4}, Foo {x= 14; y= 3}, Foo {x= 15; y= 2}, Foo {x= 15; y= 2}, Foo {x= 16; y= 1}, Foo {x= 16; y= 0}, Foo {x= 17; y= 0}, Foo {x= 17; y= -1}, Foo {x= 18; y= -2}, Foo {x= 18; y= -2}, Foo {x= 19; y= -3}, Foo {x= 19; y= -4}, Foo {x= 20; y= -4}, Foo {x= 20; y= -5}, Foo {x= 21; y= -6}, Foo {x= 21; y= -6}, Foo {x= 22; y= -7}, Foo {x= 22; y= -8}, Foo {x= 23; y= -8}, Foo {x= 23; y= -9}, Foo {x= 24; y= -10}, Foo {x= 24; y= -10}, Foo {x= 25; y= -11}, Foo {x= 25; y= -12}, Foo {x= 26; y= -12}, Foo {x= 26; y= -13}, Foo {x= 27; y= -14}, Foo {x= 27; y= -14}, Foo {x= 28; y= -15}, Foo {x= 28; y= -16}, Foo {x= 29; y= -16}, Foo {x= 29; y= -17}, Foo {x= 30; y= -18}, Foo {x= 30; y= -18}, Foo {x= 31; y= -19}, Foo {x= 31; y= -20}, Foo {x= 32; y= -20}, Foo {x= 32; y= -21}, Foo {x= 33; y= -22}, Foo {x= 33; y= -22}] putBaz: Baz {a=Valid (Foo {x= 9; y= 10}); b=Bar {v=[True, False, False]; w=(True, 4660); z=Foo {x= 3; y= 4}}; c=[([Foo {x= 11; y= 12}, Foo {x= 13; y= 14}, Foo {x= 15; y= 16}, Foo {x= 17; y= 18}, Foo {x= 19; y= 20}, Foo {x= 21; y= 22}, Foo {x= 23; y= 24}, Foo {x= 25; y= 26}], Bar {v=[True, False, True]; w=(True, 48879); z=Foo {x= 3; y= 4}}), ([Foo {x= 27; y= 28}, Foo {x= 29; y= 30}, Foo {x= 31; y= 32}, Foo {x= 33; y= 34}, Foo {x= 35; y= 36}, Foo {x= 37; y= 38}, Foo {x= 39; y= 40}, Foo {x= 41; y= 42}], Bar {v=[True, False, True]; w=(True, 17185); z=Foo {x= 123; y= 42}}), ([Foo {x= 43; y= 44}, Foo {x= 45; y= 46}, Foo {x= 47; y= 48}, Foo {x= 49; y= 50}, Foo {x= 51; y= 52}, Foo {x= 53; y= 54}, Foo {x= 55; y= 56}, Foo {x= 57; y= 58}], Bar {v=[True, True, True]; w=(True, 43707); z=Foo {x= 3; y= 4}})]; d=(); e=[]} putZug: Zug {qs=[Quix {q= 1; v=True}, Quix {q= 2; v=False}]; blob=False} +getFoo: DeepSplit (Foo {x= 42; y= 43}) +getBar: DeepSplit (Bar {v=[True, False, True]; w=(False, 17185); z=Foo {x= 42; y= 43}}) +getZug: DeepSplit (Zug {qs=[Quix {q=-2; v=True}, Quix {q= 2; v=False}]; blob=True}) +update: DeepSplit (Bar {v=[False, False, True]; w=(False, 57005); z=Foo {x= 0; y= 0}}) +update: DeepSplit (Bar {v=[True, True, False]; w=(True, 57005); z=Foo {x= 77; y= 88}}) diff --git a/testsuite/bsc.verilog/splitports/sysInstanceSplit.out.expected b/testsuite/bsc.verilog/splitports/sysInstanceSplit.out.expected index bb4f2dc03..00bf5618c 100644 --- a/testsuite/bsc.verilog/splitports/sysInstanceSplit.out.expected +++ b/testsuite/bsc.verilog/splitports/sysInstanceSplit.out.expected @@ -3,3 +3,7 @@ putBar: Bar {v=[True, False, True]; w=(True, 4660); z=Foo {x= 3; y= 4}} putFooBar: Foo {x= 5; y= 6} Bar {v=[False, True, False]; w=(False, 22136); z=Foo {x= 7; y= 8}} putFoos: [Foo {x= 9; y= 10}, Foo {x= 9; y= 10}, Foo {x= 10; y= 9}, Foo {x= 10; y= 8}, Foo {x= 11; y= 8}, Foo {x= 11; y= 7}, Foo {x= 12; y= 6}, Foo {x= 12; y= 6}, Foo {x= 13; y= 5}, Foo {x= 13; y= 4}, Foo {x= 14; y= 4}, Foo {x= 14; y= 3}, Foo {x= 15; y= 2}, Foo {x= 15; y= 2}, Foo {x= 16; y= 1}, Foo {x= 16; y= 0}, Foo {x= 17; y= 0}, Foo {x= 17; y= -1}, Foo {x= 18; y= -2}, Foo {x= 18; y= -2}, Foo {x= 19; y= -3}, Foo {x= 19; y= -4}, Foo {x= 20; y= -4}, Foo {x= 20; y= -5}, Foo {x= 21; y= -6}, Foo {x= 21; y= -6}, Foo {x= 22; y= -7}, Foo {x= 22; y= -8}, Foo {x= 23; y= -8}, Foo {x= 23; y= -9}, Foo {x= 24; y= -10}, Foo {x= 24; y= -10}, Foo {x= 25; y= -11}, Foo {x= 25; y= -12}, Foo {x= 26; y= -12}, Foo {x= 26; y= -13}, Foo {x= 27; y= -14}, Foo {x= 27; y= -14}, Foo {x= 28; y= -15}, Foo {x= 28; y= -16}, Foo {x= 29; y= -16}, Foo {x= 29; y= -17}, Foo {x= 30; y= -18}, Foo {x= 30; y= -18}, Foo {x= 31; y= -19}, Foo {x= 31; y= -20}, Foo {x= 32; y= -20}, Foo {x= 32; y= -21}, Foo {x= 33; y= -22}, Foo {x= 33; y= -22}] putBaz: Baz {a=Valid (Foo {x= 9; y= 10}); b=Bar {v=[True, False, False]; w=(True, 4660); z=Foo {x= 3; y= 4}}; c=[([Foo {x= 11; y= 12}, Foo {x= 13; y= 14}, Foo {x= 15; y= 16}, Foo {x= 17; y= 18}, Foo {x= 19; y= 20}, Foo {x= 21; y= 22}, Foo {x= 23; y= 24}, Foo {x= 25; y= 26}], Bar {v=[True, False, True]; w=(True, 48879); z=Foo {x= 3; y= 4}}), ([Foo {x= 27; y= 28}, Foo {x= 29; y= 30}, Foo {x= 31; y= 32}, Foo {x= 33; y= 34}, Foo {x= 35; y= 36}, Foo {x= 37; y= 38}, Foo {x= 39; y= 40}, Foo {x= 41; y= 42}], Bar {v=[True, False, True]; w=(True, 17185); z=Foo {x= 123; y= 42}}), ([Foo {x= 43; y= 44}, Foo {x= 45; y= 46}, Foo {x= 47; y= 48}, Foo {x= 49; y= 50}, Foo {x= 51; y= 52}, Foo {x= 53; y= 54}, Foo {x= 55; y= 56}, Foo {x= 57; y= 58}], Bar {v=[True, True, True]; w=(True, 43707); z=Foo {x= 3; y= 4}})]; d=(); e=[]} +getFoo: Foo {x= 42; y= 43} +getBar: Bar {v=[True, False, True]; w=(False, 17185); z=Foo {x= 42; y= 43}} +update: Bar {v=[False, False, True]; w=(False, 57005); z=Foo {x= 0; y= 0}} +update: Bar {v=[True, True, False]; w=(True, 57005); z=Foo {x= 77; y= 88}} diff --git a/testsuite/bsc.verilog/splitports/sysShallowSplit.out.expected b/testsuite/bsc.verilog/splitports/sysShallowSplit.out.expected index bb4f2dc03..40e21a373 100644 --- a/testsuite/bsc.verilog/splitports/sysShallowSplit.out.expected +++ b/testsuite/bsc.verilog/splitports/sysShallowSplit.out.expected @@ -3,3 +3,7 @@ putBar: Bar {v=[True, False, True]; w=(True, 4660); z=Foo {x= 3; y= 4}} putFooBar: Foo {x= 5; y= 6} Bar {v=[False, True, False]; w=(False, 22136); z=Foo {x= 7; y= 8}} putFoos: [Foo {x= 9; y= 10}, Foo {x= 9; y= 10}, Foo {x= 10; y= 9}, Foo {x= 10; y= 8}, Foo {x= 11; y= 8}, Foo {x= 11; y= 7}, Foo {x= 12; y= 6}, Foo {x= 12; y= 6}, Foo {x= 13; y= 5}, Foo {x= 13; y= 4}, Foo {x= 14; y= 4}, Foo {x= 14; y= 3}, Foo {x= 15; y= 2}, Foo {x= 15; y= 2}, Foo {x= 16; y= 1}, Foo {x= 16; y= 0}, Foo {x= 17; y= 0}, Foo {x= 17; y= -1}, Foo {x= 18; y= -2}, Foo {x= 18; y= -2}, Foo {x= 19; y= -3}, Foo {x= 19; y= -4}, Foo {x= 20; y= -4}, Foo {x= 20; y= -5}, Foo {x= 21; y= -6}, Foo {x= 21; y= -6}, Foo {x= 22; y= -7}, Foo {x= 22; y= -8}, Foo {x= 23; y= -8}, Foo {x= 23; y= -9}, Foo {x= 24; y= -10}, Foo {x= 24; y= -10}, Foo {x= 25; y= -11}, Foo {x= 25; y= -12}, Foo {x= 26; y= -12}, Foo {x= 26; y= -13}, Foo {x= 27; y= -14}, Foo {x= 27; y= -14}, Foo {x= 28; y= -15}, Foo {x= 28; y= -16}, Foo {x= 29; y= -16}, Foo {x= 29; y= -17}, Foo {x= 30; y= -18}, Foo {x= 30; y= -18}, Foo {x= 31; y= -19}, Foo {x= 31; y= -20}, Foo {x= 32; y= -20}, Foo {x= 32; y= -21}, Foo {x= 33; y= -22}, Foo {x= 33; y= -22}] putBaz: Baz {a=Valid (Foo {x= 9; y= 10}); b=Bar {v=[True, False, False]; w=(True, 4660); z=Foo {x= 3; y= 4}}; c=[([Foo {x= 11; y= 12}, Foo {x= 13; y= 14}, Foo {x= 15; y= 16}, Foo {x= 17; y= 18}, Foo {x= 19; y= 20}, Foo {x= 21; y= 22}, Foo {x= 23; y= 24}, Foo {x= 25; y= 26}], Bar {v=[True, False, True]; w=(True, 48879); z=Foo {x= 3; y= 4}}), ([Foo {x= 27; y= 28}, Foo {x= 29; y= 30}, Foo {x= 31; y= 32}, Foo {x= 33; y= 34}, Foo {x= 35; y= 36}, Foo {x= 37; y= 38}, Foo {x= 39; y= 40}, Foo {x= 41; y= 42}], Bar {v=[True, False, True]; w=(True, 17185); z=Foo {x= 123; y= 42}}), ([Foo {x= 43; y= 44}, Foo {x= 45; y= 46}, Foo {x= 47; y= 48}, Foo {x= 49; y= 50}, Foo {x= 51; y= 52}, Foo {x= 53; y= 54}, Foo {x= 55; y= 56}, Foo {x= 57; y= 58}], Bar {v=[True, True, True]; w=(True, 43707); z=Foo {x= 3; y= 4}})]; d=(); e=[]} +getFoo: ShallowSplit (Foo {x= 42; y= 43}) +getBar: ShallowSplit (Bar {v=[True, False, True]; w=(False, 17185); z=Foo {x= 42; y= 43}}) +update: ShallowSplit (Bar {v=[False, False, True]; w=(False, 57005); z=Foo {x= 0; y= 0}}) +update: ShallowSplit (Bar {v=[True, True, False]; w=(True, 57005); z=Foo {x= 77; y= 88}})