-
Notifications
You must be signed in to change notification settings - Fork 521
/
netlist.h
3007 lines (2349 loc) · 83.2 KB
/
netlist.h
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
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#ifndef __netlist_H
#define __netlist_H
/*
* Copyright (c) 1998-2002 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: netlist.h,v 1.235 2002/04/21 22:31:02 steve Exp $"
#endif
/*
* The netlist types, as described in this header file, are intended
* to be the output from elaboration of the source design. The design
* can be passed around in this form to the various stages and design
* processors.
*/
# include <string>
# include <map>
# include <list>
# include "verinum.h"
# include "HName.h"
# include "LineInfo.h"
# include "svector.h"
# include "Attrib.h"
#ifdef HAVE_IOSFWD
# include <iosfwd>
#else
class ostream;
#endif
class Design;
class Link;
class Nexus;
class NetNode;
class NetProc;
class NetProcTop;
class NetScope;
class NetExpr;
class NetESignal;
class NetFuncDef;
struct target;
struct functor_t;
/* =========
* A NetObj is anything that has any kind of behavior in the
* netlist. Nodes can be gates, registers, etc. and are linked
* together to form a design web.
*
* The web of nodes that makes up a circuit is held together by the
* Link class. There is a link for each pin. All mutually connected
* pins form a ring of links.
*
* A link can be INPUT, OUTPUT or PASSIVE. An input never drives the
* signal, and PASSIVE never receives the value of the signal. Wires
* are PASSIVE, for example.
*
* A NetObj also has delays specified as rise_time, fall_time and
* decay_time. The rise and fall time are the times to transition to 1
* or 0 values. The decay_time is the time needed to decay to a 'bz
* value, or to decay of the net is a trireg. The exact and precise
* interpretation of the rise/fall/decay times is typically left to
* the target to properly interpret.
*/
class NetObj {
public:
public:
explicit NetObj(NetScope*s, const string&n, unsigned npins);
explicit NetObj(NetScope*s, const char*n, unsigned npins);
virtual ~NetObj();
NetScope* scope();
const NetScope* scope() const;
const char* name() const { return name_; }
unsigned pin_count() const { return npins_; }
unsigned rise_time() const { return delay1_; }
unsigned fall_time() const { return delay2_; }
unsigned decay_time() const { return delay3_; }
void rise_time(unsigned d) { delay1_ = d; }
void fall_time(unsigned d) { delay2_ = d; }
void decay_time(unsigned d) { delay3_ = d; }
void set_attributes(const map<string,string>&);
string attribute(const string&key) const;
void attribute(const string&key, const string&value);
// Return true if this has all the attributes in that and they
// all have the same values.
bool has_compat_attributes(const NetObj&that) const;
unsigned nattr() const;
const char* attr_key(unsigned) const;
const char* attr_value(unsigned) const;
Link&pin(unsigned idx);
const Link&pin(unsigned idx) const;
void dump_node_pins(ostream&, unsigned) const;
void dump_obj_attr(ostream&, unsigned) const;
private:
NetScope*scope_;
char* name_;
Link*pins_;
const unsigned npins_;
unsigned delay1_;
unsigned delay2_;
unsigned delay3_;
Attrib attributes_;
};
class Link {
friend void connect(Link&, Link&);
friend void connect(Nexus*, Link&);
friend class NetObj;
friend class Nexus;
public:
enum DIR { PASSIVE, INPUT, OUTPUT };
enum strength_t { HIGHZ, WEAK, PULL, STRONG, SUPPLY };
Link();
~Link();
// Manipulate the link direction.
void set_dir(DIR d);
DIR get_dir() const;
// A link has a drive strength for 0 and 1 values. The drive0
// strength is for when the link has the value 0, and drive1
// strength is for when the link has a value 1.
void drive0(strength_t);
void drive1(strength_t);
strength_t drive0() const;
strength_t drive1() const;
// A link has an initial value that is used by the nexus to
// figure out its initial value. Normally, only the object
// that contains the link sets the initial value, and only the
// attached Nexus gets it. The default link value is Vx.
void set_init(verinum::V val);
verinum::V get_init() const;
void cur_link(NetObj*&net, unsigned &pin);
void cur_link(const NetObj*&net, unsigned &pin) const;
// Get a pointer to the nexus that represents all the links
// connected to me.
Nexus* nexus();
const Nexus* nexus()const;
// Return a pointer to the next link in the nexus.
Link* next_nlink();
const Link* next_nlink() const;
// Remove this link from the set of connected pins. The
// destructor will automatically do this if needed.
void unlink();
// Return true if this link is connected to anything else.
bool is_linked() const;
// Return true if these pins are connected.
bool is_linked(const Link&that) const;
// Return true if this is the same pin of the same object of
// that link.
bool is_equal(const Link&that) const;
// Return information about the object that this link is
// a part of.
const NetObj*get_obj() const;
NetObj*get_obj();
unsigned get_pin() const;
// A link of an object (sometimes called a "pin") has a
// name. It is convenient for the name to have a string and an
// integer part.
void set_name(const string&, unsigned inst =0);
const string& get_name() const;
unsigned get_inst() const;
private:
// The NetNode manages these. They point back to the
// NetNode so that following the links can get me here.
NetObj *node_;
unsigned pin_;
DIR dir_;
strength_t drive0_, drive1_;
verinum::V init_;
// These members name the pin of the link. If the name
// has width, then the ninst_ member is the index of the
// pin.
string name_;
unsigned inst_;
private:
Link *next_;
Nexus*nexus_;
private: // not implemented
Link(const Link&);
Link& operator= (const Link&);
};
/*
* The Nexus represents a collection of links that are joined
* together. Each link has its own properties, this class holds the
* properties of the group.
*
* The links in a nexus are grouped into a singly linked list, with
* the nexus pointing to the first Link. Each link in turn points to
* the next link in the nexus, with the last link pointing to 0.
*
* The t_cookie() is a void* that targets can use to store information
* in a Nexus. ivl guarantees that the t_cookie will be 0 when the
* target is invoked.
*/
class Nexus {
friend void connect(Link&, Link&);
friend void connect(Nexus*, Link&);
friend class Link;
public:
explicit Nexus();
~Nexus();
const char* name() const;
verinum::V get_init() const;
Link*first_nlink();
const Link* first_nlink()const;
void* t_cookie() const;
void* t_cookie(void*) const;
private:
Link*list_;
void unlink(Link*);
void relink(Link*);
mutable char* name_; /* Cache the calculated name for the Nexus. */
mutable void* t_cookie_;
private: // not implemented
Nexus(const Nexus&);
Nexus& operator= (const Nexus&);
};
class NexusSet {
public:
~NexusSet();
NexusSet();
unsigned count() const;
void add(Nexus*that);
void add(const NexusSet&that);
Nexus* operator[] (unsigned idx);
private:
Nexus**items_;
unsigned nitems_;
unsigned bsearch_(Nexus*that);
private: // not implemented
NexusSet(const NexusSet&);
NexusSet& operator= (const NexusSet&);
};
/*
* A NetNode is a device of some sort, where each pin has a different
* meaning. (i.e. pin(0) is the output to an and gate.) NetNode
* objects are listed in the nodes_ of the Design object.
*/
class NetNode : public NetObj {
public:
explicit NetNode(NetScope*s, const string&n, unsigned npins);
explicit NetNode(NetScope*s, const char*n, unsigned npins);
virtual ~NetNode();
// This method locates the next node that has all its pins
// connected to the same of my own pins.
NetNode*next_node();
virtual bool emit_node(struct target_t*) const;
virtual void dump_node(ostream&, unsigned) const;
// This is used to scan a modifiable netlist, one node at a time.
virtual void functor_node(Design*, functor_t*);
private:
friend class Design;
NetNode*node_next_, *node_prev_;
Design*design_;
};
/*
* NetNet is a special kind of NetObj that doesn't really do anything,
* but carries the properties of the wire/reg/trireg, including its
* name. A scaler wire is a NetNet with one pin, a vector a wider
* NetNet. NetNet objects also appear as side effects of synthesis or
* other abstractions.
*
* Note that there are no INTEGER types. Express a verilog integer as
* a ``reg signed'' instead. The parser automatically does this for us.
*
* NetNet objects have a name and exist within a scope, so the
* constructor takes a pointer to the containing scope. The object
* automatically adds itself to the scope.
*
* NetNet objects are located by searching NetScope objects.
*
* All the pins of a NetNet object are PASSIVE: they do not drive
* anything and they are not a data sink, per se. The pins follow the
* values on the nexus.
*/
class NetNet : public NetObj, public LineInfo {
public:
enum Type { IMPLICIT, IMPLICIT_REG, WIRE, TRI, TRI1, SUPPLY0,
SUPPLY1, WAND, TRIAND, TRI0, WOR, TRIOR, REG };
enum PortType { NOT_A_PORT, PIMPLICIT, PINPUT, POUTPUT, PINOUT };
explicit NetNet(NetScope*s, const string&n, Type t, unsigned npins =1);
explicit NetNet(NetScope*s, const string&n, Type t, long ms, long ls);
virtual ~NetNet();
Type type() const;
PortType port_type() const;
void port_type(PortType t);
/* If a NetNet is signed, then its value is to be treated as
signed. Otherwise, it is unsigned. */
bool get_signed() const;
void set_signed(bool);
/* These methods return the msb and lsb indices for the most
significant and least significant bits. These are signed
longs, and may be different from pin numbers. For example,
reg [1:8] has 8 bits, msb==1 and lsb==8. */
long msb() const;
long lsb() const;
/* This method converts a signed index (the type that might be
found in the verilog source) to a pin number. It accounts
for variation in the definition of the reg/wire/whatever. */
unsigned sb_to_idx(long sb) const;
bool local_flag() const { return local_flag_; }
void local_flag(bool f) { local_flag_ = f; }
/* NetESignal objects may reference this object. Keep a
reference count so that I keep track of them. */
void incr_eref();
void decr_eref();
unsigned get_eref() const;
virtual void dump_net(ostream&, unsigned) const;
private:
// The NetScope class uses this for listing signals.
friend class NetScope;
NetNet*sig_next_, *sig_prev_;
private:
Type type_;
PortType port_type_;
bool signed_;
long msb_, lsb_;
bool local_flag_;
unsigned eref_count_;
};
/*
* This class implements the LPM_ADD_SUB component as described in the
* EDIF LPM Version 2 1 0 standard. It is used as a structural
* implementation of the + and - operators.
*/
class NetAddSub : public NetNode {
public:
NetAddSub(NetScope*s, const string&n, unsigned width);
~NetAddSub();
// Get the width of the device (that is, the width of the
// operands and results.)
unsigned width() const;
Link& pin_Aclr();
Link& pin_Add_Sub();
Link& pin_Clock();
Link& pin_Cin();
Link& pin_Cout();
Link& pin_Overflow();
Link& pin_DataA(unsigned idx);
Link& pin_DataB(unsigned idx);
Link& pin_Result(unsigned idx);
const Link& pin_Cout() const;
const Link& pin_DataA(unsigned idx) const;
const Link& pin_DataB(unsigned idx) const;
const Link& pin_Result(unsigned idx) const;
virtual void dump_node(ostream&, unsigned ind) const;
virtual bool emit_node(struct target_t*) const;
virtual void functor_node(Design*des, functor_t*fun);
};
/*
* This type represents the LPM_CLSHIFT device.
*/
class NetCLShift : public NetNode {
public:
NetCLShift(NetScope*s, const string&n, unsigned width,
unsigned width_dist);
~NetCLShift();
unsigned width() const;
unsigned width_dist() const;
Link& pin_Direction();
Link& pin_Underflow();
Link& pin_Overflow();
Link& pin_Data(unsigned idx);
Link& pin_Result(unsigned idx);
Link& pin_Distance(unsigned idx);
const Link& pin_Direction() const;
const Link& pin_Underflow() const;
const Link& pin_Overflow() const;
const Link& pin_Data(unsigned idx) const;
const Link& pin_Result(unsigned idx) const;
const Link& pin_Distance(unsigned idx) const;
virtual void dump_node(ostream&, unsigned ind) const;
virtual bool emit_node(struct target_t*) const;
private:
unsigned width_;
unsigned width_dist_;
};
/*
* This class supports the LPM_COMPARE device.
*
* The width of the device is the width of the inputs. If one of the
* inputs is narrower then the other, it is up to the generator to
* make sure all the data pins are properly driven.
*
* NOTE: This is not the same as the device used to support case
* compare. Case comparisons handle Vx and Vz values, whereas this
* device need not.
*/
class NetCompare : public NetNode {
public:
NetCompare(NetScope*scope, const string&n, unsigned width);
~NetCompare();
unsigned width() const;
Link& pin_Aclr();
Link& pin_Clock();
Link& pin_AGB();
Link& pin_AGEB();
Link& pin_AEB();
Link& pin_ANEB();
Link& pin_ALB();
Link& pin_ALEB();
Link& pin_DataA(unsigned idx);
Link& pin_DataB(unsigned idx);
const Link& pin_Aclr() const;
const Link& pin_Clock() const;
const Link& pin_AGB() const;
const Link& pin_AGEB() const;
const Link& pin_AEB() const;
const Link& pin_ANEB() const;
const Link& pin_ALB() const;
const Link& pin_ALEB() const;
const Link& pin_DataA(unsigned idx) const;
const Link& pin_DataB(unsigned idx) const;
virtual void functor_node(Design*, functor_t*);
virtual void dump_node(ostream&, unsigned ind) const;
virtual bool emit_node(struct target_t*) const;
private:
unsigned width_;
};
/*
* This class represents a theoretical (though not necessarily
* practical) integer divider gate. This is not to represent any real
* hardware, but to support the / operator in Verilog, when it shows
* up in structural contexts.
*
* The operands of the operation are the DataA<i> and DataB<i> inputs,
* and the Result<i> output reflects the value DataA/DataB.
*/
class NetDivide : public NetNode {
public:
NetDivide(NetScope*scope, const string&n,
unsigned width, unsigned wa, unsigned wb);
~NetDivide();
unsigned width_r() const;
unsigned width_a() const;
unsigned width_b() const;
Link& pin_DataA(unsigned idx);
Link& pin_DataB(unsigned idx);
Link& pin_Result(unsigned idx);
const Link& pin_DataA(unsigned idx) const;
const Link& pin_DataB(unsigned idx) const;
const Link& pin_Result(unsigned idx) const;
virtual void dump_node(ostream&, unsigned ind) const;
virtual bool emit_node(struct target_t*) const;
virtual void functor_node(Design*des, functor_t*fun);
private:
unsigned width_r_;
unsigned width_a_;
unsigned width_b_;
};
/*
* This class represents a theoretical (though not necessarily
* practical) integer modulo gate. This is not to represent any real
* hardware, but to support the % operator in Verilog, when it shows
* up in structural contexts.
*
* The operands of the operation are the DataA<i> and DataB<i> inputs,
* and the Result<i> output reflects the value DataA%DataB.
*/
class NetModulo : public NetNode {
public:
NetModulo(NetScope*s, const string&n,
unsigned width, unsigned wa, unsigned wb);
~NetModulo();
unsigned width_r() const;
unsigned width_a() const;
unsigned width_b() const;
Link& pin_DataA(unsigned idx);
Link& pin_DataB(unsigned idx);
Link& pin_Result(unsigned idx);
const Link& pin_DataA(unsigned idx) const;
const Link& pin_DataB(unsigned idx) const;
const Link& pin_Result(unsigned idx) const;
virtual void dump_node(ostream&, unsigned ind) const;
virtual bool emit_node(struct target_t*) const;
virtual void functor_node(Design*des, functor_t*fun);
private:
unsigned width_r_;
unsigned width_a_;
unsigned width_b_;
};
/*
* This class represents an LPM_FF device. There is no literal gate
* type in Verilog that maps, but gates of this type can be inferred.
*/
class NetFF : public NetNode {
public:
NetFF(NetScope*s, const char*n, unsigned width);
~NetFF();
unsigned width() const;
Link& pin_Clock();
Link& pin_Enable();
Link& pin_Aload();
Link& pin_Aset();
Link& pin_Aclr();
Link& pin_Sload();
Link& pin_Sset();
Link& pin_Sclr();
Link& pin_Data(unsigned);
Link& pin_Q(unsigned);
const Link& pin_Clock() const;
const Link& pin_Enable() const;
const Link& pin_Data(unsigned) const;
const Link& pin_Q(unsigned) const;
virtual void dump_node(ostream&, unsigned ind) const;
virtual bool emit_node(struct target_t*) const;
virtual void functor_node(Design*des, functor_t*fun);
};
/*
* This class represents the declared memory object. The parser
* creates one of these for each declared memory in the elaborated
* design. A reference to one of these is handled by the NetEMemory
* object, which is derived from NetExpr. This is not a node because
* memory objects can only be accessed by behavioral code.
*/
class NetMemory {
public:
NetMemory(NetScope*sc, const string&n, long w, long s, long e);
~NetMemory();
const string&name() const { return name_; }
// This is the width (in bits) of a single memory position.
unsigned width() const { return width_; }
// NetScope*scope();
const NetScope*scope() const { return scope_; };
// This is the number of memory positions.
unsigned count() const;
// This method returns a 0 based address of a memory entry as
// indexed by idx. The Verilog source may give index ranges
// that are not zero based.
unsigned index_to_address(long idx) const;
void dump(ostream&o, unsigned lm) const;
private:
string name_;
unsigned width_;
long idxh_;
long idxl_;
friend class NetRamDq;
NetRamDq* ram_list_;
friend class NetScope;
NetMemory*snext_, *sprev_;
NetScope*scope_;
private: // not implemented
NetMemory(const NetMemory&);
NetMemory& operator= (const NetMemory&);
};
/*
* This class implements the LPM_MULT component as described in the
* EDIF LPM Version 2 1 0 standard. It is used as a structural
* implementation of the * operator. The device has inputs DataA and
* DataB that can have independent widths, as can the result. If the
* result is smaller then the widths of a and b together, then the
* device drops the least significant bits of the product.
*/
class NetMult : public NetNode {
public:
NetMult(NetScope*sc, const string&n, unsigned width,
unsigned wa, unsigned wb, unsigned width_s =0);
~NetMult();
// Get the width of the device bussed inputs. There are these
// parameterized widths:
unsigned width_r() const; // Result
unsigned width_a() const; // DataA
unsigned width_b() const; // DataB
unsigned width_s() const; // Sum (my be 0)
Link& pin_Aclr();
Link& pin_Clock();
Link& pin_DataA(unsigned idx);
Link& pin_DataB(unsigned idx);
Link& pin_Result(unsigned idx);
Link& pin_Sum(unsigned idx);
const Link& pin_Aclr() const;
const Link& pin_Clock() const;
const Link& pin_DataA(unsigned idx) const;
const Link& pin_DataB(unsigned idx) const;
const Link& pin_Result(unsigned idx) const;
const Link& pin_Sum(unsigned idx) const;
virtual void dump_node(ostream&, unsigned ind) const;
virtual bool emit_node(struct target_t*) const;
virtual void functor_node(Design*des, functor_t*fun);
private:
unsigned width_r_;
unsigned width_a_;
unsigned width_b_;
unsigned width_s_;
};
/*
* This class represents an LPM_MUX device. This device has some
* number of Result points (the width of the device) and some number
* of input choices. There is also a selector of some width. The
* parameters are:
*
* width -- Width of the result and each possible Data input
* size -- Number of Data input (each of width)
* selw -- Width in bits of the select input
*/
class NetMux : public NetNode {
public:
NetMux(NetScope*scope, const string&n,
unsigned width, unsigned size, unsigned selw);
~NetMux();
unsigned width() const;
unsigned size() const;
unsigned sel_width() const;
Link& pin_Aclr();
Link& pin_Clock();
Link& pin_Result(unsigned);
Link& pin_Data(unsigned wi, unsigned si);
Link& pin_Sel(unsigned);
const Link& pin_Aclr() const;
const Link& pin_Clock() const;
const Link& pin_Result(unsigned) const;
const Link& pin_Data(unsigned, unsigned) const;
const Link& pin_Sel(unsigned) const;
virtual void dump_node(ostream&, unsigned ind) const;
virtual bool emit_node(struct target_t*) const;
virtual void functor_node(Design*des, functor_t*fun);
private:
unsigned width_;
unsigned size_;
unsigned swidth_;
};
/*
* This device represents an LPM_RAM_DQ device. The actual content is
* represented by a NetMemory object allocated elsewhere, but that
* object fixes the width and size of the device. The pin count of the
* address input is given in the constructor.
*/
class NetRamDq : public NetNode {
public:
NetRamDq(NetScope*s, const string&name, NetMemory*mem, unsigned awid);
~NetRamDq();
unsigned width() const;
unsigned awidth() const;
unsigned size() const;
const NetMemory*mem() const;
Link& pin_InClock();
Link& pin_OutClock();
Link& pin_WE();
Link& pin_Address(unsigned idx);
Link& pin_Data(unsigned idx);
Link& pin_Q(unsigned idx);
const Link& pin_InClock() const;
const Link& pin_OutClock() const;
const Link& pin_WE() const;
const Link& pin_Address(unsigned idx) const;
const Link& pin_Data(unsigned idx) const;
const Link& pin_Q(unsigned idx) const;
virtual void dump_node(ostream&, unsigned ind) const;
virtual bool emit_node(struct target_t*) const;
// Use this method to absorb other NetRamDq objects that are
// connected to the same memory, and have compatible pin
// connections.
void absorb_partners();
// Use this method to count the partners (including myself)
// that are ports to the attached memory.
unsigned count_partners() const;
private:
NetMemory*mem_;
NetRamDq*next_;
unsigned awidth_;
};
/*
* This node represents the call of a user defined function in a
* structural context.
*/
class NetUserFunc : public NetNode {
public:
NetUserFunc(NetScope*s, const char*n, NetScope*def);
~NetUserFunc();
unsigned port_count() const;
unsigned port_width(unsigned port) const;
Link& port_pin(unsigned port, unsigned idx);
const NetScope* def() const;
virtual void dump_node(ostream&, unsigned ind) const;
virtual bool emit_node(struct target_t*) const;
private:
NetScope*def_;
};
/* =========
* There are cases where expressions need to be represented. The
* NetExpr class is the root of a heirarchy that serves that purpose.
*
* The expr_width() is the width of the expression, that accounts
* for the widths of the sub-expressions I might have. It is up to the
* derived classes to properly set the expr width, if need be. The
* set_width() method is used to compel an expression to have a
* certain width, and is used particulary when the expression is an
* rvalue in an assignment statement.
*/
class NetExpr : public LineInfo {
public:
explicit NetExpr(unsigned w =0);
virtual ~NetExpr() =0;
virtual void expr_scan(struct expr_scan_t*) const =0;
virtual void dump(ostream&) const;
// How wide am I?
unsigned expr_width() const { return width_; }
// Coerce the expression to have a specific width. If the
// coersion works, then return true. Otherwise, return false.
virtual bool set_width(unsigned);
// This method returns true if the expression is
// signed. Unsigned expressions return false.
bool has_sign() const;
void cast_signed(bool flag);
// This returns true if the expression has a definite
// width. This is generally true, but in some cases the
// expression is amorphous and desires a width from its
// environment. For example, 'd5 has indefinite width, but
// 5'd5 has a definite width.
// This method is only really used within concatenation
// expressions to check validity.
virtual bool has_width() const;
// This method evaluates the expression and returns an
// equivilent expression that is reduced as far as compile
// time knows how. Essentially, this is designed to fold
// constants.
virtual NetExpr*eval_tree();
// Make a duplicate of myself, and subexpressions if I have
// any. This is a deep copy operation.
virtual NetExpr*dup_expr() const =0;
// Get the Nexus that are the input to this
// expression. Normally this descends down to the reference to
// a signal that reads from its input.
virtual NexusSet* nex_input() =0;
// Return a version of myself that is structural. This is used
// for converting expressions to gates.
virtual NetNet*synthesize(Design*);
protected:
void expr_width(unsigned w) { width_ = w; }
private:
unsigned width_;
bool signed_flag_;
private: // not implemented
NetExpr(const NetExpr&);
NetExpr& operator=(const NetExpr&);
};
/*
* The expression constant is slightly special, and is sometimes
* returned from other classes that can be evaluated at compile
* time. This class represents constant values in expressions.
*/
class NetEConst : public NetExpr {
public:
explicit NetEConst(const verinum&val);
~NetEConst();
const verinum&value() const;
virtual bool set_width(unsigned w);
virtual bool has_width() const;
virtual void expr_scan(struct expr_scan_t*) const;
virtual void dump(ostream&) const;
virtual NetEConst* dup_expr() const;
virtual NetNet*synthesize(Design*);
virtual NexusSet* nex_input();
private:
verinum value_;
};
/*
* The NetTmp object is a network that is only used momentarily by
* elaboration to carry links around. A completed netlist should not
* have any of these within. This is a kind of wire, so it is NetNet
* type. The constructor for this class also marks the NetNet as
* local, so that it is not likely to suppress a real symbol.
*/
class NetTmp : public NetNet {
public:
explicit NetTmp(NetScope*s, const string&name, unsigned npins =1);
};
/*
* The NetBUFZ is a magic device that represents the continuous
* assign, with the output being the target register and the input
* the logic that feeds it. The netlist preserves the directional
* nature of that assignment with the BUFZ. The target may elide it if
* that makes sense for the technology.
*/
class NetBUFZ : public NetNode {
public:
explicit NetBUFZ(NetScope*s, const string&n);
~NetBUFZ();
virtual void dump_node(ostream&, unsigned ind) const;