Merge git://github.com/darchon/clash into cλash
authorMatthijs Kooijman <m.kooijman@student.utwente.nl>
Thu, 2 Jul 2009 14:47:18 +0000 (16:47 +0200)
committerMatthijs Kooijman <m.kooijman@student.utwente.nl>
Thu, 2 Jul 2009 14:47:18 +0000 (16:47 +0200)
* git://github.com/darchon/clash:
  We now output VHDL types in the correct order
  Removed the need for a special vector-type map.
  Added builtin functions: concat, reverse, iterate, iteraten, generate and generaten

Adders.hs
Constants.hs
Generate.hs
HighOrdAlu.hs
VHDL.hs
VHDLTools.hs
VHDLTypes.hs
cλash.cabal

index 85e86c0f4a985f20da6d69207c4a9fa43e5825d4..6ada7df0f58d522c73522df6a3014c8944eb047c 100644 (file)
--- a/Adders.hs
+++ b/Adders.hs
@@ -174,8 +174,8 @@ highordtest = \x ->
 
 xand a b = hwand a b
 
-functiontest :: TFVec D4 Bit -> (TFVec D4 Bit, TFVec D4 Bit)
-functiontest = \v -> let r = (rotl v, rotr v) in r
+functiontest :: TFVec D4 (TFVec D3 Bit) -> (TFVec D12 Bit, TFVec D3 Bit)
+functiontest = \v -> let r = (concat v, head v) in r
 
 xhwnot x = hwnot x
 
index cfb9d555faec4f4e2b58b197e2aef1dc0c5f2f55..af8c324b300e2f52aae2ca36f8a42960e6fde837 100644 (file)
@@ -149,10 +149,30 @@ rotlId = "rotl"
 rotrId :: String
 rotrId = "rotr"
 
+-- | concatenate the vectors in a vector
+concatId :: String
+concatId = "concat"
+
 -- | reverse function identifier
 reverseId :: String
 reverseId = "reverse"
 
+-- | iterate function identifier
+iterateId :: String
+iterateId = "iterate"
+
+-- | iteraten function identifier
+iteratenId :: String
+iteratenId = "iteraten"
+
+-- | iterate function identifier
+generateId :: String
+generateId = "generate"
+
+-- | iteraten function identifier
+generatenId :: String
+generatenId = "generaten"
+
 -- | copy function identifier
 copyId :: String
 copyId = "copy"
index 7cd82f726cecb35a809c8e4521c6fba653137526..55f015608de743e03540a18e52633d66dfbead5f 100644 (file)
@@ -292,7 +292,119 @@ genCopy' (Left res) f args@[arg] =
   in 
     return [out_assign]
     
