Home My Page Projects Code Snippets Project Openings diderot
Summary Activity Tracker Tasks SCM

SCM Repository

[diderot] View of /branches/charisee/src/compiler/tree-il/lowOp-to-treeOp.sml
ViewVC logotype

View of /branches/charisee/src/compiler/tree-il/lowOp-to-treeOp.sml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3195 - (download) (annotate)
Wed May 20 21:02:12 2015 UTC (4 years, 4 months ago) by cchiw
File size: 13074 byte(s)
does not use vectors, benchmarks all faster
(*This function transitions low-il operators to tree-il operators
    When there is a LowIL vector op then it breaks it into HW supported TreeIL vector operation
    i.e. A6+B6=> Mux[A4+B4, A2+B2]
    The following variables are used
    isAligned/A:bool-Is the array aligned
    isFill:bool-Is the vector filled with zeros i.e. length 3 vectors represented with length 4
    nSize: int -The Size of the vector operation, (4)
    oSize:int-The Size of the orginal arguments in vector operation if less than new Size.  (3)
    pieces: sizes of vector operations. i.e.2->[2], 6->[4,2]   3->[4]
*)

(* FIXME: add signature!!! *)
structure LowOpToTreeOp =
  struct
    local
      structure Src = LowIL
      structure SrcOp = LowOps
      structure SrcTy = LowILTypes
      structure SrcV = Src.Var
      structure DstOp = TreeOps
      structure DstTy = TreeILTypes
      structure Dst = TreeIL
      structure DstSV=Dst.StateVar
      structure DstV = Dst.Var
      structure Ty=TreeIL.Ty
    in

    val testing=1
    fun testp t=(case testing
        of 1=>(print(String.concat t);1)
         |_ =>1
    (*end case*))

    (**************************************)
    (* isAlignedLoad: bool* ty->bool
    * Do we Load this array assuming it's aligned?
    * Decides if isAligned is true when creating E_load
    * Currently, it is only true when the vector argument can be represent in the HW
    * Fix here
    *)
    fun isAlignedLoad(isFill,Ty.TensorTy [_]) =(case isFill
        of true => false
        | _     => true
        (*end case*))
    | isAlignedLoad _ =false

    (* isAlignedStore: bool*int->bool
    * Do we Store this array assuming it's aligned?
    * Decides if isAligned is true when creating S_Store and E_Mux
    * Currently, it is false always 
    * Fix here
    *)
    fun (*isAlignedStore(isFill,1) =(case isFill
        of true => false
        | _     => true
    (*end case*))
    |*)isAlignedStore _ =false(*true*)

    (**************************************)
    (*mkStmt:TreeIL.Var* TreeIL.Var.kind*MidIL.Op*bool*int*bool*ty*TreeIL.Exp list ->TreeIL.stmt
    * makes final TreeIL.Stmt
    * When TreeIL.Op is a sumVec is then all ops are added
    * If lhs is a global then S_Store is used
    * Otherwise uses S_Assign
    *)
    fun mkStmt(lhs,lhsKind,origrator,isFill,oSize,A,splitTy,ops)= (case origrator
        of SrcOp.sumVec _ => Dst.S_Assign([lhs], addSca ops)
        | _               => (case lhsKind
            of TreeIL.VK_Local  =>  Dst.S_Assign([lhs], Dst.E_Mux(A,isFill,oSize,splitTy,ops))
            | _     => Dst.S_StoreVec(Dst.E_Var lhs,0,A,isFill,oSize,Ty.TensorTy[oSize],splitTy, ops)
            (*end case*))
        (*end case*))
    and addSca [e1]=e1
    | addSca(e1::e2::es)= addSca([Dst.E_Op(DstOp.addSca,[e1,e2])]@es)



    (**************************************)
    (*getArg:bool*TreeILVar.kind*TreeIL.Exp*int*int*int*int->TreeIL.Exp
    *  Gets the argument for the operation 
    *  if the argument is a mux then we get the piece needed for the operation
    *  if the argument is a local var then we assume it is the right size
    *  if the argument is a global var or state var then we load the array with offset and sizes
    *  otherwise the arg was not loaded probably and should produce an error 
    *)
    fun getArg(isFill,lhsKind,t,count, nSize, oSize,offset)=(case t
        of (Dst.E_Var a) =>(case (DstV.kind a)
            of TreeIL.VK_Local =>t
            | _  => Dst.E_LoadArr(isAlignedLoad(isFill,DstV.ty a) ,nSize,oSize,t, Dst.E_Lit(Literal.Int offset))
            (*end case*))
        | (Dst.E_State a)=> Dst.E_LoadArr(isAlignedLoad(isFill,DstSV.ty a) ,nSize,oSize,t, Dst.E_Lit(Literal.Int offset))
        | (Dst.E_Mux(_,_,_,_,ops))=> List.nth(ops,count)
        | a1 =>( print(String.concat["Warning argument to vector operation is: ",Dst.toString a1]);a1)
        (*|  a1 = raise Fail("Arg to vector op is not Mux or Var. Found: "^Dst.toString a1)*)
        (*end case*))


    (* mkGenericOps:bool.TreeIL.Var.kind*LowILOP*TreeILOP*int*int list*TreeILExp*TreeILExp*int->TreeILExp List
        Take the original vector op and breaks it "pieces" which are HW supported sizes
        gets arguments with getArg(). 
        and then puts them inside TreeIL op ("rator")
        special case sumVecOp, because it maintains new and old size.
        
    *)
    fun mkGenericOps(isFill,lhsKind,oldrator,rator,oSize,pieces,argScas,argVecs,indexAt)= let
        (*createOps:int list*int*int*DstIL.exp->DstIL.exp list
        *  Gets all the Arguments in order
        *   i.e. nsize=[4,2]=>  [[A4,B4],[A2,B2]]
        *)
        fun createOps ([], _,_, code) = code
        | createOps (nSize::es, count,offset, code)=let
            val argsLd =List.map (fn a =>getArg(isFill,lhsKind,a,count, nSize, oSize, offset))  argVecs
            val exp = (nSize, argScas@argsLd)
            in
                createOps (es, count+1,offset + IntInf.fromInt nSize, code@[exp])
            end
        in (case (oldrator,pieces,argVecs)
            of  (SrcOp.sumVec _,_,_) =>let
                val code=createOps (pieces, 0,indexAt, [])
                val args=List.foldr op@ [] (List.map (fn(_,args)=>args) code)
                in
                   (* List.map (fn(nSize,args)=> Dst.E_Op(DstOp.sumVec([nSize],nSize),args)) code*)
                 [Dst.E_Op(DstOp.sumVec(pieces,oSize),args)]
                end
            | _ => let
                val code=createOps (pieces, 0,indexAt, [])
                in
                    List.map (fn(nSize,args)=> Dst.E_Op(rator nSize,args)) code
                end
            (*end case*))
        end

    (* Same funciton as above
    * Except this first scans for special case ProjectLast LowIL Op.
    * ProjectLast is an op that slices a vector from a higher order tensor
    * That vec could be in pieces
    * So we load each one and the next step wraps a mux around it
    * We can assume the higher order tensor is an array
    * This rewrites the ProjectLast op as an E_LoadArr.
    *Otherwise hand off to above function 
    *)
    fun mkOps(isFill,lhsKind,oldrator,rator,oSize,pieces,argScas,argVecs,indexAt)=  (case (oldrator,pieces,argVecs)
        of (SrcOp.ProjectLast(_,_,indTy,argTy),_,[a]) => let
            val A=isAlignedLoad(isFill,argTy)

            (*shift based on type of argument*)
            val shift=(case (indTy,argTy)
                of (Ty.indexTy[i],Ty.TensorTy[_,argTyX])=> i*argTyX         
                    | (Ty.indexTy[j,i],Ty.TensorTy[_,argTyY,argTyX])=> j*(argTyX*argTyY)+i*argTyX
                    |  _ =>raise Fail "ProjectLast Tensor of a unhandled size" (*add this later*)
                    (*end case *))
            fun mkLoad ([], _, code) = code
            | mkLoad (nSize::es, offset, code)=
                mkLoad (es, offset + IntInf.fromInt nSize,
                code@[Dst.E_LoadArr(A, nSize,oSize,a, Dst.E_Lit(Literal.Int offset))])
            in
                mkLoad (pieces, IntInf.fromInt shift, [])
            end
    | (SrcOp.ProjectFirst(_,vecIX,Ty.indexTy[i],Ty.TensorTy[argTy,argTyX]),_,args)=> let
            fun f cnt = Dst.E_Op(DstOp.IndexTensor(false,Ty.indexTy [cnt,i],Ty.TensorTy[argTy,argTyX]),args)
            val indops=List.tabulate(vecIX, fn e=> f e)
            val econs=[Dst.E_Cons(oSize, oSize,indops)]
            in econs end 

        | (SrcOp.sumVec _,[nSize],[a]) =>  [Dst.E_Op(DstOp.sumVec([nSize],oSize), [getArg(isFill,lhsKind,a,0, nSize, oSize, 0)])]
        | _ => mkGenericOps(isFill,lhsKind,oldrator,rator,oSize,pieces,argScas,argVecs,indexAt)
        (*end case*))

        (**************************************)
    (*vecToTree:TreeIL.Var.kind*LowILOP*TreeILOP*int*int*int list*TreeILExp list *TreeILExp list *bool->TreeILExp List
    *Main function that turns a low-il vector operation into tree-il stmt 
    *)
    fun vecToTree(lhs,origrator,rator,nSize,oSize,pieces,argScas,argVecs,isFill)=(case origrator
        of (* SrcOp.ProjectFirst(_,vecIX,Ty.indexTy[i],Ty.TensorTy[argTy,argTyX])=> let
                fun f cnt = Dst.E_Op(DstOp.IndexTensor(false,Ty.indexTy [cnt,i],Ty.TensorTy[argTy,argTyX]),[a])
                val indops=List.tabulate(vecIX, fn e=> f e)
                val econs=Dst.E_Cons(nSize, nSize,ops)
                in
                    mkStmt(lhs,lhsKind,origrator,isFill,oSize,aligned,splitTy,econs)
                end
        |*) _=> let
            val splitTy=DstTy.vectorLength pieces
            val aligned= isAlignedStore(isFill,length pieces)
            val indexAt=IntInf.fromInt 0
            (*Create Ld Expressions and Tree Ops*)
            val lhsKind=DstV.kind lhs

            val ops=mkOps(isFill,lhsKind,origrator,rator,oSize,pieces,argScas,argVecs,indexAt)
        in
            mkStmt(lhs,lhsKind,origrator,isFill,oSize,aligned,splitTy,ops)
        end
    (* end case*))


    (* consVecToTree:int*int*int list*TreeIL.Exp* bool->TreeIL.Exp
     * Takes Cons of a vector and returns TreeIL.exp inside E_Mux.
     *  When isFill is true, creates zeros
     *)
    fun consVecToTree(_,oSize,[nSize],args,true)= let
        val nArg=length(args)
        val n=nSize-nArg
        val newArgs=List.tabulate(n, (fn _=>Dst.E_Lit(Literal.Int 0)))
        val op1=Dst.E_Cons(nSize, oSize,args@newArgs)
        val aligned= isAlignedStore(true,1)
        val splitTy=DstTy.vectorLength [nSize]
        in
            Dst.E_Mux(aligned,true,oSize,splitTy,[op1])
        end
    | consVecToTree(_,_,_,_,true)= raise Fail"In ConsVecToTree-isFill with more than 1 piece"
    | consVecToTree(nSize,oSize,pieces,args,isFill)= let
        val aligned= isAlignedStore(isFill,length pieces)
        val splitTy=DstTy.vectorLength pieces
        fun createOps ([], _,_,_) = []
        | createOps (nSize::es, offset,arg, code)=
            [Dst.E_Cons(nSize, nSize,List.take(arg,nSize))]@
            createOps (es, offset + IntInf.fromInt nSize, List.drop(arg,nSize),code)
        val ops= createOps (pieces, 0,args, [])
        in
            Dst.E_Mux(aligned,isFill,oSize,splitTy,ops)
        end
        (**************************************)

    (*Low-IL operators to Tree-IL operators*)
    fun expandOp rator=(case rator
        of SrcOp.IAdd  =>    DstOp.IAdd
        | SrcOp.ISub  =>    DstOp.ISub
        | SrcOp.IMul  =>    DstOp.IMul
        | SrcOp.IDiv  =>    DstOp.IDiv
        | SrcOp.INeg  =>    DstOp.INeg
        | SrcOp.Abs ty =>    DstOp.Abs ty
        | SrcOp.LT ty =>    DstOp.LT  ty
        | SrcOp.LTE ty =>    DstOp.LTE  ty
        | SrcOp.EQ ty =>    DstOp.EQ  ty
        | SrcOp.NEQ ty =>    DstOp.NEQ  ty
        | SrcOp.GT ty =>    DstOp.GT  ty
        | SrcOp.GTE ty =>    DstOp.GTE  ty
        | SrcOp.Not =>    DstOp.Not
        | SrcOp.Max =>    DstOp.Max
        | SrcOp.Min =>    DstOp.Min
        | SrcOp.Clamp ty =>    DstOp.Clamp ty
        | SrcOp.Lerp ty =>    DstOp.Lerp  ty
        | SrcOp.Sqrt=>      DstOp.Sqrt
      | SrcOp.Cosine=>      DstOp.Cosine
      | SrcOp.ArcCosine=>      DstOp.ArcCosine
      | SrcOp.Sine=>      DstOp.Sine
        | SrcOp.Zero ty =>    DstOp.Zero  ty
        | SrcOp.PrincipleEvec ty =>    DstOp.PrincipleEvec ty
        | SrcOp.EigenVals2x2 =>    DstOp.EigenVals2x2
        | SrcOp.EigenVals3x3 =>    DstOp.EigenVals3x3
        | SrcOp.EigenVecs2x2 =>    DstOp.EigenVecs2x2
        | SrcOp.EigenVecs3x3 =>    DstOp.EigenVecs3x3
        | SrcOp.Select(ty as SrcTy.TupleTy tys, i)  =>    DstOp.Select( ty, i)
        | SrcOp.Index (ty, i ) =>    DstOp.Index ( ty, i)
        | SrcOp.Subscript ty =>    DstOp.Subscript  ty
        | SrcOp.Ceiling d =>    DstOp.Ceiling d
        | SrcOp.Floor d =>    DstOp.Floor d
        | SrcOp.Round d =>    DstOp.Round d
        | SrcOp.Trunc d =>    DstOp.Trunc d
        | SrcOp.IntToReal =>    DstOp.IntToReal
	| SrcOp.R r => DstOp.R r 
        | SrcOp.RealToInt d =>    DstOp.RealToInt d
        (*| SrcOp.VoxelAddress( info, offset)  => expandVoxelAddress  (y, info, offset, args')
        | SrcOp.LoadVoxels (rty, d ) =>    DstOp.LoadVoxels( rty, d)*)
        (*Maybe should delete?*)
        (*  | SrcOp.LoadImage info =>    DstOp.LoadImage info*)
        | SrcOp.Inside info =>    DstOp.Inside info
        | SrcOp.Translate V=>  DstOp.Translate V
        | SrcOp.addSca =>DstOp.addSca
        | SrcOp.subSca => DstOp.subSca
        | SrcOp.prodSca => DstOp.prodSca
        | SrcOp.divSca => DstOp.divSca
	| SrcOp.powRat ty => raise Fail"PowRat"
	| SrcOp.powInt => raise Fail"PowInt"
        (*| SrcOp.Norm ty =>  (DstOp.Norm ty)*)
        | SrcOp.Normalize d =>(DstOp.Normalize d)
        | SrcOp.imgAddr(v,indexAt, dim)=>DstOp.imgAddr(v, indexAt, dim)
        | SrcOp.baseAddr V => DstOp.baseAddr V
        (*EigenVecs,mkDynamic, Append,Prepend, Concat,Length,ImageAddress,LoadVoxel,Inputs, and Pritns*)
        (*| SrcOp.Input e=>*)
	| SrcOp.LoadImage args => DstOp.LoadImage args
	| SrcOp.Input inp => DstOp.Input inp
	| SrcOp.Print tys => DstOp.Print tys
        | rator => raise Fail ("bogus operator " ^ SrcOp.toString rator)
      (* end case *))
    end

  end

root@smlnj-gforge.cs.uchicago.edu
ViewVC Help
Powered by ViewVC 1.0.0