aboutsummaryrefslogtreecommitdiff
path: root/src/main/stanza/chirrtl.stanza
blob: 4f1c9cd5bfc5b7188ee59fce3b375916d35a8db1 (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
defpackage firrtl/chirrtl :
   import core
   import verse
   import firrtl/ir2
   import firrtl/ir-utils

public defstruct ToIR <: Pass
public defmethod pass (b:ToIR) -> (Circuit -> Circuit) : to-ir
public defmethod name (b:ToIR) -> String : "To IR"
public defmethod short-name (b:ToIR) -> String : "to-ir"

defstruct MPort :
   name : Symbol
   clk : Expression
defstruct MPorts :
   readers : Vector<MPort>
   writers : Vector<MPort>
   readwriters : Vector<MPort>
defstruct DataRef :
   exp : Expression
   male : Symbol
   female : Symbol

public definterface Gender
public val MALE = new Gender
public val FEMALE = new Gender

defn to-ir (c:Circuit) :
   defn to-ir-m (m:InModule) -> InModule :
      val hash = HashTable<Symbol,MPorts>(symbol-hash)
      val sh = get-sym-hash(m,keys(v-keywords))
      val repl = HashTable<Symbol,DataRef>(symbol-hash)
      val ut = UnknownType()
      defn EMPs () -> MPorts : 
         MPorts(Vector<MPort>(),Vector<MPort>(),Vector<MPort>())
      defn collect-mports (s:Stmt) -> Stmt :
         match(s) :
            (s:CDefMPort) : 
               val mports = get?(hash,mem(s),EMPs())
               switch { _ == direction(s) } :
                  MRead : add(readers(mports),MPort(name(s),exps(s)[1]))
                  MWrite : add(writers(mports),MPort(name(s),exps(s)[1]))
                  MReadWrite : add(readwriters(mports),MPort(name(s),exps(s)[1]))
               hash[mem(s)] = mports
               s
            (s) : map(collect-mports,s)
      defn collect-refs (s:Stmt) -> Stmt :
         match(s) :
            (s:CDefMemory) :
               val stmts = Vector<Stmt>()
               val n = firrtl-gensym(`GEN,sh)
               val t = UIntType(IntWidth(ceil-log2(size(s))))
               add(stmts,DefPoison(info(s),n,t))
               defn set-poison (vec:List<MPort>,addr:Symbol) -> False :
                  for r in vec do :
                     add(stmts,Connect(info(s),SubField(SubField(Ref(name(s),ut),name(r),ut),addr,t),Ref(n,t)))
                     add(stmts,Connect(info(s),SubField(SubField(Ref(name(s),ut),name(r),ut),`clk,t),clk(r)))
               val rds = to-list $ readers $ get?(hash,name(s),EMPs())
               set-poison(rds,`addr)
               val wrs = to-list $ writers $ get?(hash,name(s),EMPs())
               set-poison(wrs,`addr)
               val rws = to-list $ readwriters $ get?(hash,name(s),EMPs())
               set-poison(rws,`waddr)
               set-poison(rws,`raddr)
               val read-l = 
                  if seq?(s) : 1
                  else : 0
               val mem = DefMemory(info(s),name(s),type(s),size(s),1,read-l,map(name,rds),map(name,wrs),map(name,rws))
               Begin $ List(mem,to-list(stmts))
            (s:CDefMPort) :
               val addrs = Vector<Symbol>()
               val ens = Vector<Symbol>()
               val masks = Vector<Symbol>()
               switch { _ == direction(s) } :
                  MReadWrite : 
                     repl[name(s)] = DataRef(SubField(Ref(mem(s),ut),name(s),ut),`wdata,`rdata)
                     add(addrs,`addr)
                     add(ens,`wen)
                     add(ens,`ren)
                  else : ; TODO add MWrite for mask
                     repl[name(s)] = DataRef(SubField(Ref(mem(s),ut),name(s),ut),`data,`data)
                     add(addrs,`addr)
                     add(ens,`en)
               val stmts = Vector<Stmt>()
               for x in addrs do :
                  add(stmts,Connect(info(s),SubField(SubField(Ref(mem(s),ut),name(s),ut),x,ut),exps(s)[0]))
               for x in ens do :
                  add(stmts,Connect(info(s),SubField(SubField(Ref(mem(s),ut),name(s),ut),x,ut),one))
               Begin $ to-list $ stmts   
            (s) : map(collect-refs,s)
      defn to-ir-e (e:Expression,g:Gender) -> Expression :
         match(map(to-ir-e{_,g},e)) :
            (e:Ref) : 
               if key?(repl,name(e)) : 
                  val vt = repl[name(e)]
                  switch {g == _ }:
                     MALE : SubField(exp(vt),male(vt),ut)
                     FEMALE : SubField(exp(vt),female(vt),ut)
               else : e
            (e) : e
      defn to-ir-s (s:Stmt) -> Stmt :
         match(s) :
            (s:Connect|BulkConnect) : 
               val loc* = to-ir-e(loc(s),FEMALE)
               val roc* = to-ir-e(exp(s),MALE)
               Connect(info(s),loc*,roc*)
            (s) : map(to-ir-e{_,MALE}, map(to-ir-s,s))
      collect-mports(body(m))
      val s* = collect-refs(body(m))
      InModule(info(m),name(m), ports(m), to-ir-s(s*))
   Circuit(info(c),modules*, main(c)) where :
      val modules* =
         for m in modules(c) map :
            match(m) :
               (m:InModule) : to-ir-m(m)
               (m:ExModule) : m