- BlackBox:
    name: Clash.Sized.Vector.head
    kind: Expression
    type: 'head :: Vec (n + 1) a -> a'
    template: ~FROMBV[~VAR[vec][0][\0\]][~TYPO]
    workInfo: Never
- BlackBox:
    name: Clash.Sized.Vector.tail
    kind: Expression
    type: 'tail :: Vec (n + 1) a -> Vec n a'
    template: '~VAR[vec][0][1 : $high(~VAR[vec][0])]'
    workInfo: Never
- BlackBox:
    name: Clash.Sized.Vector.last
    kind: Expression
    type: Vec (n + 1) a -> a
    template: ~FROMBV[~VAR[vec][0][\$high(~VAR[vec][0])\]][~TYPO]
    workInfo: Never
- BlackBox:
    name: Clash.Sized.Vector.init
    kind: Expression
    type: Vec (n + 1) a -> Vec n a
    template: '~VAR[vec][0][0 : $high(~VAR[vec][0]) - 1]'
    workInfo: Never
- BlackBox:
    name: Clash.Sized.Vector.select
    kind: Declaration
    type: |-
      select :: (CmpNat (i + s) (s * n) ~ GT) -- ARG[0]
              => SNat f                        -- ARG[1]
              -> SNat s                        -- ARG[2]
              -> SNat n                        -- ARG[3]
              -> Vec i a                       -- ARG[4]
              -> Vec n a
    template: |-
      // select begin
      genvar ~GENSYM[n][1];
      ~GENERATE
        for (~SYM[1]=0; ~SYM[1] < ~LIT[3]; ~SYM[1] = ~SYM[1] + 1) begin : ~GENSYM[select][2]
          assign ~RESULT[~SYM[1]] = ~VAR[vec][4][~LIT[1] + (~LIT[2] * ~SYM[1])];
        end
      ~ENDGENERATE
      // select end
    workInfo: Never
- BlackBox:
    name: Clash.Sized.Vector.++
    kind: Expression
    type: '(++) :: Vec n a -> Vec m a -> Vec (n + m) a'
    template: ~FROMBV[{~TOBV[~ARG[0]][~TYP[0]],~TOBV[~ARG[1]][~TYP[1]]}][~TYPO]
    workInfo: Never
- BlackBox:
    name: Clash.Sized.Vector.concat
    kind: Declaration
    type: 'concat :: Vec n (Vec m a) -> Vec (n * m) a'
    template: |-
      // concat begin
      genvar ~GENSYM[n][1];
      ~GENERATE
        for (~SYM[1]=0; ~SYM[1] < $size(~VAR[vec][0]); ~SYM[1] = ~SYM[1] + 1) begin : ~GENSYM[concat][2]
          assign ~RESULT[~SYM[1]*~LENGTH[~TYPEL[~TYP[0]]] : ~SYM[1]*~LENGTH[~TYPEL[~TYP[0]]]+(~LENGTH[~TYPEL[~TYP[0]]]-1)] = ~FROMBV[~VAR[vec][0][\~SYM[1]\]][~TYPEL[~TYP[0]]];
        end
      ~ENDGENERATE
      // concat end
    workInfo: Never
- BlackBox:
    name: Clash.Sized.Vector.splitAt
    kind: Declaration
    type: 'splitAt :: SNat m -> Vec (m + n) a -> (Vec m a, Vec n a)'
    template: |-
      // splitAt begin~IF~LENGTH[~TYPO]~THEN
      assign ~RESULT = ~ARG[1];~ELSE
      logic [0:~LENGTH[~TYP[1]]-1] [0:~SIZE[~TYPEL[~TYP[1]]]-1] ~GENSYM[vec][0];
      assign ~SYM[0] = ~TOBV[~ARG[1]][~TYP[1]];
      ~GENERATE
        if (~LIT[0] == ~LENGTH[~TYP[1]]) begin : ~GENSYM[no_split][1]
          assign ~RESULT = {~SYM[0]};
        end else begin : ~GENSYM[do_split][2]
          assign ~RESULT = {~SYM[0][0:~LIT[0]-1]
                           ,~SYM[0][~LIT[0]:~LENGTH[~TYP[1]]-1]
                           };
        end
      ~ENDGENERATE~FI
      // splitAt end
    workInfo: Never
