aboutsummaryrefslogtreecommitdiff
path: root/src/main/stanza/primop.stanza
blob: 023723b8d632fc19bd2b164cf579a3d7b8d5abaa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
defpackage firrtl/primops :
  import core
  import verse
  import firrtl/ir2
  import firrtl/ir-utils
  import firrtl/passes

public defn lower-and-type-primop (e:DoPrim) -> DoPrim :
   defn u () : UIntType(UnknownWidth())
   defn s () : SIntType(UnknownWidth())
   defn u-and (op1:Expression,op2:Expression) : 
      match(type(op1), type(op2)) :
         (t1:UIntType, t2:UIntType) : u()
         (t1:SIntType, t2) : s()
         (t1, t2:SIntType) : s()
         (t1, t2) : UnknownType()
        
   defn of-type (op:Expression) :
      match(type(op)) :
         (t:UIntType) : u()
         (t:SIntType) : s()
         (t) : UnknownType()

   ;println-all(["Inferencing primop type: " e])
   switch {op(e) == _} :
      ADD-OP             : DoPrim(ADD-OP,args(e),consts(e),u-and(args(e)[0],args(e)[1])) 
      SUB-OP             : DoPrim(SUB-OP,args(e),consts(e),s())
      MUL-OP             : DoPrim(MUL-OP,args(e),consts(e),u-and(args(e)[0],args(e)[1]))
      DIV-OP             : DoPrim(DIV-OP,args(e),consts(e),u-and(args(e)[0],args(e)[1]))
      MOD-OP             : DoPrim(MOD-OP,args(e),consts(e),of-type(args(e)[0]))
      QUO-OP             : DoPrim(QUO-OP,args(e),consts(e),u-and(args(e)[0],args(e)[1]))
      REM-OP             : DoPrim(REM-OP,args(e),consts(e),of-type(args(e)[1]))
      ADD-WRAP-OP        : DoPrim(ADD-WRAP-OP,args(e),consts(e),u-and(args(e)[0],args(e)[1]))
      SUB-WRAP-OP        : DoPrim(SUB-WRAP-OP,args(e),consts(e),u-and(args(e)[0],args(e)[1]))
      LESS-OP            : DoPrim(LESS-OP,args(e),consts(e),u())
      LESS-EQ-OP         : DoPrim(LESS-EQ-OP,args(e),consts(e),u())
      GREATER-OP         : DoPrim(GREATER-OP,args(e),consts(e),u())
      GREATER-EQ-OP      : DoPrim(GREATER-EQ-OP,args(e),consts(e),u())
      EQUAL-OP           : DoPrim(EQUAL-OP,args(e),consts(e),u())
      NEQUAL-OP          : DoPrim(NEQUAL-OP,args(e),consts(e),u())
      MUX-OP             : DoPrim(MUX-OP,args(e),consts(e),of-type(args(e)[1]))
      PAD-OP             : DoPrim(PAD-OP,args(e),consts(e),of-type(args(e)[0]))
      AS-UINT-OP         : DoPrim(AS-UINT-OP,args(e),consts(e),u())
      AS-SINT-OP         : DoPrim(AS-SINT-OP,args(e),consts(e),s())
      DYN-SHIFT-LEFT-OP  : DoPrim(DYN-SHIFT-LEFT-OP,args(e),consts(e),of-type(args(e)[0]))
      DYN-SHIFT-RIGHT-OP : DoPrim(DYN-SHIFT-RIGHT-OP,args(e),consts(e),of-type(args(e)[0]))
      SHIFT-LEFT-OP      : DoPrim(SHIFT-LEFT-OP,args(e),consts(e),of-type(args(e)[0]))
      SHIFT-RIGHT-OP     : DoPrim(SHIFT-RIGHT-OP,args(e),consts(e),of-type(args(e)[0]))
      CONVERT-OP         : DoPrim(CONVERT-OP,args(e),consts(e),s())
      NEG-OP             : DoPrim(NEG-OP,args(e),consts(e),u())
      BIT-NOT-OP         : DoPrim(op(e),args(e),consts(e),u())
      BIT-AND-OP         : DoPrim(op(e),args(e),consts(e),u())
      BIT-OR-OP          : DoPrim(op(e),args(e),consts(e),u())
      BIT-XOR-OP         : DoPrim(op(e),args(e),consts(e),u())
      CONCAT-OP          : DoPrim(op(e),args(e),consts(e),u())
      BIT-SELECT-OP      : DoPrim(op(e),args(e),consts(e),u())
      BITS-SELECT-OP     : DoPrim(op(e),args(e),consts(e),u())
      BIT-AND-REDUCE-OP  : DoPrim(op(e),args(e),consts(e),u())
      BIT-OR-REDUCE-OP   : DoPrim(op(e),args(e),consts(e),u())
      BIT-XOR-REDUCE-OP  : DoPrim(op(e),args(e),consts(e),u())

