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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
|
defpackage firrtl/errors :
import core
import verse
import firrtl/ir2
import firrtl/ir-utils
import firrtl/primops
import firrtl/passes
import firrtl-main
;========== ALL CHECKS =================
;CAUGHT IN PARSER
; No nested modules <- parser
; Only modules in circuit (no statements or expressions) <- parser
;CAUGHT in HIGH FORM CHECK
; Unique names per module
; No name can be a prefix of any other name.
; Can only connect to a Ref or Subfield or Index
; UInt only has positive ints
; all references are declared
; mems cannot be a bundle with flips
; cannot connect to Register or ReadPort
;AFTER KIND RESOLUTION
; Cannot connect directly to a mem ever
; onreset can only handle a register
;AFTER TYPE INFERENCE
; expression in pad must be a ground type
; Subfields are only on bundles, before type inference <- need to not error, just do unknown-type
; node's value cannot be a bundle with a flip in it
; 2nd arg in dshr/l must be UInt
; pred in conditionally must be of type UInt
; Type checking
;AFTER WIDTH INFERENCE
; No names
; No Unknowns
; All widths are positive
; Pad's width is greater than value's width
; pad's width is greater than value's width
;AFTER LOWERING
; All things connect to once
; ??
; No combinational loops
; cannot connect to a pad, or a register. only connct to a reference
definterface HighFormException <: Exception
defn HighFormException (s:String) :
new HighFormException :
defmethod print (o:OutputStream, this) :
print(o, s)
defn HighFormExceptions (xs:Streamable<HighFormException>) :
HighFormException(string-join(xs, "\n"))
defn NotUnique (info:FileInfo|False, name:Symbol) :
HighFormException $ string-join $
[info ": Reference " name " does not have a unique name."]
defn IsPrefix (info:FileInfo|False, name1:Symbol, name2:Symbol) :
HighFormException $ string-join $
[info ": Reference " name1 " and " name2 " share a prefix."]
defn InvalidLOC (info:FileInfo|False) :
HighFormException $ string-join $
[info ": Invalid connect to an expression that is not a reference or a WritePort."]
defn NegUInt (info:FileInfo|False) :
HighFormException $ string-join $
[info ": UInt has a negative value."]
defn UndeclaredReference (info:FileInfo|False, name:Symbol) :
HighFormException $ string-join $
[info ": Reference " name " is not declared."]
defn MemWithFlip (info:FileInfo|False, name:Symbol) :
HighFormException $ string-join $
[info ": Memory " name " cannot be a bundle type with flips."]
defn InvalidSubfield (info:FileInfo|False, name:Symbol) :
HighFormException $ string-join $
[info ": Invalid subfield access to non-reference."]
defn InvalidIndex (info:FileInfo|False, name:Symbol) :
HighFormException $ string-join $
[info ": Invalid index access to non-reference."]
defn NoTopModule (info:FileInfo|False, name:Symbol) :
HighFormException $ string-join $
[info ": A single module must be named " name "."]
defn InstNotModule (info:FileInfo|False, name:Symbol) :
HighFormException $ string-join $
[info ": The referenced module in the instance declaration, " name ", is not a reference."]
defn ModuleNotDefined (info:FileInfo|False, name:Symbol) :
HighFormException $ string-join $
[info ": The referenced module in the instance declaration, " name ", is not defined."]
;================ Check Helper Functions ==============
defn has-flip? (t:Type) -> True|False :
var has? = false
defn find-flip (t:Type) -> Type :
match(t) :
(t:BundleType) :
for f in fields(t) do :
if flip(f) == REVERSE : has? = true
t
(t) : t
find-flip(t)
map(find-flip,t)
has?
defn contains?<?T> (c:?T,cs:Streamable<?T>) -> True|False :
label<True|False> myret :
for x in cs do :
if x == c : myret(true)
false
defn is-prefix? (s:Symbol,v:Vector<Symbol>) -> Symbol|False :
label<Symbol|False> myret :
for x in v do :
if is-prefix?(x,s) : myret(x)
false
defn is-prefix? (s1:Symbol,s2:Symbol) -> True|False :
var is? = true
val s1* = to-string(s1)
val s2* = to-string(s2)
for (x in s1*, y in s2*) do :
if x != y : is? = false
if length(s1*) > length(s2*) :
if s1*[length(s2*)] != '$' : is? = false
if length(s1*) < length(s2*) :
if s2*[length(s1*)] != '$' : is? = false
is?
;================= High Form Check ==========================
;CAUGHT in HIGH FORM CHECK
; o Unique names per module
; o No name can be a prefix of any other name.
; o Can only connect to a Ref or Subfield or Index
; o UInt only has positive ints
; o all references are declared
; o cannot connect to Register or ReadPort
; * A module has the same name as main of circuit
; * mems cannot be a bundle with flips
; o instance module must be a reference with same name as defined module
public defn check-high-form (c:Circuit) -> Circuit :
val errors = Vector<HighFormException>()
defn check-high-form-s (s:Stmt,names:Vector<Symbol>) -> Stmt :
defn check-name (info:FileInfo|False,name:Symbol) -> False :
if contains?(name,names) : add(errors,NotUnique(info,name))
val prefix = is-prefix?(name,names)
if prefix typeof Symbol : add(errors,IsPrefix(info,name,prefix as Symbol))
map{check-high-form-s{_,names},_} $ {
match(s) :
(s:DefWire|DefRegister) : check-name(info!(s),name(s))
(s:DefMemory) :
check-name(info!(s),name(s))
if has-flip?(type(s)) : add(errors, MemWithFlip(info!(s), name(s)))
(s:DefInstance) :
if not (module(s) typeof Ref) : add(errors, InstNotModule(info!(s),name(s)))
else :
if not contains?(name(module(s) as Ref),map(name,modules(c))) :
add(errors, ModuleNotDefined(info!(s),name(s)))
(s) : false
s }()
defn check-high-form-m (m:Module) -> False :
val names = Vector<Symbol>()
check-high-form-s(body(m),names)
false
var number-top-m = 0
for m in modules(c) do :
if name(m) == main(c) : number-top-m = number-top-m + 1
check-high-form-m(m)
if number-top-m != 1 : add(errors,NoTopModule(info!(c),main(c)))
throw(HighFormExceptions(errors)) when not empty?(errors)
c
|