forked from steveicarus/iverilog
-
Notifications
You must be signed in to change notification settings - Fork 1
/
netlist.h
3583 lines (2830 loc) · 100 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-2003 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
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: netlist.h,v 1.347 2005/07/14 23:34:19 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 "ivl_target.h"
# include "verinum.h"
# include "verireal.h"
# include "StringHeap.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 NetNet;
class NetNode;
class NetProc;
class NetProcTop;
class NetRelease;
class NetScope;
class NetEvProbe;
class NetExpr;
class NetESignal;
class NetFuncDef;
class NetRamDq;
class NetEvTrig;
class NetEvWait;
struct target;
struct functor_t;
ostream& operator << (ostream&o, ivl_variable_type_t val);
/* =========
* 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 Attrib, public virtual LineInfo {
public:
public:
// The name of the object must be a permallocated string. A
// lex_strings string, for example.
explicit NetObj(NetScope*s, perm_string n, unsigned npins);
virtual ~NetObj();
NetScope* scope();
const NetScope* scope() const;
perm_string 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; }
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_;
perm_string name_;
Link*pins_;
const unsigned npins_;
unsigned delay1_;
unsigned delay2_;
unsigned delay3_;
};
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(perm_string, unsigned inst =0);
perm_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 inst_ member is the index of the
// pin.
perm_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;
/* Get the width of the Nexus, or 0 if there are no vectors
(in the form of NetNet objects) linked. */
unsigned vector_width() const;
NetNet* pick_any_net();
/* This method returns true if all the possible drivers of
this nexus are constant. It will also return true if there
are no drivers at all. */
bool drivers_constant() const;
/* Given the nexus has constant drivers, this method returns
the value that has been driven. */
verinum::V driven_value() 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_;
enum VALUE { NO_GUESS, V0, V1, Vx, Vz, VAR };
mutable VALUE driven_;
private: // not implemented
Nexus(const Nexus&);
Nexus& operator= (const Nexus&);
};
class NexusSet {
public:
~NexusSet();
NexusSet();
unsigned count() const;
// Add the nexus to the set, if it is not already present.
void add(Nexus*that);
void add(const NexusSet&that);
// Remove the nexus from the set, if it is present.
void rem(Nexus*that);
void rem(const NexusSet&that);
Nexus* operator[] (unsigned idx) const;
// Return true if this set contains every nexus in that set.
bool contains(const NexusSet&that) const;
// Return true if this set contains any nexus in that set.
bool intersect(const NexusSet&that) const;
private:
Nexus**items_;
unsigned nitems_;
unsigned bsearch_(Nexus*that) const;
private: // not implemented
NexusSet(const NexusSet&);
NexusSet& operator= (const NexusSet&);
};
/*
* A NetBus is a transparent device that is merely a bunch of pins
* used to tie some pins to. It is a convenient way to collect a
* bundle of pins and pass that bundle around.
*/
class NetBus : public NetObj {
public:
NetBus(NetScope*scope, unsigned pin_count);
~NetBus();
private: // not implemented
NetBus(const NetBus&);
NetBus& operator= (const NetBus&);
};
/*
* 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:
// The name parameter must be a permallocated string.
explicit NetNode(NetScope*s, perm_string n, unsigned npins);
virtual ~NetNode();
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. Scalers and vectors are all the same thing here, a NetNet
* with a single pin. The difference between a scaler and vector is
* the video of the atomic vector datum it carries.
*
* NetNet objects can also appear as side effects of synthesis or
* other abstractions.
*
* Note that INTEGER types are an alias for a ``reg signed [31:0]''.
*
* 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.
*
* The pin 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:
enum Type { NONE, IMPLICIT, IMPLICIT_REG, INTEGER, WIRE, TRI, TRI1,
SUPPLY0, SUPPLY1, WAND, TRIAND, TRI0, WOR, TRIOR, REG,
WONE };
enum PortType { NOT_A_PORT, PIMPLICIT, PINPUT, POUTPUT, PINOUT };
// The width in this case is a shorthand for ms=width-1 and
// ls=0. Only one pin is created, the width is of the vector
// that passed through.
explicit NetNet(NetScope*s, perm_string n, Type t, unsigned width =1);
explicit NetNet(NetScope*s, perm_string n, Type t, long ms, long ls);
virtual ~NetNet();
Type type() const;
void type(Type t);
PortType port_type() const;
void port_type(PortType t);
ivl_variable_type_t data_type() const;
void data_type(ivl_variable_type_t 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);
/* Used to maintain original type of net since integers are
implemented as 'reg signed [31:0]' in Icarus */
bool get_isint() const;
void set_isint(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;
unsigned long vector_width() 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;
/* This method checks that the signed index is valid for this
signal. If it is, the above sb_to_idx can be used to get
the pin# from the index. */
bool sb_is_valid(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 peek_eref() const;
/* Assignment statements count their lrefs here. */
void incr_lref();
void decr_lref();
unsigned peek_lref() const;
unsigned get_refs() 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_;
ivl_variable_type_t data_type_;
bool signed_;
bool isint_; // original type of integer
long msb_, lsb_;
bool local_flag_;
unsigned eref_count_;
unsigned lref_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, perm_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();
Link& pin_DataB();
Link& pin_Result();
const Link& pin_Cout() const;
const Link& pin_DataA() const;
const Link& pin_DataB() const;
const Link& pin_Result() 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_;
};
/*
* This type represents the LPM_CLSHIFT device.
*/
class NetCLShift : public NetNode {
public:
NetCLShift(NetScope*s, perm_string n, unsigned width,
unsigned width_dist, bool right_flag, bool signed_flag);
~NetCLShift();
unsigned width() const;
unsigned width_dist() const;
bool right_flag() const;
bool signed_flag() const;
Link& pin_Data();
Link& pin_Result();
Link& pin_Distance();
const Link& pin_Data() const;
const Link& pin_Result() const;
const Link& pin_Distance() const;
virtual void dump_node(ostream&, unsigned ind) const;
virtual bool emit_node(struct target_t*) const;
private:
unsigned width_;
unsigned width_dist_;
bool right_flag_;
bool signed_flag_;
};
/*
* 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, perm_string n, unsigned width);
~NetCompare();
unsigned width() const;
bool get_signed() const;
void set_signed(bool);
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();
Link& pin_DataB();
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() const;
const Link& pin_DataB() 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_;
bool signed_flag_;
};
/*
* This node is a means to connect net inputs together to form a wider
* vector. The output (pin 0) is a concatenation of the input vectors,
* with pin-1 at the LSB, pin-2 next, and so on. This node is most
* like the NetLogic node, as it has one output at pin 0 and the
* remaining pins are the input that are combined to make the
* output. It is seperated out because it it generally a special case
* for the code generators.
*
* When constructing the node, the width is the vector_width of the
* output, and the cnt is the number of pins. (the number of input
* vectors.)
*/
class NetConcat : public NetNode {
public:
NetConcat(NetScope*scope, perm_string n, unsigned wid, unsigned cnt);
~NetConcat();
unsigned width() const;
void dump_node(ostream&, unsigned ind) const;
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, perm_string n,
unsigned width, unsigned wa, unsigned wb);
~NetDivide();
unsigned width_r() const;
unsigned width_a() const;
unsigned width_b() const;
void set_signed(bool);
bool get_signed() const;
Link& pin_DataA();
Link& pin_DataB();
Link& pin_Result();
const Link& pin_DataA() const;
const Link& pin_DataB() const;
const Link& pin_Result() 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_;
bool signed_flag_;
};
/*
* 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, perm_string n,
unsigned width, unsigned wa, unsigned wb);
~NetModulo();
unsigned width_r() const;
unsigned width_a() const;
unsigned width_b() const;
Link& pin_DataA();
Link& pin_DataB();
Link& pin_Result();
const Link& pin_DataA() const;
const Link& pin_DataB() const;
const Link& pin_Result() 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, perm_string n, unsigned vector_width);
~NetFF();
unsigned width() const;
Link& pin_Clock();
Link& pin_Enable();
Link& pin_Aset();
Link& pin_Aclr();
Link& pin_Sset();
Link& pin_Sclr();
Link& pin_Data();
Link& pin_Q();
const Link& pin_Clock() const;
const Link& pin_Enable() const;
const Link& pin_Aset() const;
const Link& pin_Aclr() const;
const Link& pin_Sset() const;
const Link& pin_Sclr() const;
const Link& pin_Data() const;
const Link& pin_Q() const;
void aset_value(const verinum&val);
const verinum& aset_value() const;
void sset_value(const verinum&val);
const verinum& sset_value() 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_;
verinum aset_value_;
verinum sset_value_;
};
/*
* 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, perm_string n, long w, long s, long e);
~NetMemory();
// This is the BASE name of the memory object. It does not
// include scope name, get that from the scope itself.
perm_string name() const;
// 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.
long index_to_address(long idx) const;
void dump(ostream&o, unsigned lm) const;
private:
perm_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 a basic LPM_MULT combinational multiplier. It
* is used as a structural representation of the * operator. The
* device has inputs A and B and output Result all with independent
* widths.
*
* NOTE: Check this width thing. I think that the independence of the
* widths is not necessary or even useful.
*/
class NetMult : public NetNode {
public:
NetMult(NetScope*sc, perm_string n, unsigned width,
unsigned wa, unsigned wb);
~NetMult();
bool get_signed() const;
void set_signed(bool);
// 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
Link& pin_DataA();
Link& pin_DataB();
Link& pin_Result();
const Link& pin_DataA() const;
const Link& pin_DataB() const;
const Link& pin_Result() 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:
bool signed_;
unsigned width_r_;
unsigned width_a_;
unsigned width_b_;
};
/*
* 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, perm_string n,
unsigned width, unsigned size, unsigned selw);
~NetMux();
unsigned width() const;
unsigned size() const;
unsigned sel_width() const;
Link& pin_Result();
Link& pin_Data(unsigned si);
Link& pin_Sel();
const Link& pin_Result() const;
const Link& pin_Data(unsigned) const;
const Link& pin_Sel() 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, perm_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();
Link& pin_Data();
Link& pin_Q();
const Link& pin_InClock() const;
const Link& pin_OutClock() const;
const Link& pin_WE() const;
const Link& pin_Address() const;
const Link& pin_Data() const;
const Link& pin_Q() 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_;
};
/*
* The NetReplicate node takes a vector input and makes it into a larger
* vector by repeating the input vector some number of times. The
* repeat count is a fixed value. This is just like the repeat
* concatenation of Verilog: {<repeat>{<vector>}}.
*
* When construction this node, the wid is the vector width of the
* output, and the rpt is the repeat count. The wid must be an even
* multiple of the cnt, and wid/cnt is the expected input width.
*
* The device has exacly 2 pins: pin(0) is the output and pin(1) the
* input.
*/
class NetReplicate : public NetNode {
public:
NetReplicate(NetScope*scope, perm_string n, unsigned wid, unsigned rpt);
~NetReplicate();
unsigned width() const;
unsigned repeat() const;
void dump_node(ostream&, unsigned ind) const;
bool emit_node(struct target_t*) const;
private:
unsigned width_;
unsigned repeat_;
};
/*
* This node represents the call of a user defined function in a
* structural context. The pin count is the same as the port count,
* with pin0 the return value.
*/
class NetUserFunc : public NetNode {
public:
NetUserFunc(NetScope*s, perm_string n, NetScope*def);
~NetUserFunc();