public defn primop-gen-constraints (e:DoPrim,v:Vector<WGeq>) -> Type :
   defn get-max (i0:Int,i1:Int) -> Width : get-max(list(i0,i1))
   defn get-max (ls:List<Int>) -> Width : 
      MaxWidth $ for i in ls map : width!(args(e)[i])
   defn all-max () -> Width :
      MaxWidth $ for x in args(e) map : width!(x)

   println-all-debug(["Looking at " op(e) " with inputs " args(e)])
   val w* = switch {op(e) == _} :
      ADD-OP : PlusWidth(get-max(0,1),IntWidth(1))
      SUB-OP : PlusWidth(get-max(0,1),IntWidth(1))
      MUL-OP : PlusWidth(get-max(0,1),get-max(0,1))
      DIV-OP : 
         match(type(args(e)[0]),type(args(e)[1])) :
            (t0:UIntType,t1:SIntType) : PlusWidth(width!(args(e)[0]),IntWidth(1))
            (t0:SIntType,t1:SIntType) : PlusWidth(width!(args(e)[0]),IntWidth(1))
            (t0,t1) : width!(args(e)[0])
      MOD-OP : 
         match(type(args(e)[0]),type(args(e)[1])) :
            (t0:SIntType,t1:UIntType) : PlusWidth(width!(args(e)[1]),IntWidth(1))
            (t0,t1) : width!(args(e)[1])
      QUO-OP : 
         match(type(args(e)[0]),type(args(e)[1])) :
            (t0:UIntType,t1:SIntType) : PlusWidth(width!(args(e)[0]),IntWidth(1))
            (t0:SIntType,t1:SIntType) : PlusWidth(width!(args(e)[0]),IntWidth(1))
            (t0,t1) : width!(args(e)[0])
      REM-OP : 
         match(type(args(e)[0]),type(args(e)[1])) :
            (t0:SIntType,t1:UIntType) : PlusWidth(width!(args(e)[1]),IntWidth(1))
            (t0,t1) : width!(args(e)[1])
      ADD-WRAP-OP : get-max(0,1)
      SUB-WRAP-OP : get-max(0,1)
      LESS-OP : IntWidth(1)
      LESS-EQ-OP : IntWidth(1)
      GREATER-OP : IntWidth(1)
      GREATER-EQ-OP : IntWidth(1)
      EQUAL-OP : IntWidth(1)
      NEQUAL-OP : IntWidth(1)
      MUX-OP : 
         add(v,WGeq(IntWidth(1),width!(args(e)[0])))
         add(v,WGeq(width!(args(e)[0]),IntWidth(1)))
         get-max(1,2)
      PAD-OP : IntWidth(consts(e)[0])
      AS-UINT-OP : width!(args(e)[0])
      AS-SINT-OP : width!(args(e)[0])
      SHIFT-LEFT-OP : PlusWidth(width!(args(e)[0]),IntWidth(consts(e)[0]))
      SHIFT-RIGHT-OP : MinusWidth(width!(args(e)[0]),IntWidth(consts(e)[0]))
      DYN-SHIFT-LEFT-OP : PlusWidth(width!(args(e)[0]),ExpWidth(width!(args(e)[1])))
      DYN-SHIFT-RIGHT-OP : width!(args(e)[0])
      CONVERT-OP : 
         match(type(args(e)[0])) :
            (t0:UIntType) : PlusWidth(width!(args(e)[0]),IntWidth(1))
            (t0:SIntType) : width!(args(e)[0])
      NEG-OP : PlusWidth(width!(args(e)[0]),IntWidth(1))
      BIT-NOT-OP : width!(args(e)[0])
      BIT-AND-OP : get-max(0,1)
      BIT-OR-OP :  get-max(0,1)
      BIT-XOR-OP : get-max(0,1)
      BIT-AND-REDUCE-OP : all-max()
      BIT-OR-REDUCE-OP  : all-max()
      BIT-XOR-REDUCE-OP : all-max()
      CONCAT-OP : PlusWidth(width!(args(e)[0]),width!(args(e)[1]))
      BIT-SELECT-OP  : IntWidth(1)
      BITS-SELECT-OP : IntWidth(consts(e)[0] - consts(e)[1])

   match(type(e)) :
      (t:UIntType) : UIntType(w*)
      (t:SIntType) : SIntType(w*)
      (t) : error("Shouldn't be here")