- BlackBox:
    name: Clash.Sized.Vector.unconcat
    kind: Declaration
    type: |-
      unconcat :: KnownNat n     -- ARG[0]
                 => SNat m         -- ARG[1]
                 -> Vec (n * m) a  -- ARG[2]
                 -> Vec n (Vec m a)
    template: |-
      // unconcat begin~DEVNULL[~ARG[0]]
      genvar ~GENSYM[n][1];
      ~GENERATE
        for (~SYM[1] = 0; ~SYM[1] < $size(~RESULT); ~SYM[1] = ~SYM[1] + 1) begin : ~GENSYM[unconcat][2]
          assign ~RESULT[~SYM[1]] = ~TOBV[~VAR[vec][2][\(~SYM[1] * ~LIT[1]) : ((~SYM[1] * ~LIT[1]) + ~LIT[1] - 1)\]][~TYPEL[~TYPO]];
        end
      ~ENDGENERATE
      // unconcat end
    workInfo: Never
- BlackBox:
    name: Clash.Sized.Vector.map
    kind: Declaration
    type: 'map :: (a -> b) -> Vec n a -> Vec n b'
    template: |-
      // map begin
      genvar ~GENSYM[n][1];
      ~GENERATE
      for (~SYM[1]=0; ~SYM[1] < $size(~RESULT); ~SYM[1] = ~SYM[1] + 1) begin : ~GENSYM[map][2]~IF~SIZE[~TYP[1]]~THEN
        ~TYPEL[~TYP[1]] ~GENSYM[map_in][3];
        assign ~SYM[3] = ~FROMBV[~VAR[vec][1][\~SYM[1]\]][~TYPEL[~TYP[1]]];~ELSE ~FI
        ~TYPEL[~TYPO] ~GENSYM[map_out][4];
        ~INST 0
          ~OUTPUT <= ~SYM[4]~ ~TYPEL[~TYPO]~
          ~INPUT  <= ~SYM[3]~ ~TYPEL[~TYP[1]]~
        ~INST
        assign ~RESULT[~SYM[1]] = ~TOBV[~SYM[4]][~TYPEL[~TYPO]];
      end
      ~ENDGENERATE
      // map end
    workInfo: Never
- BlackBox:
    name: Clash.Sized.Vector.imap
    kind: Declaration
    type: 'imap :: KnownNat n => (Index n -> a -> b) -> Vec n a -> Vec n b'
    template: |-
      // imap begin
      genvar ~GENSYM[n][1];
      ~GENERATE
      for (~SYM[1]=0; ~SYM[1] < $size(~RESULT); ~SYM[1] = ~SYM[1] + 1) begin : ~GENSYM[imap][2]
        ~INDEXTYPE[~LIT[0]] ~GENSYM[i][3];
        assign ~SYM[3] = ~SYM[1];~IF~SIZE[~TYP[2]]~THEN
        ~TYPEL[~TYP[2]] ~GENSYM[imap_in][4];
        assign ~SYM[4] = ~FROMBV[~VAR[vec][2][\~SYM[1]\]][~TYPEL[~TYP[2]]];~ELSE ~FI
        ~TYPEL[~TYPO] ~GENSYM[imap_out][5];
        ~INST 1
          ~OUTPUT <= ~SYM[5]~ ~TYPEL[~TYPO]~
          ~INPUT  <= ~SYM[3]~ ~INDEXTYPE[~LIT[0]]~
          ~INPUT  <= ~SYM[4]~ ~TYPEL[~TYP[2]]~
        ~INST
        assign ~RESULT[~SYM[1]] = ~TOBV[~SYM[5]][~TYPEL[~TYPO]];
      end
      ~ENDGENERATE
      // imap end
    workInfo: Never
- BlackBox:
    name: Clash.Sized.Vector.imap_go
    kind: Declaration
    type: 'imap_go :: (Index n -> a -> b) -> Vec m a -> Index n -> Vec m b'
    template: |-
      // imap begin
      genvar ~GENSYM[n][1];
      ~GENERATE
      for (~SYM[1]=0; ~SYM[1] < $size(~RESULT); ~SYM[1] = ~SYM[1] + 1) begin : ~GENSYM[imap][2]
        ~TYP[2] ~GENSYM[i][3];
        assign ~SYM[3] = ~SYM[1] + ~ARG[2];~IF~SIZE[~TYP[1]]~THEN
        ~TYPEL[~TYP[1]] ~GENSYM[imap_in][4];
        assign ~SYM[4] = ~FROMBV[~VAR[vec][1][\~SYM[1]\]][~TYPEL[~TYP[1]]];~ELSE ~FI
        ~TYPEL[~TYPO] ~GENSYM[imap_out][5];
        ~INST 0
          ~OUTPUT <= ~SYM[5]~ ~TYPEL[~TYPO]~
          ~INPUT  <= ~SYM[3]~ ~TYP[2]~
          ~INPUT  <= ~SYM[4]~ ~TYPEL[~TYP[1]]~
        ~INST
        assign ~RESULT[~SYM[1]] = ~TOBV[~SYM[5]][~TYPEL[~TYPO]];
      end
      ~ENDGENERATE
      // imap end
    workInfo: Never
