X-Git-Url: https://git.stderr.nl/gitweb?a=blobdiff_plain;f=c%CE%BBash%2FCLasH%2FVHDL%2FGenerate.hs;h=83404334e01d8c4c1c26e3f067b32bf5142e16b8;hb=6b25abd35ae3cfe2fe42b9d0446d35d0dd118f98;hp=afd1741d28dd81924032573bd5f10fdf39011fff;hpb=254a259d6cfa363ac4da8c69b665ce4ce2a29ee7;p=matthijs%2Fmaster-project%2Fc%CE%BBash.git diff --git "a/c\316\273ash/CLasH/VHDL/Generate.hs" "b/c\316\273ash/CLasH/VHDL/Generate.hs" index afd1741..8340433 100644 --- "a/c\316\273ash/CLasH/VHDL/Generate.hs" +++ "b/c\316\273ash/CLasH/VHDL/Generate.hs" @@ -41,7 +41,7 @@ getEntity :: -> TranslatorSession Entity -- ^ The resulting entity getEntity fname = makeCached fname tsEntities $ do - expr <- Normalize.getNormalized fname + expr <- Normalize.getNormalized False fname -- Split the normalized expression let (args, binds, res) = Normalize.splitNormalized expr -- Generate ports for all non-empty types @@ -109,7 +109,7 @@ getArchitecture :: -- ^ The architecture for this function getArchitecture fname = makeCached fname tsArchitectures $ do - expr <- Normalize.getNormalized fname + expr <- Normalize.getNormalized False fname -- Split the normalized expression let (args, binds, res) = Normalize.splitNormalized expr @@ -134,8 +134,14 @@ getArchitecture fname = makeCached fname tsArchitectures $ do (state_proc, resbndr) <- case (Maybe.catMaybes in_state_maybes, Maybe.catMaybes out_state_maybes, init_state) of ([in_state], [out_state], Nothing) -> do nonEmpty <- hasNonEmptyType in_state - if nonEmpty then error ("No initial state defined for: " ++ show fname) else return ([],[]) - ([in_state], [out_state], Just resetval) -> mkStateProcSm (in_state, out_state,resetval) + if nonEmpty + then error ("No initial state defined for: " ++ show fname) + else return ([],[]) + ([in_state], [out_state], Just resetval) -> do + nonEmpty <- hasNonEmptyType in_state + if nonEmpty + then mkStateProcSm (in_state, out_state, resetval) + else error ("Initial state defined for function with only substate: " ++ show fname) ([], [], Just _) -> error $ "Initial state defined for state-less function: " ++ show fname ([], [], Nothing) -> return ([],[]) (ins, outs, res) -> error $ "Weird use of state in " ++ show fname ++ ". In: " ++ show ins ++ " Out: " ++ show outs @@ -272,19 +278,11 @@ mkConcSm (bndr, expr@(CoreSyn.Case (CoreSyn.Var scrut) b ty [alt])) _ -> error $ "\nVHDL.mkConcSM: Not in normal form: Not a selector case:\n" ++ (pprString expr) --- Multiple case alt are be conditional assignments and have only wild +-- Multiple case alt become conditional assignments and have only wild -- binders in the alts and only variables in the case values and a variable -- for a scrutinee. We check the constructor of the second alt, since the -- first is the default case, if there is any. - --- mkConcSm (bndr, (CoreSyn.Case (CoreSyn.Var scrut) b ty [(_, _, CoreSyn.Var false), (con, _, CoreSyn.Var true)])) = do --- scrut' <- MonadState.lift tsType $ varToVHDLExpr scrut --- altcon <- MonadState.lift tsType $ altconToVHDLExpr con --- let cond_expr = scrut' AST.:=: altcon --- true_expr <- MonadState.lift tsType $ varToVHDLExpr true --- false_expr <- MonadState.lift tsType $ varToVHDLExpr false --- return ([mkCondAssign (Left bndr) cond_expr true_expr false_expr], []) -mkConcSm (bndr, (CoreSyn.Case (CoreSyn.Var scrut) _ _ (alt:alts))) = do --error "\nVHDL.mkConcSm: Not in normal form: Case statement with more than two alternatives" +mkConcSm (bndr, (CoreSyn.Case (CoreSyn.Var scrut) _ _ (alt:alts))) = do scrut' <- MonadState.lift tsType $ varToVHDLExpr scrut -- Omit first condition, which is the default altcons <- MonadState.lift tsType $ mapM (altconToVHDLExpr . (\(con,_,_) -> con)) alts @@ -293,7 +291,7 @@ mkConcSm (bndr, (CoreSyn.Case (CoreSyn.Var scrut) _ _ (alt:alts))) = do --error exprs <- MonadState.lift tsType $ mapM (varToVHDLExpr . (\(_,_,CoreSyn.Var expr) -> expr)) (alts ++ [alt]) return ([mkAltsAssign (Left bndr) cond_exprs exprs], []) -mkConcSm (_, CoreSyn.Case _ _ _ _) = error "\nVHDL.mkConcSm: Not in normal form: Case statement has does not have a simple variable as scrutinee" +mkConcSm (_, CoreSyn.Case _ _ _ _) = error "\nVHDL.mkConcSm: Not in normal form: Case statement does not have a simple variable as scrutinee" mkConcSm (bndr, expr) = error $ "\nVHDL.mkConcSM: Unsupported binding in let expression: " ++ pprString bndr ++ " = " ++ pprString expr ----------------------------------------------------------------------------- @@ -336,24 +334,22 @@ genNoInsts wrap dst func args = do genVarArgs :: (dst -> func -> [Var.Var] -> res) -> (dst -> func -> [Either CoreSyn.CoreExpr AST.Expr] -> res) -genVarArgs wrap dst func args = wrap dst func args' - where - args' = map exprToVar exprargs - -- Check (rather crudely) that all arguments are CoreExprs - (exprargs, []) = Either.partitionEithers args +genVarArgs wrap = genCoreArgs $ \dst func args -> let + args' = map exprToVar args + in + wrap dst func args' -- | A function to wrap a builder-like function that expects its arguments to --- be Literals -genLitArgs :: - (dst -> func -> [Literal.Literal] -> TranslatorSession [AST.ConcSm]) - -> (dst -> func -> [Either CoreSyn.CoreExpr AST.Expr] -> TranslatorSession [AST.ConcSm]) -genLitArgs wrap dst func args = do - hscenv <- MonadState.lift tsType $ MonadState.get tsHscEnv - let (exprargs, []) = Either.partitionEithers args - -- FIXME: Check if we were passed an CoreSyn.App - let litargs = concatMap (getLiterals hscenv) exprargs - let args' = map exprToLit litargs - wrap dst func args' +-- be core expressions. +genCoreArgs :: + (dst -> func -> [CoreSyn.CoreExpr] -> res) + -> (dst -> func -> [Either CoreSyn.CoreExpr AST.Expr] -> res) +genCoreArgs wrap dst func args = wrap dst func args' + where + -- Check (rather crudely) that all arguments are CoreExprs + args' = case Either.partitionEithers args of + (exprargs, []) -> exprargs + (exprsargs, rest) -> error $ "\nGenerate.genCoreArgs: expect core expression arguments but found ast exprs:" ++ (show rest) -- | A function to wrap a builder-like function that produces an expression -- and expects it to be assigned to the destination. @@ -413,6 +409,20 @@ genFromSizedWord' (Left res) f args@[arg] = -- map (\exp -> Nothing AST.:=>: AST.ADExpr exp) args genFromSizedWord' (Right name) _ _ = error $ "\nGenerate.genFromSizedWord': Cannot generate builtin function call assigned to a VHDLName: " ++ show name +genFromRangedWord :: BuiltinBuilder +genFromRangedWord = genNoInsts $ genExprArgs $ genExprRes genFromRangedWord' +genFromRangedWord' :: Either CoreSyn.CoreBndr AST.VHDLName -> CoreSyn.CoreBndr -> [AST.Expr] -> TranslatorSession AST.Expr +genFromRangedWord' (Left res) f [arg] = do { + ; let { ty = Var.varType res + ; (tycon, args) = Type.splitTyConApp ty + ; name = Name.getOccString (TyCon.tyConName tycon) + } ; + ; len <- MonadState.lift tsType $ tfp_to_int (sized_word_len_ty ty) + ; return $ AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLBasicId resizeId)) + [Nothing AST.:=>: AST.ADExpr arg, Nothing AST.:=>: AST.ADExpr( AST.PrimLit (show len))] + } +genFromRangedWord' (Right name) _ _ = error $ "\nGenerate.genFromRangedWord': Cannot generate builtin function call assigned to a VHDLName: " ++ show name + genResize :: BuiltinBuilder genResize = genNoInsts $ genExprArgs $ genExprRes genResize' genResize' :: Either CoreSyn.CoreBndr AST.VHDLName -> CoreSyn.CoreBndr -> [AST.Expr] -> TranslatorSession AST.Expr @@ -449,28 +459,29 @@ genTimes' (Left res) f [arg1,arg2] = do { } genTimes' (Right name) _ _ = error $ "\nGenerate.genTimes': Cannot generate builtin function call assigned to a VHDLName: " ++ show name --- FIXME: I'm calling genLitArgs which is very specific function, --- which needs to be fixed as well +-- fromInteger turns an Integer into a Num instance. Since Integer is +-- not representable and is only allowed for literals, the actual +-- Integer should be inlined entirely into the fromInteger argument. genFromInteger :: BuiltinBuilder -genFromInteger = genNoInsts $ genLitArgs $ genExprRes genFromInteger' -genFromInteger' :: Either CoreSyn.CoreBndr AST.VHDLName -> CoreSyn.CoreBndr -> [Literal.Literal] -> TranslatorSession AST.Expr -genFromInteger' (Left res) f lits = do { - ; let { ty = Var.varType res - ; (tycon, args) = Type.splitTyConApp ty - ; name = Name.getOccString (TyCon.tyConName tycon) - } ; - ; len <- case name of +genFromInteger = genNoInsts $ genCoreArgs $ genExprRes genFromInteger' +genFromInteger' :: Either CoreSyn.CoreBndr AST.VHDLName -> CoreSyn.CoreBndr -> [CoreSyn.CoreExpr] -> TranslatorSession AST.Expr +genFromInteger' (Left res) f args = do + let ty = Var.varType res + let (tycon, tyargs) = Type.splitTyConApp ty + let name = Name.getOccString (TyCon.tyConName tycon) + len <- case name of "SizedInt" -> MonadState.lift tsType $ tfp_to_int (sized_int_len_ty ty) "SizedWord" -> MonadState.lift tsType $ tfp_to_int (sized_word_len_ty ty) - "RangedWord" -> do { - ; bound <- MonadState.lift tsType $ tfp_to_int (ranged_word_bound_ty ty) - ; return $ floor (logBase 2 (fromInteger (toInteger (bound)))) + 1 - } - ; let fname = case name of "SizedInt" -> toSignedId ; "SizedWord" -> toUnsignedId ; "RangedWord" -> toUnsignedId - ; return $ AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLBasicId fname)) - [Nothing AST.:=>: AST.ADExpr (AST.PrimLit (show (last lits))), Nothing AST.:=>: AST.ADExpr( AST.PrimLit (show len))] - - } + "RangedWord" -> do + bound <- MonadState.lift tsType $ tfp_to_int (ranged_word_bound_ty ty) + return $ floor (logBase 2 (fromInteger (toInteger (bound)))) + 1 + let fname = case name of "SizedInt" -> toSignedId ; "SizedWord" -> toUnsignedId ; "RangedWord" -> toUnsignedId + case args of + [integer] -> do -- The type and dictionary arguments are removed by genApplication + literal <- getIntegerLiteral integer + return $ AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLBasicId fname)) + [Nothing AST.:=>: AST.ADExpr (AST.PrimLit (show literal)), Nothing AST.:=>: AST.ADExpr( AST.PrimLit (show len))] + _ -> error $ "\nGenerate.genFromInteger': Wrong number of arguments to genInteger. Applying " ++ pprString f ++ " to " ++ pprString args genFromInteger' (Right name) _ _ = error $ "\nGenerate.genFromInteger': Cannot generate builtin function call assigned to a VHDLName: " ++ show name @@ -478,6 +489,10 @@ genSizedInt :: BuiltinBuilder genSizedInt = genFromInteger {- +-- This function is useful for use with vectorTH, since that generates +-- explicit references to the TFVec constructor (which is normally +-- hidden). Below implementation is probably not current anymore, but +-- kept here in case we start using vectorTH again. -- | Generate a Builder for the builtin datacon TFVec genTFVec :: BuiltinBuilder genTFVec (Left res) f [Left (CoreSyn.Let (CoreSyn.Rec letBinders) letRes)] = do { @@ -578,9 +593,7 @@ genMap (Left res) f [Left mapped_f, Left (CoreSyn.Var arg)] = do { genMap' (Right name) _ _ = error $ "\nGenerate.genMap': Cannot generate map function call assigned to a VHDLName: " ++ show name genZipWith :: BuiltinBuilder -genZipWith = genVarArgs genZipWith' -genZipWith' :: (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [Var.Var] -> TranslatorSession ([AST.ConcSm], [CoreSyn.CoreBndr]) -genZipWith' (Left res) f args@[zipped_f, arg1, arg2] = do { +genZipWith (Left res) f args@[Left zipped_f, Left (CoreSyn.Var arg1), Left (CoreSyn.Var arg2)] = do { -- Setup the generate scheme ; len <- MonadState.lift tsType $ tfp_to_int $ (tfvec_len_ty . Var.varType) res -- TODO: Use something better than varToString @@ -592,10 +605,12 @@ genZipWith' (Left res) f args@[zipped_f, arg1, arg2] = do { -- Create the content of the generate statement: Applying the zipped_f to -- each of the elements in arg1 and arg2, storing to each element in res ; resname = mkIndexedName (varToVHDLName res) n_expr + ; (CoreSyn.Var real_f, already_mapped_args) = CoreSyn.collectArgs zipped_f + ; valargs = get_val_args (Var.varType real_f) already_mapped_args ; argexpr1 = vhdlNameToVHDLExpr $ mkIndexedName (varToVHDLName arg1) n_expr ; argexpr2 = vhdlNameToVHDLExpr $ mkIndexedName (varToVHDLName arg2) n_expr } ; - ; (app_concsms, used) <- genApplication (Right resname) zipped_f [Right argexpr1, Right argexpr2] + ; (app_concsms, used) <- genApplication (Right resname) real_f (map Left valargs ++ [Right argexpr1, Right argexpr2]) -- Return the generate functions ; return ([AST.CSGSm $ AST.GenerateSm label genScheme [] app_concsms], used) } @@ -808,15 +823,15 @@ genUnzip' (Left res) f args@[arg] = do _ -> error $ "Unzipping a value that is not a vector? Value: " ++ pprString arg ++ "\nType: " ++ pprString (Var.varType arg) ++ "\nhtype: " ++ show htype genCopy :: BuiltinBuilder -genCopy = genNoInsts $ genVarArgs genCopy' -genCopy' :: (Either CoreSyn.CoreBndr AST.VHDLName ) -> CoreSyn.CoreBndr -> [Var.Var] -> TranslatorSession [AST.ConcSm] -genCopy' (Left res) f args@[arg] = - let - resExpr = AST.Aggregate [AST.ElemAssoc (Just AST.Others) - (AST.PrimName (varToVHDLName arg))] - out_assign = mkUncondAssign (Left res) resExpr - in - return [out_assign] +genCopy = genNoInsts genCopy' +genCopy' :: (Either CoreSyn.CoreBndr AST.VHDLName ) -> CoreSyn.CoreBndr -> [Either CoreSyn.CoreExpr AST.Expr] -> TranslatorSession [AST.ConcSm] +genCopy' (Left res) f [arg] = do { + ; [arg'] <- argsToVHDLExprs [arg] + ; let { resExpr = AST.Aggregate [AST.ElemAssoc (Just AST.Others) arg'] + ; out_assign = mkUncondAssign (Left res) resExpr + } + ; return [out_assign] + } genConcat :: BuiltinBuilder genConcat = genNoInsts $ genVarArgs genConcat' @@ -1548,7 +1563,8 @@ type BuiltinBuilder = type NameTable = Map.Map String (Int, BuiltinBuilder ) -- | The builtin functions we support. Maps a name to an argument count and a --- builder function. +-- builder function. If you add a name to this map, don't forget to add +-- it to VHDL.Constants/builtinIds as well. globalNameTable :: NameTable globalNameTable = Map.fromList [ (exId , (2, genFCall True ) ) @@ -1597,11 +1613,13 @@ globalNameTable = Map.fromList , (gteqId , (2, genOperator2 (AST.:>=:) ) ) , (boolOrId , (2, genOperator2 AST.Or ) ) , (boolAndId , (2, genOperator2 AST.And ) ) + , (boolNot , (1, genOperator1 AST.Not ) ) , (plusId , (2, genOperator2 (AST.:+:) ) ) , (timesId , (2, genTimes ) ) , (negateId , (1, genNegation ) ) , (minusId , (2, genOperator2 (AST.:-:) ) ) , (fromSizedWordId , (1, genFromSizedWord ) ) + , (fromRangedWordId , (1, genFromRangedWord ) ) , (fromIntegerId , (1, genFromInteger ) ) , (resizeWordId , (1, genResize ) ) , (resizeIntId , (1, genResize ) )