-    
+genConcat :: BuiltinBuilder
+genConcat = genVarArgs genConcat'
+genConcat' :: (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [Var.Var] -> VHDLSession [AST.ConcSm]
+genConcat' (Left res) f args@[arg] =
+  let
+    -- Setup the generate scheme
+    len1        = (tfvec_len . Var.varType) arg
+    (_, nvec)   = splitAppTy (Var.varType arg)
+    len2        = tfvec_len nvec
+    -- TODO: Use something better than varToString
+    label       = mkVHDLExtId ("concatVector" ++ (varToString res))
+    n_id        = mkVHDLBasicId "n"
+    n_expr      = idToVHDLExpr n_id
+    fromRange   = n_expr AST.:*: (AST.PrimLit $ show len2)
+    genScheme   = AST.ForGn n_id range
+    -- Create the content of the generate statement: Applying the mapped_f to
+    -- each of the elements in arg, storing to each element in res
+    toRange     = (n_expr AST.:*: (AST.PrimLit $ show len2)) AST.:+: (AST.PrimLit $ show (len2-1))
+    range       = AST.ToRange (AST.PrimLit "0") (AST.PrimLit $ show (len1-1))
+    resname     = vecSlice fromRange toRange
+    argexpr     = vhdlNameToVHDLExpr $ mkIndexedName (varToVHDLName arg) n_expr
+    out_assign  = mkUncondAssign (Right resname) argexpr
+  in
+    -- Return the generate statement
+    return [AST.CSGSm $ AST.GenerateSm label genScheme [] [out_assign]]
+  where
+    vecSlice init last =  AST.NSlice (AST.SliceName (varToVHDLName res) 
+                            (AST.ToRange init last))
+
+genIteraten :: BuiltinBuilder
+genIteraten dst f args = genIterate dst f (tail args)
+
+genIterate :: BuiltinBuilder
+genIterate = genIterateOrGenerate True
+
+genGeneraten :: BuiltinBuilder
+genGeneraten dst f args = genGenerate dst f (tail args)
+
+genGenerate :: BuiltinBuilder
+genGenerate = genIterateOrGenerate False
+
+genIterateOrGenerate :: Bool -> BuiltinBuilder
+genIterateOrGenerate iter = genVarArgs (genIterateOrGenerate' iter)
+genIterateOrGenerate' :: Bool -> (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [Var.Var] -> VHDLSession [AST.ConcSm]
+-- Special case for an empty input vector, just assign start to res
+genIterateOrGenerate' iter (Left res) _ [app_f, start] | len == 0 = return [mkUncondAssign (Left res) (AST.PrimLit "\"\"")]
+    where len = (tfvec_len . Var.varType) res
+genIterateOrGenerate' iter (Left res) f [app_f, start] = do
+  -- -- evec is (TFVec n), so it still needs an element type
+  -- let (nvec, _) = splitAppTy (Var.varType vec)
+  -- -- Put the type of the start value in nvec, this will be the type of our
+  -- -- temporary vector
+  let tmp_ty = Var.varType res
+  let error_msg = "\nGenerate.genFold': Can not construct temp vector for element type: " ++ pprString tmp_ty 
+  tmp_vhdl_ty <- vhdl_ty error_msg tmp_ty
+  -- Setup the generate scheme
+  let gen_label = mkVHDLExtId ("iterateVector" ++ (varToString start))
+  let block_label = mkVHDLExtId ("iterateVector" ++ (varToString res))
+  let gen_range = AST.ToRange (AST.PrimLit "0") len_min_expr
+  let gen_scheme   = AST.ForGn n_id gen_range
+  -- Make the intermediate vector
+  let  tmp_dec     = AST.BDISD $ AST.SigDec tmp_id tmp_vhdl_ty Nothing
+  -- Create the generate statement
+  cells <- sequence [genFirstCell, genOtherCell]
+  let gen_sm = AST.GenerateSm gen_label gen_scheme [] (map AST.CSGSm cells)
+  -- Assign tmp[len-1] or tmp[0] to res
+  let out_assign = mkUncondAssign (Left res) $ vhdlNameToVHDLExpr tmp_name    
+  let block = AST.BlockSm block_label [] (AST.PMapAspect []) [tmp_dec] [AST.CSGSm gen_sm, out_assign]
+  return [AST.CSBSm block]
+  where
+    -- The vector length
+    len = (tfvec_len . Var.varType) res
+    -- An id for the counter
+    n_id = mkVHDLBasicId "n"
+    n_cur = idToVHDLExpr n_id
+    -- An expression for previous n
+    n_prev = n_cur AST.:-: (AST.PrimLit "1")
+    -- An expression for len-1
+    len_min_expr = (AST.PrimLit $ show (len-1))
+    -- An id for the tmp result vector
+    tmp_id = mkVHDLBasicId "tmp"
+    tmp_name = AST.NSimple tmp_id
+    -- Generate parts of the fold
+    genFirstCell, genOtherCell :: VHDLSession AST.GenerateSm
+    genFirstCell = do
+      let cond_label = mkVHDLExtId "firstcell"
+      -- if n == 0 or n == len-1
+      let cond_scheme = AST.IfGn $ n_cur AST.:=: (AST.PrimLit "0")
+      -- Output to tmp[current n]
+      let resname = mkIndexedName tmp_name n_cur
+      -- Input from start
+      let argexpr = varToVHDLExpr start
+      let startassign = mkUncondAssign (Right resname) argexpr
+      app_concsms <- genApplication (Right resname) app_f  [Right argexpr]
+      -- Return the conditional generate part
+      return $ AST.GenerateSm cond_label cond_scheme [] (if iter then 
+                                                          [startassign]
+                                                         else 
+                                                          app_concsms
+                                                        )
+
+    genOtherCell = do
+      let cond_label = mkVHDLExtId "othercell"
+      -- if n > 0 or n < len-1
+      let cond_scheme = AST.IfGn $ n_cur AST.:/=: (AST.PrimLit "0")
+      -- Output to tmp[current n]
+      let resname = mkIndexedName tmp_name n_cur
+      -- Input from tmp[previous n]
+      let argexpr = vhdlNameToVHDLExpr $ mkIndexedName tmp_name n_prev
+      app_concsms <- genApplication (Right resname) app_f [Right argexpr]
+      -- Return the conditional generate part
+      return $ AST.GenerateSm cond_label cond_scheme [] app_concsms
+
 
 -----------------------------------------------------------------------------
 -- Function to generate VHDL for applications
@@ -400,6 +512,7 @@ genUnconsVectorFuns elemTM vectorTM  =
   , (nullId, (AST.SubProgBody nullSpec [] [nullExpr], []))
   , (rotlId, (AST.SubProgBody rotlSpec [AST.SPVD rotlVar] [rotlExpr, rotlRet], [nullId, lastId, initId]))
   , (rotrId, (AST.SubProgBody rotrSpec [AST.SPVD rotrVar] [rotrExpr, rotrRet], [nullId, tailId, headId]))
+  , (reverseId, (AST.SubProgBody reverseSpec [AST.SPVD reverseVar] [reverseFor, reverseRet], []))
   ]
   where 
     ixPar   = AST.unsafeVHDLBasicId "ix"