- BlackBox:
    name: Clash.Sized.Vector.zipWith
    kind: Declaration
    type: 'zipWith :: (a -> b -> c) -> Vec n a -> Vec n b -> Vec n c'
    template: |-
      // zipWith begin
      genvar ~GENSYM[n][2];
      ~GENERATE
      for (~SYM[2] = 0; ~SYM[2] < $size(~RESULT); ~SYM[2] = ~SYM[2] + 1) begin : ~GENSYM[zipWith][3]~IF~SIZE[~TYP[1]]~THEN
        ~TYPEL[~TYP[1]] ~GENSYM[zipWith_in1][4];
        assign ~SYM[4] = ~FROMBV[~VAR[vec1][1][\~SYM[2]\]][~TYPEL[~TYP[1]]];~ELSE ~FI~IF~SIZE[~TYP[2]]~THEN
        ~TYPEL[~TYP[2]] ~GENSYM[zipWith_in2][5];
        assign ~SYM[5] = ~FROMBV[~VAR[vec2][2][\~SYM[2]\]][~TYPEL[~TYP[2]]];~ELSE ~FI
        ~TYPEL[~TYPO] ~GENSYM[zipWith_out][6];
        ~INST 0
          ~OUTPUT <= ~SYM[6]~ ~TYPEL[~TYPO]~
          ~INPUT  <= ~SYM[4]~ ~TYPEL[~TYP[1]]~
          ~INPUT  <= ~SYM[5]~ ~TYPEL[~TYP[2]]~
        ~INST
        assign ~RESULT[~SYM[2]] = ~TOBV[~SYM[6]][~TYPEL[~TYPO]];
      end
      ~ENDGENERATE
      // zipWith end
    workInfo: Never
- BlackBox:
    name: Clash.Sized.Vector.foldr
    kind: Declaration
    type: 'foldr :: (a -> b -> b) -> b -> Vec n a -> b'
    template: |-
      // foldr start~IF ~LENGTH[~TYP[2]] ~THEN
      ~SIGDO[~GENSYM[intermediate][0]] [0:~LENGTH[~TYP[2]]];
      assign ~SYM[0][~LENGTH[~TYP[2]]] = ~ARG[1];

      genvar ~GENSYM[i][3];
      ~GENERATE
      for (~SYM[3]=0; ~SYM[3] < ~LENGTH[~TYP[2]]; ~SYM[3]=~SYM[3]+1) begin : ~GENSYM[foldr_loop][4]~IF~SIZE[~TYP[2]]~THEN
        ~TYPEL[~TYP[2]] ~GENSYM[foldr_in][5];
        assign ~SYM[5] = ~FROMBV[~VAR[xs][2][\~SYM[3]\]][~TYPEL[~TYP[2]]];~ELSE ~FI
        ~INST 0
          ~OUTPUT <= ~SYM[0][~SYM[3]]~ ~TYP[1]~
          ~INPUT <= ~SYM[5]~ ~TYPEL[~TYP[2]]~
          ~INPUT <= ~SYM[0][~SYM[3]+1]~ ~TYP[1]~
        ~INST
      end
      ~ENDGENERATE

      assign ~RESULT = ~SYM[0][0];
      ~ELSE
      assign ~RESULT = ~ARG[1];
      ~FI// foldr end
    workInfo: Never
- BlackBox:
    name: Clash.Sized.Vector.index_int
    kind: Expression
    type: 'index_int :: KnownNat n => Vec n a -> Int -> a'
    template: ~IF~SIZE[~TYP[1]]~THEN~FROMBV[~VAR[vec][1][\~ARG[2]\]][~TYPO]~ELSE~ERRORO~FI
- BlackBox:
    name: Clash.Sized.Vector.replace_int
    kind: Declaration
    outputUsage: Blocking
    type: 'replace_int :: KnownNat n => Vec n a -> Int -> a -> Vec n a'
    template: |-
      // replaceVec start
      always_comb begin
        ~RESULT = ~ARG[1];
        ~RESULT[~ARG[2]] = ~TOBV[~ARG[3]][~TYP[3]];
      end
      // replaceVec end
- BlackBox:
    name: Clash.Sized.Vector.replicate
    kind: Expression
    type: 'replicate :: SNat n -> a -> Vec n a'
    template: "'{~LIT[0] {~TOBV[~ARG[1]][~TYP[1]]}}"
    workInfo: Never
