1 // Copyright 2017-2019 VMware, Inc.
2 // SPDX-License-Identifier: BSD-2-Clause
3 //
4 // The BSD-2 license (the License) set forth below applies to all parts of the
5 // Cascade project.  You may not use this file except in compliance with the
6 // License.
7 //
8 // BSD-2 License
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are met:
12 //
13 // 1. Redistributions of source code must retain the above copyright notice, this
14 // list of conditions and the following disclaimer.
15 //
16 // 2. Redistributions in binary form must reproduce the above copyright notice,
17 // this list of conditions and the following disclaimer in the documentation
18 // and/or other materials provided with the distribution.
19 //
20 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND
21 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 #include "verilog/analyze/module_info.h"
32 
33 #include <unordered_set>
34 #include "verilog/ast/ast.h"
35 #include "verilog/analyze/read_set.h"
36 #include "verilog/analyze/resolve.h"
37 #include "verilog/program/elaborate.h"
38 #include "verilog/program/inline.h"
39 
40 using namespace std;
41 
42 namespace cascade {
43 
ModuleInfo(const ModuleDeclaration * md)44 ModuleInfo::ModuleInfo(const ModuleDeclaration* md) : Visitor() {
45   md_ = const_cast<ModuleDeclaration*>(md);
46   lhs_ = false;
47 }
48 
invalidate()49 void ModuleInfo::invalidate() {
50   if (md_->next_update_ == 0) {
51     return;
52   }
53 
54   // NOTE: It's important that we don't *just* call clear here. There's a
55   // potential for a pretty large soft-leak as we inline the user's program
56   // from leaf to root and each node's module info comes to encompass
57   // everything below it.
58 
59   md_->next_update_ = 0;
60   unordered_set<const Identifier*>().swap(md_->locals_);
61   unordered_set<const Identifier*>().swap(md_->inputs_);
62   unordered_set<const Identifier*>().swap(md_->outputs_);
63   unordered_set<const Identifier*>().swap(md_->stateful_);
64   unordered_set<const Identifier*>().swap(md_->implied_wires_);
65   unordered_set<const Identifier*>().swap(md_->implied_latches_);
66   unordered_set<const Identifier*>().swap(md_->reads_);
67   unordered_set<const Identifier*>().swap(md_->writes_);
68   ModuleDeclaration::ParamSet().swap(md_->named_params_);
69   Vector<const Identifier*>().swap(md_->ordered_params_);
70   ModuleDeclaration::PortSet().swap(md_->named_ports_);
71   Vector<const Identifier*>().swap(md_->ordered_ports_);
72   ModuleDeclaration::ConnMap().swap(md_->connections_);
73   ModuleDeclaration::ChildMap().swap(md_->children_);
74   md_->uses_mixed_triggers_ = false;
75   md_->clocks_ = 0;
76 }
77 
is_declaration()78 bool ModuleInfo::is_declaration() {
79   return md_->get_parent() == nullptr;
80 }
81 
is_instantiated()82 bool ModuleInfo::is_instantiated() {
83   return md_->get_parent() != nullptr;
84 }
85 
id()86 const Identifier* ModuleInfo::id() {
87   auto* p = md_->get_parent();
88   if (p == nullptr) {
89     return nullptr;
90   }
91   assert(p->is(Node::Tag::module_instantiation));
92   auto* mi = static_cast<ModuleInstantiation*>(p);
93   return mi->get_iid();
94 }
95 
is_local(const Identifier * id)96 bool ModuleInfo::is_local(const Identifier* id) {
97   refresh();
98   const auto* r = Resolve().get_resolution(id);
99   return (r == nullptr) ? false : (md_->locals_.find(r) != md_->locals_.end());
100 }
101 
is_input(const Identifier * id)102 bool ModuleInfo::is_input(const Identifier* id) {
103   refresh();
104   const auto* r = Resolve().get_resolution(id);
105   return (r == nullptr) ? false : (md_->inputs_.find(r) != md_->inputs_.end());
106 }
107 
is_stateful(const Identifier * id)108 bool ModuleInfo::is_stateful(const Identifier* id) {
109   refresh();
110   const auto* r = Resolve().get_resolution(id);
111   return (r == nullptr) ? false : (md_->stateful_.find(r) != md_->stateful_.end());
112 }
113 
is_implied_wire(const Identifier * id)114 bool ModuleInfo::is_implied_wire(const Identifier* id) {
115   refresh();
116   const auto* r = Resolve().get_resolution(id);
117   return (r == nullptr) ? false : (md_->implied_wires_.find(r) != md_->implied_wires_.end());
118 }
119 
is_implied_latch(const Identifier * id)120 bool ModuleInfo::is_implied_latch(const Identifier* id) {
121   refresh();
122   const auto* r = Resolve().get_resolution(id);
123   return (r == nullptr) ? false : (md_->implied_latches_.find(r) != md_->implied_latches_.end());
124 }
125 
is_output(const Identifier * id)126 bool ModuleInfo::is_output(const Identifier* id) {
127   refresh();
128   const auto* r = Resolve().get_resolution(id);
129   return (r == nullptr) ? false : (md_->outputs_.find(r) != md_->outputs_.end());
130 }
131 
is_read(const Identifier * id)132 bool ModuleInfo::is_read(const Identifier* id) {
133   refresh();
134   const auto* r = Resolve().get_resolution(id);
135   return (r == nullptr) ? false : (md_->reads_.find(r) != md_->reads_.end());
136 }
137 
is_write(const Identifier * id)138 bool ModuleInfo::is_write(const Identifier* id) {
139   refresh();
140   const auto* r = Resolve().get_resolution(id);
141   return (r == nullptr) ? false : (md_->writes_.find(r) != md_->writes_.end());
142 }
143 
is_child(const Identifier * id)144 bool ModuleInfo::is_child(const Identifier* id) {
145   refresh();
146   const auto* r = Resolve().get_resolution(id);
147   return (r == nullptr) ? false : (md_->children_.find(r) != md_->children_.end());
148 }
149 
uses_mixed_triggers()150 bool ModuleInfo::uses_mixed_triggers() {
151   refresh();
152   return md_->uses_mixed_triggers_;
153 }
154 
uses_multiple_clocks()155 bool ModuleInfo::uses_multiple_clocks() {
156   refresh();
157   return md_->clocks_ > 1;
158 }
159 
locals()160 const unordered_set<const Identifier*>& ModuleInfo::locals() {
161   refresh();
162   return md_->locals_;
163 }
164 
inputs()165 const unordered_set<const Identifier*>& ModuleInfo::inputs() {
166   refresh();
167   return md_->inputs_;
168 }
169 
outputs()170 const unordered_set<const Identifier*>& ModuleInfo::outputs() {
171   refresh();
172   return md_->outputs_;
173 }
174 
stateful()175 const unordered_set<const Identifier*>& ModuleInfo::stateful() {
176   refresh();
177   return md_->stateful_;
178 }
179 
implied_wires()180 const unordered_set<const Identifier*>& ModuleInfo::implied_wires() {
181   refresh();
182   return md_->implied_wires_;
183 }
184 
implied_latches()185 const unordered_set<const Identifier*>& ModuleInfo::implied_latches() {
186   refresh();
187   return md_->implied_latches_;
188 }
189 
reads()190 const unordered_set<const Identifier*>& ModuleInfo::reads() {
191   refresh();
192   return md_->reads_;
193 }
194 
writes()195 const unordered_set<const Identifier*>& ModuleInfo::writes() {
196   refresh();
197   return md_->writes_;
198 }
199 
children()200 const unordered_map<const Identifier*, const ModuleDeclaration*>& ModuleInfo::children() {
201   refresh();
202   return md_->children_;
203 }
204 
named_params()205 const unordered_set<const Identifier*, HashId, EqId>& ModuleInfo::named_params() {
206   refresh();
207   return md_->named_params_;
208 }
209 
ordered_params()210 const Vector<const Identifier*>& ModuleInfo::ordered_params() {
211   refresh();
212   return md_->ordered_params_;
213 }
214 
named_ports()215 const unordered_set<const Identifier*, HashId, EqId>& ModuleInfo::named_ports() {
216   refresh();
217   return md_->named_ports_;
218 }
219 
ordered_ports()220 const Vector<const Identifier*>& ModuleInfo::ordered_ports() {
221   refresh();
222   return md_->ordered_ports_;
223 }
224 
connections()225 const unordered_map<const Identifier*, unordered_map<const Identifier*, const Expression*>>& ModuleInfo::connections() {
226   refresh();
227   return md_->connections_;
228 }
229 
named_parent_conn(const ModuleInstantiation * mi,const PortDeclaration * pd)230 void ModuleInfo::named_parent_conn(const ModuleInstantiation* mi, const PortDeclaration* pd) {
231   for (auto i = mi->begin_ports(), ie = mi->end_ports(); i != ie; ++i) {
232     // This is a named connection, so explicit port should never be null.
233     // Typechecking should enforce this.
234     assert((*i)->is_non_null_exp());
235     // Nothing to do for an empty named connection
236     if ((*i)->is_null_imp()) {
237       continue;
238     }
239     // Nothing to do if this isn't the right port
240     const auto* r = Resolve().get_resolution((*i)->get_exp());
241     if (r != pd->get_decl()->get_id()) {
242       continue;
243     }
244 
245     // Flag this variable as either a read or a write and return
246     switch (pd->get_type()) {
247       case PortDeclaration::Type::INPUT:
248         record_local_write(r);
249         return;
250       case PortDeclaration::Type::OUTPUT:
251         record_local_read(r);
252         return;
253       default:
254         record_local_read(r);
255         record_local_write(r);
256         return;
257     }
258   }
259 }
260 
ordered_parent_conn(const ModuleInstantiation * mi,const PortDeclaration * pd,size_t idx)261 void ModuleInfo::ordered_parent_conn(const ModuleInstantiation* mi, const PortDeclaration* pd, size_t idx) {
262   // Do nothing if this port doesn't appear in mi's port list
263   if (idx >= mi->size_ports()) {
264     return;
265   }
266   auto* p = mi->get_ports(idx);
267 
268   // This is an ordered connection, so explicit port should always be null.
269   // Typechecking should enforce this.
270   assert(p->is_null_exp());
271   // Nothing to do for an empty ordered connection
272   if (p->is_null_imp()) {
273     return;
274   }
275 
276   // Flag this variable as either a read or a write
277   const auto* r = pd->get_decl()->get_id();
278   switch (pd->get_type()) {
279     case PortDeclaration::Type::INPUT:
280       record_local_write(r);
281       break;
282     case PortDeclaration::Type::OUTPUT:
283       record_local_read(r);
284       break;
285     default:
286       record_local_read(r);
287       record_local_write(r);
288       break;
289   }
290 }
291 
named_child_conns(const ModuleInstantiation * mi)292 void ModuleInfo::named_child_conns(const ModuleInstantiation* mi) {
293   unordered_map<const Identifier*, const Expression*> conn;
294   for (auto i = mi->begin_ports(), ie = mi->end_ports(); i != ie; ++i) {
295     // This is a named connection, so explicit port should never be null.
296     // Typechecking should enforce this.
297     assert((*i)->is_non_null_exp());
298     // Nothing to do for an empty named connection
299     if ((*i)->is_null_imp()) {
300       continue;
301     }
302 
303     // Grab the declaration that this explicit port corresponds to
304     const auto* r = Resolve().get_resolution((*i)->get_exp());
305     assert(r != nullptr);
306     // Connect the variable tot he expression in this module
307     conn.insert(make_pair(r, (*i)->get_imp()));
308 
309     // Anything that appears in a module's port list must be declared as
310     // a port. Typechecking should enforce this.
311     assert(r->get_parent()->get_parent()->is(Node::Tag::port_declaration));
312     auto* pd = static_cast<const PortDeclaration*>(r->get_parent()->get_parent());
313 
314     switch (pd->get_type()) {
315       case PortDeclaration::Type::INPUT:
316         record_external_read(r);
317         break;
318       case PortDeclaration::Type::OUTPUT:
319         record_external_write(r);
320         break;
321       default:
322         record_external_read(r);
323         record_external_write(r);
324         break;
325     }
326   }
327   md_->connections_.insert(make_pair(mi->get_iid(), conn));
328 }
329 
ordered_child_conns(const ModuleInstantiation * mi)330 void ModuleInfo::ordered_child_conns(const ModuleInstantiation* mi) {
331   unordered_map<const Identifier*, const Expression*> conn;
332 
333   auto itr = Elaborate().get_elaboration(mi)->begin_items();
334   for (size_t i = 0, ie = mi->size_ports(); i < ie; ++i) {
335     const auto* p = mi->get_ports(i);
336     // This is an ordered connection, so explicit port should always be null.
337     // Typechecking should enforce this.
338     assert(p->is_null_exp());
339 
340     // Track to the first port declaration. It's kind of ugly to have to iterate
341     // over the entire text of this module every time we refresh, but it's the price
342     // we pay for not having to rely on its module info.
343     while (!(*itr)->is(Node::Tag::port_declaration)) {
344       ++itr;
345       assert(itr != Elaborate().get_elaboration(mi)->end_items());
346     }
347     // Anything that appears in a module's port list must be declared as
348     // a port. Typechecking should enforce this.
349     auto* pd = static_cast<const PortDeclaration*>(*itr++);
350 
351     // Nothing to do for an empty ordered connection
352     if (p->is_null_imp()) {
353       continue;
354     }
355 
356     // Grab the declaration that this port corresponds to
357     const auto* r = pd->get_decl()->get_id();
358     // Connect the variable to the expression in this module
359     conn.insert(make_pair(r, p->get_imp()));
360 
361     switch (pd->get_type()) {
362       case PortDeclaration::Type::INPUT:
363         record_external_read(r);
364         break;
365       case PortDeclaration::Type::OUTPUT:
366         record_external_write(r);
367         break;
368       default:
369         record_external_read(r);
370         record_external_write(r);
371         break;
372     }
373   }
374   md_->connections_.insert(make_pair(mi->get_iid(), conn));
375 }
376 
named_external_conn(const ModuleInstantiation * mi,const ArgAssign * aa,const Identifier * id)377 void ModuleInfo::named_external_conn(const ModuleInstantiation* mi, const ArgAssign* aa, const Identifier* id) {
378   // This method should never be called for an empty named connection
379   assert(aa->is_non_null_exp());
380 
381   // Grab the declaration that this explicit port corresponds to
382   const auto* r = Resolve().get_resolution(aa->get_exp());
383   assert(r != nullptr);
384 
385   // If this module hasn't been inlined, then we can extract the port type for
386   // this variable from its declaration
387   if (!Inline().is_inlined(mi)) {
388     assert(r->get_parent()->get_parent()->is(Node::Tag::port_declaration));
389     auto* pd = static_cast<const PortDeclaration*>(r->get_parent()->get_parent());
390 
391     switch (pd->get_type()) {
392       case PortDeclaration::Type::INPUT:
393         record_local_read(id);
394         break;
395       case PortDeclaration::Type::OUTPUT:
396         record_local_write(id);
397         break;
398       default:
399         record_local_read(id);
400         record_local_write(id);
401         break;
402     }
403   }
404   // Otherwise, we'll need to extract it from the inlining annotation we generated
405   else {
406     assert(r->get_parent()->is_subclass_of(Node::Tag::declaration));
407     auto* d = static_cast<const Declaration*>(r->get_parent());
408     const auto* inl = d->get_attrs()->get<String>("__inline");
409     assert(inl != nullptr);
410 
411     if (inl->eq("input")) {
412       record_local_read(id);
413     } else if (inl->eq("output")) {
414       record_local_write(id);
415     } else {
416       record_local_read(id);
417       record_local_write(id);
418     }
419   }
420 }
421 
ordered_external_conn(const ModuleInstantiation * mi,const ArgAssign * aa,const Identifier * id)422 void ModuleInfo::ordered_external_conn(const ModuleInstantiation* mi, const ArgAssign* aa, const Identifier* id) {
423   // Nothing to do for modules which haven't been elaborated yet.
424   if (!Elaborate().is_elaborated(mi)) {
425     return;
426   }
427   // If this module hasn't been inlined, we'll have to scan through its declarations one at a time
428   // to determine the type of this port connection
429   if (!Inline().is_inlined(mi)) {
430     auto itr = Elaborate().get_elaboration(mi)->begin_items();
431     for (size_t i = 0, ie = (*mi->find_ports(aa) - *mi->begin_ports()); i <= ie; ++i) {
432       while (!(*itr)->is(Node::Tag::port_declaration)) {
433         ++itr;
434         assert(itr != Elaborate().get_elaboration(mi)->end_items());
435       }
436       if (i != ie) {
437         ++itr;
438       }
439     }
440     const auto* pd = static_cast<const PortDeclaration*>(*itr);
441     switch (pd->get_type()) {
442       case PortDeclaration::Type::INPUT:
443         record_external_read(id);
444         break;
445       case PortDeclaration::Type::OUTPUT:
446         record_external_write(id);
447         break;
448       default:
449         record_external_read(id);
450         record_external_write(id);
451         break;
452     }
453   }
454   // Otherwise, we'll need to pick out port declarations by inspecting inlining annotations
455   else {
456     auto itr = Inline().get_source(mi)->front_clauses()->get_then()->begin_items();
457     for (size_t i = 0, ie = (*mi->find_ports(aa) - *mi->begin_ports()); i <= ie; ++i) {
458       while ((!(*itr)->is(Node::Tag::net_declaration) && !(*itr)->is(Node::Tag::reg_declaration)) ||
459              (static_cast<const Declaration*>(*itr)->get_attrs()->get<String>("__inline") == nullptr)) {
460         ++itr;
461         assert(itr != Inline().get_source(mi)->front_clauses()->get_then()->end_items());
462       }
463       if (i != ie) {
464         ++itr;
465       }
466     }
467     const auto* d = static_cast<const Declaration*>(*itr);
468     const auto* inl = d->get_attrs()->get<String>("__inline");
469     assert(inl != nullptr);
470 
471     if (inl->eq("input")) {
472       record_local_read(id);
473     } else if (inl->eq("output")) {
474       record_local_write(id);
475     } else {
476       record_local_read(id);
477       record_local_write(id);
478     }
479   }
480 }
481 
record_local_read(const Identifier * id)482 void ModuleInfo::record_local_read(const Identifier* id) {
483   if (md_->reads_.find(id) == md_->reads_.end()) {
484     md_->reads_.insert(id);
485   }
486 }
487 
record_external_read(const Identifier * id)488 void ModuleInfo::record_external_read(const Identifier* id) {
489   if (md_->reads_.find(id) == md_->reads_.end()) {
490     md_->reads_.insert(id);
491   }
492 }
493 
record_local_write(const Identifier * id)494 void ModuleInfo::record_local_write(const Identifier* id) {
495   if (md_->writes_.find(id) == md_->writes_.end()) {
496     md_->writes_.insert(id);
497   }
498 }
499 
record_external_write(const Identifier * id)500 void ModuleInfo::record_external_write(const Identifier* id) {
501   if (md_->writes_.find(id) == md_->writes_.end()) {
502     md_->writes_.insert(id);
503   }
504 }
505 
record_external_use(const Identifier * id)506 void ModuleInfo::record_external_use(const Identifier* id) {
507   for (auto i = Resolve().use_begin(id), ie = Resolve().use_end(id); i != ie; ++i) {
508     // Nothing to do for expressions which aren't identifiers
509     if (!(*i)->is(Node::Tag::identifier)) {
510       continue;
511     }
512     const auto* eid = static_cast<const Identifier*>(*i);
513     // Nothing to do if this variable appears in this module
514     if (Resolve().get_parent(eid) == md_) {
515       continue;
516     }
517 
518     // Grab a pointer to this identifier's parent
519     const auto* p = eid->get_parent();
520     assert(p != nullptr);
521     // Identifiers in ArgAssigns can be reads, writes, or neither
522     if (p->is(Node::Tag::arg_assign)) {
523       // Nothing to do if this is an explicit port
524       const auto* aa = static_cast<const ArgAssign*>(p);
525       if (aa->get_exp() == eid) {
526         continue;
527       }
528       const auto* pp = aa->get_parent();
529       assert(pp != nullptr);
530       // Nothing to do if this ArgAssign appears in a ModuleDeclaration
531       if (pp->is(Node::Tag::module_declaration)) {
532         continue;
533       }
534       if (pp->is(Node::Tag::module_instantiation)) {
535         const auto* mi = static_cast<const ModuleInstantiation*>(pp);
536         if (mi->find_params(aa) != mi->end_params()) {
537           record_local_read(id);
538         } else if (mi->uses_named_ports()) {
539           named_external_conn(mi, aa, id);
540         } else {
541           ordered_external_conn(mi, aa, id);
542         }
543       }
544     }
545     // Identifiers on the left hand side of VariableAssigns are writes Due to
546     // AST refactorings, we need to check the three types that used to contain
547     // VariableAssign's as well.
548     else if (p->is(Node::Tag::variable_assign) && static_cast<const VariableAssign*>(p)->get_lhs() == eid) {
549       record_local_write(id);
550     } else if (p->is(Node::Tag::continuous_assign) && static_cast<const ContinuousAssign*>(p)->get_lhs() == eid) {
551       record_local_write(id);
552     } else if (p->is(Node::Tag::blocking_assign) && static_cast<const BlockingAssign*>(p)->get_lhs() == eid) {
553       record_local_write(id);
554     } else if (p->is(Node::Tag::nonblocking_assign) && static_cast<const NonblockingAssign*>(p)->get_lhs() == eid) {
555       record_local_write(id);
556     }
557     // Everything else is a read
558     else {
559       record_local_read(id);
560     }
561   }
562 }
563 
visit(const Attributes * as)564 void ModuleInfo::visit(const Attributes* as) {
565   // Does nothing. There's nothing for us in here other than the opportunity to
566   // blow a ton of time looking up variables that we can't resolve.
567   (void) as;
568   return;
569 }
570 
visit(const Identifier * i)571 void ModuleInfo::visit(const Identifier* i) {
572   // Do nothing if this is a local or unresolvable variable
573   const auto* r = Resolve().get_resolution(i);
574   if (r == nullptr || (md_->locals_.find(r) != md_->locals_.end())) {
575     return;
576   }
577   // This variable must be external, record read/write
578   if (lhs_) {
579     record_external_read(r);
580   } else {
581     record_external_write(r);
582   }
583 }
584 
visit(const CaseGenerateConstruct * cgc)585 void ModuleInfo::visit(const CaseGenerateConstruct* cgc) {
586   cgc->accept_cond(this);
587   if (Elaborate().is_elaborated(cgc)) {
588     Elaborate().get_elaboration(cgc)->accept(this);
589   }
590 }
591 
visit(const IfGenerateConstruct * igc)592 void ModuleInfo::visit(const IfGenerateConstruct* igc) {
593   for (auto i = igc->begin_clauses(), ie = igc->end_clauses(); i != ie; ++i) {
594     (*i)->accept_if(this);
595   }
596   if (Elaborate().is_elaborated(igc)) {
597     Elaborate().get_elaboration(igc)->accept(this);
598   }
599 }
600 
visit(const LoopGenerateConstruct * lgc)601 void ModuleInfo::visit(const LoopGenerateConstruct* lgc) {
602   lgc->accept_init(this);
603   lgc->accept_cond(this);
604   lgc->accept_update(this);
605   if (Elaborate().is_elaborated(lgc)) {
606     for (auto* b : Elaborate().get_elaboration(lgc)) {
607       b->accept(this);
608     }
609   }
610 }
611 
visit(const ContinuousAssign * ca)612 void ModuleInfo::visit(const ContinuousAssign* ca) {
613   lhs_ = true;
614   ca->accept_lhs(this);
615   lhs_ = false;
616   ca->accept_rhs(this);
617 }
618 
visit(const GenvarDeclaration * gd)619 void ModuleInfo::visit(const GenvarDeclaration* gd) {
620   md_->locals_.insert(gd->get_id());
621   // Nothing external should reference this
622 }
623 
visit(const LocalparamDeclaration * ld)624 void ModuleInfo::visit(const LocalparamDeclaration* ld) {
625   md_->locals_.insert(ld->get_id());
626   record_external_use(ld->get_id());
627 }
628 
visit(const NetDeclaration * nd)629 void ModuleInfo::visit(const NetDeclaration* nd) {
630   md_->locals_.insert(nd->get_id());
631   record_external_use(nd->get_id());
632 }
633 
visit(const ParameterDeclaration * pd)634 void ModuleInfo::visit(const ParameterDeclaration* pd) {
635   md_->locals_.insert(pd->get_id());
636   md_->named_params_.insert(pd->get_id());
637   md_->ordered_params_.push_back(pd->get_id());
638   record_external_use(pd->get_id());
639 }
640 
visit(const RegDeclaration * rd)641 void ModuleInfo::visit(const RegDeclaration* rd) {
642   md_->locals_.insert(rd->get_id());
643   record_external_use(rd->get_id());
644 }
645 
visit(const ModuleInstantiation * mi)646 void ModuleInfo::visit(const ModuleInstantiation* mi) {
647   // This module has been inlined, continue descending through here rather than
648   // examine its connections.
649   if (Inline().is_inlined(mi)) {
650     return Inline().get_source(mi)->accept(this);
651   }
652 
653   // Descend on implicit ports. These are syntactically part of this module.
654   for (auto i = mi->begin_params(), ie = mi->end_params(); i != ie; ++i) {
655     (*i)->accept_imp(this);
656   }
657   for (auto i = mi->begin_ports(), ie = mi->end_ports(); i != ie; ++i) {
658     (*i)->accept_imp(this);
659   }
660 
661   // Nothing else to do if this module wasn't instantiated.
662   if (!Elaborate().is_elaborated(mi)) {
663     return;
664   }
665   // Otherwise, descend on port bindings to establish connections and record
666   // this child.
667   if (mi->uses_named_ports()) {
668     named_child_conns(mi);
669   } else {
670     ordered_child_conns(mi);
671   }
672   md_->children_.insert(make_pair(mi->get_iid(), Elaborate().get_elaboration(mi)));
673 }
674 
visit(const PortDeclaration * pd)675 void ModuleInfo::visit(const PortDeclaration* pd) {
676   // Record input or output port
677   switch(pd->get_type()) {
678     case PortDeclaration::Type::INPUT:
679       md_->inputs_.insert(pd->get_decl()->get_id());
680       break;
681     case PortDeclaration::Type::OUTPUT:
682       md_->outputs_.insert(pd->get_decl()->get_id());
683       break;
684     default:
685       md_->inputs_.insert(pd->get_decl()->get_id());
686       md_->outputs_.insert(pd->get_decl()->get_id());
687       break;
688   }
689   // Record port name and ordering information
690   md_->named_ports_.insert(pd->get_decl()->get_id());
691   md_->ordered_ports_.push_back(pd->get_decl()->get_id());
692 
693   // Descend on declaration
694   pd->accept_decl(this);
695 
696   // Nothing else to do if this is a declaration
697   if (is_declaration()) {
698     return;
699   }
700   // Otherwise, update read/write information for this connection
701   assert(md_->get_parent()->is(Node::Tag::module_instantiation));
702   auto* mi = static_cast<const ModuleInstantiation*>(md_->get_parent());
703   if (mi->uses_named_ports()) {
704     named_parent_conn(mi, pd);
705   } else {
706     ordered_parent_conn(mi, pd, md_->ordered_ports_.size()-1);
707   }
708 }
709 
visit(const BlockingAssign * ba)710 void ModuleInfo::visit(const BlockingAssign* ba) {
711   lhs_ = true;
712   ba->accept_lhs(this);
713   lhs_ = false;
714   ba->accept_rhs(this);
715 }
716 
visit(const NonblockingAssign * na)717 void ModuleInfo::visit(const NonblockingAssign* na) {
718   lhs_ = true;
719   na->accept_lhs(this);
720   lhs_ = false;
721   na->accept_rhs(this);
722 }
723 
visit(const VariableAssign * va)724 void ModuleInfo::visit(const VariableAssign* va) {
725   lhs_ = true;
726   va->accept_lhs(this);
727   lhs_ = false;
728   va->accept_rhs(this);
729 }
730 
visit(const EventControl * ec)731 void ModuleInfo::visit(const EventControl* ec) {
732   Visitor::visit(ec);
733 
734   // Check for the presence of both pos/neg edge and edge, and count clocks
735   auto edge = false;
736   auto var = false;
737   for (auto i = ec->begin_events(), ie = ec->end_events(); i != ie; ++i) {
738     switch ((*i)->get_type()) {
739       case Event::Type::POSEDGE:
740       case Event::Type::NEGEDGE:
741         ++md_->clocks_;
742         edge = true;
743         break;
744       case Event::Type::EDGE:
745         var = true;
746         break;
747       default:
748         assert(false);
749         break;
750     }
751   }
752   md_->uses_mixed_triggers_ = md_->uses_mixed_triggers_ || (edge && var);
753 }
754 
refresh()755 void ModuleInfo::refresh() {
756   const auto size = md_->size_items();
757   if (md_->next_update_ == size) {
758     return;
759   }
760 
761   for (; md_->next_update_ < size; ++md_->next_update_) {
762     md_->get_items(md_->next_update_)->accept(this);
763   }
764   for (auto* l : md_->locals_) {
765     if (!l->get_parent()->is(Node::Tag::reg_declaration)) {
766       continue;
767     }
768     switch (get_type(l)) {
769       case Type::REG:
770         md_->stateful_.insert(l);
771         break;
772       case Type::IMPLIED_WIRE:
773         md_->implied_wires_.insert(l);
774         break;
775       case Type::IMPLIED_LATCH:
776         md_->stateful_.insert(l);
777         md_->implied_latches_.insert(l);
778         break;
779       default:
780         assert(false);
781         break;
782     }
783   }
784 }
785 
get_type(const Identifier * id)786 ModuleInfo::Type ModuleInfo::get_type(const Identifier* id) {
787   assert(id->get_parent()->is(Node::Tag::reg_declaration));
788   const auto* rd = static_cast<const RegDeclaration*>(id->get_parent());
789 
790   // A register which is intiialized with an fopen can't be a wire
791   if (rd->is_non_null_val() && rd->get_val()->is(Node::Tag::fopen_expression)) {
792     return Type::REG;
793   }
794 
795   const TimingControlStatement* tcs_use = nullptr;
796   for (auto i = Resolve().use_begin(id), ie = Resolve().use_end(id); i != ie; ++i) {
797     if (!(*i)->is(Node::Tag::identifier)) {
798       continue;
799     }
800     const auto* id = static_cast<const Identifier*>(*i);
801 
802     switch(id->get_parent()->get_tag()) {
803       // Regs which appear in get statements can't be wires
804       case Node::Tag::get_statement:
805         if (static_cast<const GetStatement*>(id->get_parent())->get_var() == id) {
806           return Type::REG;
807         }
808         break;
809       // Anything which is the target of a non-blocking assignment can't be a wire
810       case Node::Tag::nonblocking_assign: {
811         const auto* na = static_cast<const NonblockingAssign*>(id->get_parent());
812         if (na->find_lhs(id) != na->end_lhs()) {
813           return Type::REG;
814         }
815         break;
816       }
817       // The hard case: variables which are the targets of blocking assigns
818       case Node::Tag::blocking_assign: {
819         const auto* ba = static_cast<const BlockingAssign*>(id->get_parent());
820         if (ba->find_lhs(id) == ba->end_lhs()) {
821           break;
822         }
823 
824         // Record the dependencies of this assignment
825         ReadSet rs1(ba->get_rhs());
826         unordered_set<const Expression*> deps(rs1.begin(), rs1.end());
827 
828         // Walk up the AST until we find the enclosing timing control
829         // statement.  Add dependencies from conditional and case statements.
830         const auto* n = ba->get_parent();
831         for (; !n->is(Node::Tag::timing_control_statement); n = n->get_parent()) {
832           if (n->is(Node::Tag::conditional_statement)) {
833             ReadSet rs2(static_cast<const ConditionalStatement*>(n)->get_if());
834             deps.insert(rs2.begin(), rs2.end());
835           } else if (n->is(Node::Tag::case_statement)) {
836             ReadSet rs3(static_cast<const CaseStatement*>(n)->get_cond());
837             deps.insert(rs3.begin(), rs3.end());
838           } else if (n->is(Node::Tag::initial_construct)) {
839             return Type::REG;
840           }
841         }
842         unordered_set<const Identifier*> id_deps;
843         for (const auto* d : deps) {
844           if (d->is(Node::Tag::identifier)) {
845             id_deps.insert(Resolve().get_resolution(static_cast<const Identifier*>(d)));
846           }
847         }
848         const auto* tcs = static_cast<const TimingControlStatement*>(n);
849         const auto* ec = static_cast<const EventControl*>(tcs->get_ctrl());
850 
851         // Walk along the event control and collect its triggers. If we see an
852         // edge trigger this can't be a wire.
853         unordered_set<const Identifier*> trigs;
854         for (auto j = ec->begin_events(), je = ec->end_events(); j != je; ++j) {
855           if ((*j)->get_type() != Event::Type::EDGE) {
856             return Type::REG;
857           }
858           if ((*j)->get_expr()->is(Node::Tag::identifier)) {
859             trigs.insert(Resolve().get_resolution(static_cast<const Identifier*>((*j)->get_expr())));
860           }
861         }
862 
863         // If we're here it's because this is a value-triggered block. If we've
864         // been to a different one already, or we depend on a value that doesn't
865         // appear in its trigger list, we can't be a register.
866         if ((tcs_use != nullptr) && (tcs != tcs_use)) {
867           return Type::IMPLIED_LATCH;
868         }
869         tcs_use = tcs;
870         for (const auto* d : id_deps) {
871           if (trigs.find(d) == trigs.end()) {
872             return Type::IMPLIED_LATCH;
873           }
874         }
875         break;
876       }
877       default:
878         break;
879     }
880   }
881 
882   // If control has reached here, and we saw at least one use of a wire-style
883   // assignment, then this is a wire. Otherwise, this is a register.
884   return (tcs_use != nullptr) ? Type::IMPLIED_WIRE : Type::REG;
885 }
886 
887 } // namespace cascade
888