File Coverage

blib/lib/Verilog/Netlist/Pin.pm
Criterion Covered Total %
statement 141 162 87.0
branch 49 76 64.4
condition 20 26 76.9
subroutine 22 26 84.6
pod 11 15 73.3
total 243 305 79.6


line stmt bran cond sub pod time code
1             # Verilog - Verilog Perl Interface
2             # See copyright, etc in below POD section.
3             ######################################################################
4              
5             package Verilog::Netlist::Pin;
6              
7 8     8   45 use Verilog::Netlist;
  8         13  
  8         199  
8 8     8   2576 use Verilog::Netlist::Port;
  8         18  
  8         336  
9 8     8   43 use Verilog::Netlist::Net;
  8         14  
  8         242  
10 8     8   2951 use Verilog::Netlist::Cell;
  8         18  
  8         298  
11 8     8   3172 use Verilog::Netlist::Module;
  8         22  
  8         380  
12 8     8   56 use Verilog::Netlist::Pin;
  8         15  
  8         138  
13 8     8   2962 use Verilog::Netlist::PinSelection;
  8         20  
  8         220  
14 8     8   44 use Verilog::Netlist::Subclass;
  8         14  
  8         313  
15 8     8   38 use vars qw($VERSION @ISA);
  8         22  
  8         260  
16 8     8   33 use strict;
  8         11  
  8         11640  