@@ -727,6 +840,32 @@ genUnconsVectorFuns elemTM vectorTM  =
                       (AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLExtId headId))  
                         [Nothing AST.:=>: AST.ADExpr (AST.PrimName $ AST.NSimple vecPar)]))
     rotrRet =  AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
+    reverseSpec = AST.Function (mkVHDLExtId reverseId) [AST.IfaceVarDec vecPar vectorTM] vectorTM
+    reverseVar = 
+      AST.VarDec resId 
+             (AST.SubtypeIn vectorTM
+               (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
+                [AST.ToRange (AST.PrimLit "0")
+                         (AST.PrimName (AST.NAttribute $ 
+                           AST.AttribName (AST.NSimple vecPar) (mkVHDLBasicId lengthId) Nothing) AST.:-:
+                            (AST.PrimLit "1")) ]))
+             Nothing
+    -- for i in 0 to res'range loop
+    --   res(vec'length-i-1) := vec(i);
+    -- end loop;
+    reverseFor = 
+       AST.ForSM iId (AST.AttribRange $ AST.AttribName (AST.NSimple resId) rangeId Nothing) [reverseAssign]
+    -- res(vec'length-i-1) := vec(i);
+    reverseAssign = AST.NIndexed (AST.IndexedName (AST.NSimple resId) [destExp]) AST.:=
+      (AST.PrimName $ AST.NIndexed (AST.IndexedName (AST.NSimple vecPar) 
+                           [AST.PrimName $ AST.NSimple iId]))
+        where destExp = AST.PrimName (AST.NAttribute $ AST.AttribName (AST.NSimple vecPar) 
+                                   (mkVHDLBasicId lengthId) Nothing) AST.:-: 
+                        AST.PrimName (AST.NSimple iId) AST.:-: 
+                        (AST.PrimLit "1") 
+    -- return res;
+    reverseRet = AST.ReturnSm (Just $ AST.PrimName (AST.NSimple resId))
+    
 -----------------------------------------------------------------------------
 -- A table of builtin functions
 -----------------------------------------------------------------------------
@@ -757,6 +896,12 @@ globalNameTable = Map.fromList
   , (shiftrId         , (2, genFCall                ) )
   , (rotlId           , (1, genFCall                ) )
   , (rotrId           , (1, genFCall                ) )
+  , (concatId         , (1, genConcat               ) )
+  , (reverseId        , (1, genFCall                ) )
+  , (iteratenId       , (3, genIteraten             ) )
+  , (iterateId        , (2, genIterate              ) )
+  , (generatenId      , (3, genGeneraten            ) )
+  , (generateId       , (2, genGenerate             ) )
   , (emptyId          , (0, genFCall                ) )
   , (singletonId      , (1, genFCall                ) )
   , (copynId          , (2, genFCall                ) )
index f7d4516c4fd047e6aad63d4d7407de285b7fcc05..def77421281ce0362125c266f3887c9d86c9943b 100644 (file)
@@ -8,9 +8,9 @@ import Types
 import Data.Param.TFVec
 import Data.RangedWord
 
-constant :: NaturalT n => e -> Op n e
+constant :: e -> Op D4 e
 constant e a b =
-  copy e
+  (e +> (e +> (e +> (singleton e))))
 
 invop :: Op n Bit
 invop a b = map hwnot a
@@ -20,12 +20,14 @@ andop a b = zipWith hwand a b
 
 -- Is any bit set?
 --anyset :: (PositiveT n) => Op n Bit
-anyset :: NaturalT n => Op n Bit
+anyset :: (Bit -> Bit -> Bit) -> Op D4 Bit
 --anyset a b = copy undefined (a' `hwor` b')
-anyset a b = constant (a' `hwor` b') a b
+anyset a b = constant (a' `hwor` b') a b
   where 
-    a' = foldl hwor Low a
-    b' = foldl hwor Low b
+    a' = foldl f Low a
+    b' = foldl f Low b
+
+xhwor = hwor
 
 type Op n e = (TFVec n e -> TFVec n e -> TFVec n e)
 type Opcode = Bit
@@ -38,4 +40,4 @@ alu op1 op2 opc a b =
 
 actual_alu :: Opcode -> TFVec D4 Bit -> TFVec D4 Bit -> TFVec D4 Bit
 --actual_alu = alu (constant Low) andop
-actual_alu = alu anyset andop
+actual_alu = alu (anyset xhwor)  andop
diff --git a/VHDL.hs b/VHDL.hs
index 289ecf50f413af09258160065b6e2c3682a46c60..13a92942e171508e13ddffcf8287a04091422a5d 100644 (file)
--- a/VHDL.hs
+++ b/VHDL.hs
@@ -47,12 +47,11 @@ createDesignFiles binds =
   map (Arrow.second $ AST.DesignFile full_context) units
   
   where
-    init_session = VHDLState Map.empty Map.empty Map.empty Map.empty
+    init_session = VHDLState Map.empty [] Map.empty Map.empty
     (units, final_session) = 
       State.runState (createLibraryUnits binds) init_session
     tyfun_decls = map snd $ Map.elems (final_session ^.vsTypeFuns)
-    ty_decls = map mktydecl $ Map.elems (final_session ^. vsTypes)
-    vec_decls = map (\(v_id, v_def) -> AST.PDITD $ AST.TypeDec v_id v_def) (Map.elems (final_session ^. vsElemTypes))
+    ty_decls = final_session ^.vsTypeDecls
     tfvec_index_decl = AST.PDISD $ AST.SubtypeDec tfvec_indexTM tfvec_index_def
     tfvec_range = AST.ConstraintRange $ AST.SubTypeRange (AST.PrimLit "-1") (AST.PrimName $ AST.NAttribute $ AST.AttribName (AST.NSimple integerTM) highId Nothing)
     tfvec_index_def = AST.SubtypeIn integerTM (Just tfvec_range)
@@ -65,13 +64,10 @@ createDesignFiles binds =
       mkUseAll ["work", "types"]
       : (mkUseAll ["work"]
       : ieee_context)
-    type_package_dec = AST.LUPackageDec $ AST.PackageDec (mkVHDLBasicId "types") ([tfvec_index_decl] ++ vec_decls ++ ty_decls ++ subProgSpecs)
+    type_package_dec = AST.LUPackageDec $ AST.PackageDec (mkVHDLBasicId "types") ([tfvec_index_decl] ++ ty_decls ++ subProgSpecs)
     type_package_body = AST.LUPackageBody $ AST.PackageBody typesId tyfun_decls
     subProgSpecs = map subProgSpec tyfun_decls
     subProgSpec = \(AST.SubProgBody spec _ _) -> AST.PDISS spec
-    mktydecl :: (AST.VHDLId, Either AST.TypeDef AST.SubtypeIn) -> AST.PackageDecItem
-    mktydecl (ty_id, Left ty_def) = AST.PDITD $ AST.TypeDec ty_id ty_def
-    mktydecl (ty_id, Right ty_def) = AST.PDISD $ AST.SubtypeDec ty_id ty_def
 
 -- Create a use foo.bar.all statement. Takes a list of components in the used
 -- name. Must contain at least two components
index 06aec7feab602c70478bdeafd9a701e5f4844556..3b49b27fed8270259e2fbc30f6fe2331b098e9e7 100644 (file)
@@ -281,6 +281,7 @@ vhdl_ty msg ty = do
         Just (ty_id, ty_def) -> do
           -- TODO: Check name uniqueness
           modA vsTypes (Map.insert (OrdType ty) (ty_id, ty_def))
+          modA vsTypeDecls (\typedefs -> typedefs ++ [mktydecl (ty_id, ty_def)]) 
           return ty_id
         Nothing -> error $ msg ++ "\nVHDLTools.vhdl_ty: Unsupported Haskell type: " ++ pprString ty ++ "\n"
 
@@ -292,7 +293,7 @@ construct_vhdl_ty msg ty = do
       let name = Name.getOccString (TyCon.tyConName tycon)
       case name of
         "TFVec" -> do
-          res <- mk_vector_ty (tfvec_len ty) (tfvec_elem ty)
+          res <- mk_vector_ty ty
           return $ Just $ (Arrow.second Right) res
         -- "SizedWord" -> do
         --   res <- mk_vector_ty (sized_word_len ty) ty
@@ -339,17 +340,21 @@ mk_tycon_ty msg tycon args =
 
 -- | Create a VHDL vector type
 mk_vector_ty ::
-  Int -- ^ The length of the vector
-  -> Type.Type -- ^ The Haskell element type of the Vector
+  Type.Type -- ^ The Haskell type of the Vector
   -> VHDLSession (AST.TypeMark, AST.SubtypeIn) -- The typemark created.
 
-mk_vector_ty len el_ty = do
-  elem_types_map <- getA vsElemTypes
+mk_vector_ty ty = do
+  types_map <- getA vsTypes
+  let (nvec_l, nvec_el) = Type.splitAppTy ty
+  let (nvec, leng) = Type.splitAppTy nvec_l
+  let vec_ty = Type.mkAppTy nvec nvec_el
+  let len = tfvec_len ty
+  let el_ty = tfvec_elem ty
   let error_msg = "\nVHDLTools.mk_vector_ty: Can not construct vectortype for elementtype: " ++ pprString el_ty 
   el_ty_tm <- vhdl_ty error_msg el_ty
   let ty_id = mkVHDLExtId $ "vector-"++ (AST.fromVHDLId el_ty_tm) ++ "-0_to_" ++ (show len)
   let range = AST.ConstraintIndex $ AST.IndexConstraint [AST.ToRange (AST.PrimLit "0") (AST.PrimLit $ show (len - 1))]
-  let existing_elem_ty = (fmap fst) $ Map.lookup (OrdType el_ty) elem_types_map
+  let existing_elem_ty = (fmap fst) $ Map.lookup (OrdType vec_ty) types_map
   case existing_elem_ty of
     Just t -> do
       let ty_def = AST.SubtypeIn t (Just range)
@@ -357,8 +362,8 @@ mk_vector_ty len el_ty = do
     Nothing -> do
       let vec_id = mkVHDLExtId $ "vector_" ++ (AST.fromVHDLId el_ty_tm)
       let vec_def = AST.TDA $ AST.UnconsArrayDef [tfvec_indexTM] el_ty_tm
-      modA vsElemTypes (Map.insert (OrdType el_ty) (vec_id, vec_def))
-      --modA vsTypeFuns (Map.insert (OrdType el_ty) (genUnconsVectorFuns el_ty_tm vec_id)
+      modA vsTypes (Map.insert (OrdType vec_ty) (vec_id, (Left vec_def)))
+      modA vsTypeDecls (\typedefs -> typedefs ++ [mktydecl (vec_id, (Left vec_def))]
       let ty_def = AST.SubtypeIn vec_id (Just range)
       return (ty_id, ty_def)
 
@@ -384,3 +389,7 @@ getFieldLabels ty = do
   case Map.lookup (OrdType ty) types of
     Just (_, Left (AST.TDR (AST.RecordTypeDef elems))) -> return $ map (\(AST.ElementDec id _) -> id) elems
     _ -> error $ "\nVHDL.getFieldLabels: Type not found or not a record type? This should not happen! Type: " ++ (show ty)
+    
+mktydecl :: (AST.VHDLId, Either AST.TypeDef AST.SubtypeIn) -> AST.PackageDecItem
+mktydecl (ty_id, Left ty_def) = AST.PDITD $ AST.TypeDec ty_id ty_def
+mktydecl (ty_id, Right ty_def) = AST.PDISD $ AST.SubtypeDec ty_id ty_def
index e8a77377f87d4833963b817c6812a9e4b0699fd9..61fb0035650002fa61c95db39bb6c56429114bfb 100644 (file)
@@ -41,9 +41,6 @@ instance Ord OrdType where
 -- A map of a Core type to the corresponding type name
 type TypeMap = Map.Map OrdType (AST.VHDLId, Either AST.TypeDef AST.SubtypeIn)
 
--- A map of Elem types to the corresponding VHDL Id for the Vector
-type ElemTypeMap = Map.Map OrdType (AST.VHDLId, AST.TypeDef)
-
 -- A map of a vector Core element type and function name to the coressponding
 -- VHDLId of the function and the function body.
 type TypeFunMap = Map.Map (OrdType, String) (AST.VHDLId, AST.SubProgBody)
@@ -54,8 +51,8 @@ type SignatureMap = Map.Map CoreSyn.CoreBndr Entity
 data VHDLState = VHDLState {
   -- | A map of Core type -> VHDL Type
   vsTypes_      :: TypeMap,
-  -- | A map of Elem types -> VHDL Vector Id
-  vsElemTypes_   :: ElemTypeMap,
+  -- | A list of type declarations
+  vsTypeDecls_  :: [AST.PackageDecItem],
   -- | A map of vector Core type -> VHDL type function
   vsTypeFuns_   :: TypeFunMap,
   -- | A map of HsFunction -> hardware signature (entity name, port names,
index 7d2d670d5a2e23183fda1b42b13cdbf0b1892d8d..52966dbdd8bede69f2a836f337d9daaad36a8bb2 100644 (file)
@@ -14,7 +14,7 @@ maintainer:          christiaan.baaij@gmail.com & matthijs@stdin.nl
 build-depends:       base > 4, syb, ghc, ghc-paths, transformers, haskell98,
                      ForSyDe > 3.0, regex-posix ,data-accessor-template, pretty,
                      data-accessor, containers, prettyclass, tfp > 0.3, 
-                     tfvec, QuickCheck, template-haskell
+                     tfvec > 0.1.1, QuickCheck, template-haskell
 
 executable:          clash
 main-is:             Main.hs