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   58 use Verilog::Netlist;
  8         17  
  8         239  
8 8     8   3423 use Verilog::Netlist::Port;
  8         28  
  8         406  
9 8     8   72 use Verilog::Netlist::Net;
  8         18  
  8         250  
10 8     8   4065 use Verilog::Netlist::Cell;
  8         25  
  8         400  
11 8     8   4666 use Verilog::Netlist::Module;
  8         29  
  8         511  
12 8     8   83 use Verilog::Netlist::Pin;
  8         18  
  8         175  
13 8     8   4140 use Verilog::Netlist::PinSelection;
  8         22  
  8         270  
14 8     8   54 use Verilog::Netlist::Subclass;
  8         17  
  8         419  
15 8     8   48 use vars qw($VERSION @ISA);
  8         15  
  8         331  
16 8     8   41 use strict;
  8         14  
  8         13919  
17             @ISA = qw(Verilog::Netlist::Pin::Struct
18             Verilog::Netlist::Subclass);
19              
20             $VERSION = '3.478';
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 1177 my $class = shift;
48 851         3326 my %params = (@_);
49 851 100       1746 if (defined $params{netname}) {
    50          
50             # handle legacy constructor parameter "netname"
51 843         3210 $params{_pinselects} = [new Verilog::Netlist::PinSelection($params{netname})];
52 843         1655 delete $params{netname};
53             } elsif (defined $params{pinselects}) {
54             # remap pinselects to _pinselects
55 8         11 foreach my $pinselect (@{$params{pinselects}}) {
  8         22  
56 9         50 push @{$params{_pinselects}},
57             new Verilog::Netlist::PinSelection($pinselect->{netname},
58             $pinselect->{msb},
59 9         13 $pinselect->{lsb});
60             }
61 8         17 delete $params{pinselects};
62             }
63 851         17130 return $class->_new_base(%params);
64             }
65              
66             sub delete {
67 806     806 1 999 my $self = shift;
68 806 100 100     1516 if ($self->nets && $self->port) {
69 5         10 foreach my $net ($self->nets) {
70 5 50       13 next unless $net->{net};
71 5         96 my $dir = $self->port->direction;
72 5 50       56 if ($dir eq 'in') {
    0          
    0          
73 5         18 $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         10529 my $h = $self->cell->_pins;
82 806         10102 delete $h->{$self->name};
83 806         1669 return undef;
84             }
85              
86             ######################################################################
87             #### Methods
88              
89             # Legacy accessors
90             sub netname {
91 7 50   7 1 104 return undef if !defined($_[0]->_pinselects);
92 7         9 return @{$_[0]->_pinselects}[0]->{_netname};
  7         90  
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 12694 return [] if !defined($_[0]->_nets);
104 151         186 return (@{$_[0]->_nets});
  151         1933  
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 2094 return [] if !defined($_[0]->_pinselects);
112 154         204 return @{$_[0]->_pinselects};
  154         1922  
113             }
114             sub logger {
115 0     0 1 0 return $_[0]->netlist->logger;
116             }
117             sub module {
118 52     52 1 708 return $_[0]->cell->module;
119             }
120             sub submod {
121 61     61 0 785 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   135 my $self = shift;
129             # Note this routine is HOT
130 104         128 my $change;
131 104 100       1406 if (!$self->_nets) {
132 51 50       686 if ($self->_pinselects) {
133 51         89 my @nets = ();
134 51         61 foreach my $pinselect (@{$self->_pinselects}) {
  51         641  
135 52         139 my $net = $self->module->find_net($pinselect->netname);
136 52 100       143 next if (!defined($net));
137 22         40 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       69 if (defined($pinselect->msb)) {
141 3         9 $msb = $pinselect->msb;
142 3         9 $lsb = $pinselect->lsb;
143             } else {
144 19         296 $msb = $net->msb;
145 19         264 $lsb = $net->lsb;
146             }
147 22         103 push(@nets, {net => $net, msb => $msb, lsb => $lsb});
148             }
149 51         724 $self->_nets(\@nets);
150 51         98 $change = 1;
151             }
152             }
153 104 100       1482 if (!$self->port) {
154 59 100       124 if (my $submod = $self->submod) {
155 51         688 my $portname = $self->portname;
156 51 100 66     740 if ($portname && !$self->cell->byorder ) {
157 34         101 $self->port($submod->find_port($portname));
158 34         60 $change = 1;
159             }
160             else {
161 17         250 $self->port($submod->find_port_by_index($self->portnumber));
162             # changing name from pin# to actual port name
163 17 50       272 $self->name($self->port->name) if $self->port;
164 17         34 $change = 1;
165             }
166             }
167             }
168 104 100 66     971 if ($change && $self->_nets && $self->port) {
      100        
169 45         656 my $dir = $self->port->direction;
170 45         129 foreach my $net ($self->nets) {
171 18 50       52 next unless $net->{net};
172 18 100       48 if ($dir eq 'in') {
    50          
    0          
173 14         49 $net->{net}->_used_in_inc();
174             } elsif ($dir eq 'out') {
175 4         14 $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 32 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         34 return 1;
190             }
191              
192             sub lint {
193 40     40 1 53 my $self = shift;
194 40 50 66     551 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     505 if ($self->port && $self->nets) {
198 17 50       48 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         36 foreach my $net ($self->nets) {
206 17 100 66     278 next unless $net->{net} && $net->{net}->port;
207 6         83 my $portdir = $self->port->direction;
208 6         106 my $netdir = $net->{net}->port->direction;
209 6 50 66     57 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 46 my $self = shift;
223 37         40 my $inst;
224 37 100       517 if ($self->port) { # Even if it was by position, after linking we can write it as if it's by name.
    50          
225 34         450 $inst = ".".$self->port->name."(";
226             } elsif ($self->pinnamed) {
227 3         41 $inst = ".".$self->name."(";
228             } else { # not by name, and unlinked
229 0         0 $inst = ".".$self->portname."(";
230             }
231 37         91 my $net_cnt = $self->pinselects;
232 37 100       92 if ($net_cnt >= 2) {
    50          
233 1         3 $inst .= "{";
234 1         1 my $comma = "";
235 1         4 foreach my $pinselect (reverse($self->pinselects)) {
236 2         4 $inst .= $comma;
237 2         6 $inst .= $pinselect->bracketed_msb_lsb;
238 2         5 $comma = ",";
239             }
240 1         2 $inst .= "}";
241             } elsif ($net_cnt == 1) {
242 36         145 my @tmp = $self->pinselects;
243 36         97 $inst .= $tmp[0]->bracketed_msb_lsb;
244             }
245              
246 37         51 $inst .= ")";
247 37         90 return $inst;
248             }
249              
250             sub dump {
251 40     40 1 60 my $self = shift;
252 40   50     80 my $indent = shift||0;
253 40         97 my $net_cnt = $self->pinselects;
254 40         550 my $out = " "x$indent."Pin:".$self->name;
255 40 100       99 $out .= ($net_cnt > 1) ? " Nets:" : " Net:";
256 40         61 my $comma = "";
257 40         82 foreach my $pinselect (reverse($self->pinselects)) {
258 41         65 $out .= $comma;
259 41         119 $out .= $pinselect->bracketed_msb_lsb;
260 41         81 $comma = ",";
261             }
262 40         865 print "$out\n";
263 40 100       858 if ($self->port) {
264 37         479 $self->port->dump($indent+10, 'norecurse');
265             }
266 40         196 foreach my $net ($self->nets) {
267 18 50       52 next unless $net->{net};
268 18         63 $net->{net}->dump($indent+10, 'norecurse');
269             }
270             }
271              
272             ######################################################################
273             #### Package return
274             1;
275             __END__