17             @ISA = qw(Verilog::Netlist::Pin::Struct
18             Verilog::Netlist::Subclass);
19              
20             $VERSION = '3.480';
21              
22             structs('_new_base',
23             'Verilog::Netlist::Pin::Struct'
24             =>[name => '$', #' # Pin connection
25             filename => '$', #' # Filename this came from
26             lineno => '$', #' # Linenumber this came from
27             userdata => '%', # User information
28             attributes => '%', #' # Misc attributes for systemperl or other processors
29             #
30             comment => '$', #' # Comment provided by user
31             _pinselects => '$', #' # Arrayref to Verilog::Netlist::PinSelections
32             portname => '$', #' # Port connection name
33             portnumber => '$', #' # Position of name in call
34             pinnamed => '$', #' # True if name assigned
35             cell => '$', #' # Cell reference
36             # below only after link()
37             _nets => '$', #' # Arrayref to references to connected nets
38             port => '$', #' # Port connection reference
39             # SystemPerl: below only after autos()
40             sp_autocreated => '$', #' # Created by auto()
41             # below by accessor computation
42             #module
43             #submod
44             ]);
45              
46             sub new {
47 851     851 0 1072 my $class = shift;
48 851         2742 my %params = (@_);
49 851 100       1448 if (defined $params{netname}) {
    50          
50             # handle legacy constructor parameter "netname"
51 843         2156 $params{_pinselects} = [new Verilog::Netlist::PinSelection($params{netname})];
52 843         1342 delete $params{netname};
53             } elsif (defined $params{pinselects}) {
54             # remap pinselects to _pinselects
55 8         10 foreach my $pinselect (@{$params{pinselects}}) {
  8         18  
56 9         37 push @{$params{_pinselects}},
57             new Verilog::Netlist::PinSelection($pinselect->{netname},
58             $pinselect->{msb},
59 9         8 $pinselect->{lsb});
60             }
61 8         17 delete $params{pinselects};
62             }
63 851         14236 return $class->_new_base(%params);
64             }
65              
66             sub delete {
67 806     806 1 888 my $self = shift;
68 806 100 100     1225 if ($self->nets && $self->port) {
69 5         6 foreach my $net ($self->nets) {
70 5 50       11 next unless $net->{net};
71 5         53 my $dir = $self->port->direction;
72 5 50       9 if ($dir eq 'in') {
    0          
    0          
73 5         13 $net->{net}->_used_in_dec();
74             } elsif ($dir eq 'out') {
75 0         0 $net->{net}->_used_out_dec();
76             } elsif ($dir eq 'inout') {
77 0         0 $net->{net}->_used_inout_dec();
78             }
79             }
80             }
81 806         8949 my $h = $self->cell->_pins;
82 806         8688 delete $h->{$self->name};
83 806         1551 return undef;
84             }
85              
86             ######################################################################
87             #### Methods
88              
89             # Legacy accessors
90             sub netname {
91 7 50   7 1 74 return undef if !defined($_[0]->_pinselects);
92 7         9 return @{$_[0]->_pinselects}[0]->{_netname};
  7         72  
93             }
94             sub net {
95 0     0 1 0 my $nets = $_[0]->_nets;
96 0 0       0 return undef if !defined($nets);
97 0 0       0 return undef if !@{$nets}[0];
  0         0  
98 0         0 return @{$nets}[0]->{net};
  0         0  
99             }
100              
101             # Standard accessors
102             sub nets {
103 951 100   951 1 10558 return [] if !defined($_[0]->_nets);
104 151         153 return (@{$_[0]->_nets});
  151         1507  
105             }
106             sub nets_sorted {
107 0 0   0 1 0 return [] if !defined($_[0]->_nets);
108 0         0 return (sort {$a->name cmp $b->name} (@{$_[0]->_nets}));
  0         0  
  0         0  
109             }
110             sub pinselects {
111 154 50   154 1 1663 return [] if !defined($_[0]->_pinselects);
112 154         160 return @{$_[0]->_pinselects};
  154         1544  
113             }
114             sub logger {
115 0     0 1 0 return $_[0]->netlist->logger;
116             }
117             sub module {
118 52     52 1 551 return $_[0]->cell->module;
119             }
120             sub submod {
121 61     61 0 648 return $_[0]->cell->submod;
122             }
123             sub netlist {
124 0     0 1 0 return $_[0]->cell->module->netlist;
125             }
126              
127             sub _link {
128 104     104   112 my $self = shift;
129             # Note this routine is HOT
130 104         103 my $change;
131 104 100       1126 if (!$self->_nets) {
132 51 50       585 if ($self->_pinselects) {
133 51         83 my @nets = ();
134 51         50 foreach my $pinselect (@{$self->_pinselects}) {
  51         514  
135 52         100 my $net = $self->module->find_net($pinselect->netname);
136 52 100       122 next if (!defined($net));
137 22         33 my ($msb, $lsb);
138             # if the parsed description includes a range, use that,
139             # else use the complete range of the underlying net.
140 22 100       51 if (defined($pinselect->msb)) {
141 3         7 $msb = $pinselect->msb;
142 3         9 $lsb = $pinselect->lsb;
143             } else {
144 19         239 $msb = $net->msb;
145 19         246 $lsb = $net->lsb;
146             }
147 22         82 push(@nets, {net => $net, msb => $msb, lsb => $lsb});
148             }
149 51         604 $self->_nets(\@nets);
150 51         77 $change = 1;
151             }
152             }
153 104 100       1124 if (!$self->port) {
154 59 100       106 if (my $submod = $self->submod) {
155 51         564 my $portname = $self->portname;
156 51 100 66     622 if ($portname && !$self->cell->byorder ) {
157 34         86 $self->port($submod->find_port($portname));
158 34         50 $change = 1;
159             }
160             else {
161 17         217 $self->port($submod->find_port_by_index($self->portnumber));
162             # changing name from pin# to actual port name
163 17 50       223 $self->name($self->port->name) if $self->port;
164 17         31 $change = 1;
165             }
166             }
167             }
168 104 100 66     743 if ($change && $self->_nets && $self->port) {
      100        
169 45         482 my $dir = $self->port->direction;
170 45         99 foreach my $net ($self->nets) {
171 18 50       53 next unless $net->{net};
172 18 100       41 if ($dir eq 'in') {
    50          
    0          
173 14         57 $net->{net}->_used_in_inc();
174             } elsif ($dir eq 'out') {
175 4         12 $net->{net}->_used_out_inc();
176             } elsif ($dir eq 'inout') {
177 0         0 $net->{net}->_used_inout_inc();
178             }
179             }
180             }
181             }
182              
183             sub type_match {
184 17     17 0 20 my $self = shift;
185             # We could check for specific types being OK, but nearly everything,
186             # reg/trireg/wire/wand etc/tri/ supply0|1 etc
187             # is allowed to connect with everything else, and we're not a lint tool...
188             # So, not: return $self->net->data_type eq $self->port->data_type;
189 17         37 return 1;
190             }
191              
192             sub lint {
193 40     40 1 42 my $self = shift;
194 40 50 66     410 if (!$self->port && $self->submod) {
195 0         0 $self->error($self,"Port not found in ",$self->submod->keyword," ",$self->submod->name,": ",$self->portname,"\n");
196             }
197 40 100 100     406 if ($self->port && $self->nets) {
198 17 50       32 if (!$self->type_match) {
199 0         0 my $nettype = $self->net->data_type;
200 0         0 my $porttype = $self->port->data_type;
201 0         0 $self->error("Port pin data type '$porttype' != Net data type '$nettype': "
202             ,$self->name,"\n");
203             }
204              
205 17         33 foreach my $net ($self->nets) {
206 17 100 66     218 next unless $net->{net} && $net->{net}->port;
207 6         70 my $portdir = $self->port->direction;
208 6         66 my $netdir = $net->{net}->port->direction;
209 6 50 66     35 if (($netdir eq "in" && $portdir eq "out")
210             #Legal: ($netdir eq "in" && $portdir eq "inout")
211             #Legal: ($netdir eq "out" && $portdir eq "inout")
212             ) {
213 0         0 $self->error("Port is ${portdir}put from submodule, but ${netdir}put from this module: "
214             ,$self->name,"\n");
215             #$self->cell->module->netlist->dump;
216             }
217             }
218             }
219             }
220              
221             sub verilog_text {
222 37     37 0 39 my $self = shift;
223 37         31 my $inst;
224 37 100       418 if ($self->port) { # Even if it was by position, after linking we can write it as if it's by name.
    50          
225 34         351 $inst = ".".$self->port->name."(";
226             } elsif ($self->pinnamed) {
227 3         38 $inst = ".".$self->name."(";
228             } else { # not by name, and unlinked
229 0         0 $inst = ".".$self->portname."(";
230             }
231 37         78 my $net_cnt = $self->pinselects;
232 37 100       75 if ($net_cnt >= 2) {
    50          
233 1         2 $inst .= "{";
234 1         2 my $comma = "";
235 1         3 foreach my $pinselect (reverse($self->pinselects)) {
236 2         3 $inst .= $comma;
237 2         4 $inst .= $pinselect->bracketed_msb_lsb;
238 2         4 $comma = ",";
239             }
240 1         2 $inst .= "}";
241             } elsif ($net_cnt == 1) {
242 36         50 my @tmp = $self->pinselects;
243 36         79 $inst .= $tmp[0]->bracketed_msb_lsb;
244             }
245              
246 37         72 $inst .= ")";
247 37         77 return $inst;
248             }
249              
250             sub dump {
251 40     40 1 46 my $self = shift;
252 40   50     58 my $indent = shift||0;
253 40         85 my $net_cnt = $self->pinselects;
254 40         461 my $out = " "x$indent."Pin:".$self->name;
255 40 100       72 $out .= ($net_cnt > 1) ? " Nets:" : " Net:";
256 40         41 my $comma = "";
257 40         72 foreach my $pinselect (reverse($self->pinselects)) {
258 41         47 $out .= $comma;
259 41         97 $out .= $pinselect->bracketed_msb_lsb;
260 41         59 $comma = ",";
261             }
262 40         720 print "$out\n";
263 40 100       725 if ($self->port) {
264 37         389 $self->port->dump($indent+10, 'norecurse');
265             }
266 40         151 foreach my $net ($self->nets) {
267 18 50       39 next unless $net->{net};
268 18         50 $net->{net}->dump($indent+10, 'norecurse');
269             }
270             }
271              
272             ######################################################################
273             #### Package return
274             1;
275             __END__