- BlackBox:
    name: Clash.Sized.Vector.transpose
    kind: Declaration
    type: 'transpose :: KnownNat n => Vec m (Vec n a) -> Vec n (Vec m a)'
    template: |-
      // transpose begin
      genvar ~GENSYM[row_index][1];
      genvar ~GENSYM[col_index][2];
      ~GENERATE
        for (~SYM[1] = 0; ~SYM[1] < $size(~VAR[matrix][1]); ~SYM[1] = ~SYM[1] + 1) begin : ~GENSYM[transpose_outer][3]
          for (~SYM[2] = 0; ~SYM[2] < $size(~RESULT); ~SYM[2] = ~SYM[2] + 1) begin : ~GENSYM[transpose_inner][4]~IF ~VIVADO ~THEN
            assign ~RESULT[~SYM[2]][($size(~VAR[matrix][1])-~SYM[1])*~SIZE[~TYPEL[~TYPEL[~TYPO]]]-1 : ($size(~VAR[matrix][1])-~SYM[1]-1)*~SIZE[~TYPEL[~TYPEL[~TYPO]]]] = ~VAR[matrix][1][~SYM[1]][($size(~RESULT)-~SYM[2])*~SIZE[~TYPEL[~TYPEL[~TYPO]]]-1 : ($size(~RESULT)-~SYM[2]-1)*~SIZE[~TYPEL[~TYPEL[~TYPO]]]];~ELSE
            assign ~RESULT[~SYM[2]][~SYM[1]] = ~VAR[matrix][1][~SYM[1]][~SYM[2]];~FI
          end
        end
      ~ENDGENERATE
      // transpose end
    workInfo: Never
- BlackBox:
    name: Clash.Sized.Vector.reverse
    kind: Declaration
    type: 'reverse :: Vec n a -> Vec n a'
    template: |-
      // reverse begin
      genvar ~GENSYM[n][1];
      ~GENERATE
        for (~SYM[1] = 0; ~SYM[1] < $size(~VAR[vec][0]); ~SYM[1] = ~SYM[1] + 1) begin : ~GENSYM[reverse][2]
          assign ~RESULT[$high(~VAR[vec][0]) - ~SYM[1]] = ~VAR[vec][0][~SYM[1]];
        end
      ~ENDGENERATE
      // reverse end
    workInfo: Never
- BlackBox:
    name: Clash.Sized.Vector.concatBitVector#
    kind: Expression
    type: |-
      concatBitVector# :: (KnownNat n,KnownNat m) -- (ARG[0],ARG[1])
                        => Vec n (BitVector m)     -- ARG[2]
                        -> BitVector (n * m)
    template: ~TOBV[~ARG[2]][~TYP[2]]
    workInfo: Never
- BlackBox:
    name: Clash.Sized.Vector.unconcatBitVector#
    kind: Expression
    type: |-
      unconcatBitVector# :: (KnownNat n, KnownNat m) -- (ARG[0],ARG[1])
                          => BitVector (n * m)        -- ARG[2]
                          -> Vec n (BitVector m)
    template: ~FROMBV[~ARG[2]][~TYPO]
    workInfo: Never
- BlackBox:
    name: Clash.Sized.Vector.rotateLeftS
    kind: Declaration
    type: 'rotateLeftS :: KnownNat n => Vec n a -> SNat d -> Vec n a'
    template: |-
      // rotateLeftS begin
      localparam ~GENSYM[shift_amount][2] = ~LIT[2] % ~LIT[0];

      ~GENERATE
      if (~SYM[2] == 0) begin : ~GENSYM[no_shift][3]
        assign ~RESULT = ~VAR[vec][1];
      end else begin : ~GENSYM[do_shift][4]
        assign ~RESULT[0:~LIT[0]-~SYM[2]-1] = ~VAR[vec][1][~SYM[2]:~LIT[0]-1];
        assign ~RESULT[~LIT[0]-~SYM[2]:~LIT[0]-1] = ~VAR[vec][1][0:~SYM[2]-1];
      end
      ~ENDGENERATE
      // rotateLeftS end
    workInfo: Never
- BlackBox:
    name: Clash.Sized.Vector.rotateRightS
    kind: Declaration
    type: 'rotateRightS :: KnownNat n => Vec n a -> SNat d -> Vec n a'
    template: |-
      // rotateRightS begin
      localparam ~GENSYM[shift_amount][2] = ~LIT[2] % ~LIT[0];

      ~GENERATE
      if (~SYM[2] == 0) begin : ~GENSYM[no_shift][3]
        assign ~RESULT = ~VAR[vec][1];
      end else begin : ~GENSYM[do_shift][4]
        assign ~RESULT[0:~SYM[2]-1] = ~VAR[vec][1][~LIT[0]-~SYM[2]:~LIT[0]-1];
        assign ~RESULT[~SYM[2]:~LIT[0]-1] = ~VAR[vec][1][0:~LIT[0]-~SYM[2]-1];
      end
      ~ENDGENERATE
      // rotateRightS end
    workInfo: Never
