Netlist.pm 61.1 KB
 Christian Fibich committed May 04, 2018 1 2 #** @file Netlist.pm # @verbatim  Christian Fibich committed May 04, 2018 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 #------------------------------------------------------------------------------- # University of Applied Sciences Technikum Wien # # Department of Embedded Systems # http://embsys.technikum-wien.at # # Josef Ressel Center for Verification of Embedded Computing Systems # http://vecs.technikum-wien.at # #------------------------------------------------------------------------------- # File: Netlist.pm # Created on: 29.04.2015 # $LastChangedBy$ # $LastChangedDate$ # # Description: #  Christian Fibich committed May 04, 2018 20 # FIJI Netlist class: Functions to instrument & export a Verilog::Netlist  Christian Fibich committed May 04, 2018 21 #-------------------------------------------------------------------------------  Christian Fibich committed May 04, 2018 22 23 # @endverbatim #*  Christian Fibich committed May 04, 2018 24   Christian Fibich committed May 04, 2018 25 26 27 28 29 ## @file Netlist.pm # @brief Contains class \ref FIJI::Netlist ## @class FIJI::Netlist # @brief Functions to instrument & export a Verilog::Netlist  Stefan Tauner committed May 04, 2018 30 31 32 33 package FIJI::Netlist; use strict; use warnings;  34 use diagnostics;  Stefan Tauner committed May 04, 2018 35   Stefan Tauner committed May 04, 2018 36 use Scalar::Util 'blessed';  Stefan Tauner committed May 04, 2018 37 use List::Util qw[min max];  Stefan Tauner committed May 04, 2018 38 use Log::Log4perl qw(get_logger :easy);  Stefan Tauner committed May 04, 2018 39 use File::Basename qw(basename);  Stefan Tauner committed May 04, 2018 40   Stefan Tauner committed May 04, 2018 41 42 use Verilog::Netlist 99.415; use Verilog::Language 99.415;  Christian Fibich committed May 04, 2018 43 44 45 46 use Data::Dumper; use FIJI::VHDL;  47 use constant HIERSEP => "/";  Christian Fibich committed May 04, 2018 48 49 use constant EQUALSEP => "="; use constant FIJI_NAMESPACE_PREFIX => "fiji_";  Christian Fibich committed May 04, 2018 50 51 use constant FIJI_PORT_IN_POSTFIX => "_inj_i"; use constant FIJI_PORT_OUT_POSTFIX => "_ori_o";  Christian Fibich committed May 04, 2018 52 use constant MAX_UNIQUE_TRIES => 10;  Stefan Tauner committed May 04, 2018 53   Christian Fibich committed May 04, 2018 54 use constant FIJI_LOGO => <{'nl'} = new Verilog::Netlist(  Christian Fibich committed May 04, 2018 86   Christian Fibich committed May 04, 2018 87 88 89 90 91 92  # options => $opt, # keep_comments => 1, # include comments in netlist link_read_nonfatal => 1, # do not fail if module description not found use_vars => 1, ); return$self;  Stefan Tauner committed May 04, 2018 93 94 }  Christian Fibich committed May 04, 2018 95 96 97 98 99 100 101 102 ## @method public read_file ($filename) # @brief Tries to read a Verilog netlist from the given file # # @param filename The Verilog file to read # # @returns 1 if an error occurred # @returns 0 if successful sub read_file {  Christian Fibich committed May 04, 2018 103  my$logger = get_logger("");  Christian Fibich committed May 04, 2018 104  my ($self,$filename) = @_;  Christian Fibich committed May 04, 2018 105   Christian Fibich committed May 04, 2018 106 107  ## Netlist synthesized from VHDL could contain SV keywords at this point. Verilog::Language::language_standard("1364-2001");  Christian Fibich committed May 04, 2018 108   Stefan Tauner committed May 04, 2018 109  $logger->info("Reading in netlist from file \"$filename\".");  Christian Fibich committed May 04, 2018 110  eval {  Christian Fibich committed May 04, 2018 111 112  $self->{'nl'}->read_file(filename =>$filename); # read Verilog file $self->{'nl'}->link(); # Read in any sub-modules  Christian Fibich committed May 04, 2018 113  };  Stefan Tauner committed May 04, 2018 114   Christian Fibich committed May 04, 2018 115 116  if ($self->{'nl'}->errors() != 0 || $@) {$logger->error("Could not parse $filename!",$@ ? "\n" . $@ : "");  Christian Fibich committed May 04, 2018 117 118  return 1; }  Stefan Tauner committed May 04, 2018 119   Christian Fibich committed May 04, 2018 120 $self->{'filename'} = $filename;  Christian Fibich committed May 04, 2018 121   Christian Fibich committed May 04, 2018 122 123 $logger->info("Successfully read in netlist from file \"$filename\"."); return 0;  Stefan Tauner committed May 04, 2018 124 125 }  Christian Fibich committed May 04, 2018 126 127 128 129 130 ## @method public get_toplevel_port_names () # @brief retrieves the port names of all toplevel modules # # @returns an array of Verilog::Port references sub get_toplevel_port_names {  Christian Fibich committed May 04, 2018 131  my ($self, $dir) = @_;  Christian Fibich committed May 04, 2018 132  my$ports_ref = [];  Christian Fibich committed May 04, 2018 133  foreach my $mod ($self->{'nl'}->top_modules_sorted) {  Stefan Tauner committed May 04, 2018 134  foreach my $port ($mod->ports) {  Christian Fibich committed May 04, 2018 135 136 137 138  if ( !defined($dir) || ($dir eq "o" && $port->direction eq "out") || ($dir eq "i" && $port->direction eq "in")) {  Christian Fibich committed May 04, 2018 139 140  push @{$ports_ref}, $port->name; }  Christian Fibich committed May 04, 2018 141 142 143  } } return$ports_ref;  144 145 }  Christian Fibich committed May 04, 2018 146 147 148 149 150 151 ## @method public get_toplevel_module () # @brief retrieves the port names of all toplevel modules # # @returns a Verilog::Module reference sub get_toplevel_module { my ($self) = @_;  Christian Fibich committed May 04, 2018 152 153 154 155 156  my @m =$self->{'nl'}->top_modules_sorted; my $n = @m; return$m[0] if ($n == 1); return "More than one toplevel module present in netlist." if ($n > 1); return "No toplevel module found.";  Christian Fibich committed May 04, 2018 157 158 }  Christian Fibich committed May 04, 2018 159 160 161 162 ## @method public get_nets () # @brief retrieves all nets in the netlist # # @returns an array of hashes for all nets containing:  Christian Fibich committed May 04, 2018 163 164 165 # 'name' the name of the net # 'path' the hierarchical path of the net # 'net' the Verilog::Netlist::Net reference to the net  Christian Fibich committed May 04, 2018 166 sub get_nets {  Christian Fibich committed May 04, 2018 167 168 169 170 171  my ($self) = @_; # my$nets_ref = {'metadata' => [], 'names' => [], 'nets' => []}; my $nets_ref = []; my$hier = "";  172 173 174  my $top =$self->get_toplevel_module(); if ($top->isa("Verilog::Netlist::Module")) {$self->_get_subnets($nets_ref,$top, $hier);  Christian Fibich committed May 04, 2018 175 176  } return$nets_ref;  Stefan Tauner committed May 04, 2018 177 178 }  Stefan Tauner committed May 04, 2018 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 sub _extract_low_high { my ($in_low,$in_high) = @_; my ($out_low,$out_high); # msb might be lower than lsb if index range is "upto" -> swap if ($in_high <$in_low) { $out_low =$in_high; $out_high =$in_low; } else { $out_low =$in_low; $out_high =$in_high; } return ($out_low,$out_high); }  Christian Fibich committed May 04, 2018 194 195 196 197 198 199 200 201 202 #** @method private _get_subnets ($nets_ref,$mod,$hier) # @brief retrieves all nets in the given module # # @param nets_ref the central reference to push found nets (name,path,netref) to # @param mod the module to search # @param hier a string representing the current hierarchy level, separated # be HIERSEP sub _get_subnets {  Christian Fibich committed May 04, 2018 203  my$logger = get_logger("");  204  my ($self,$nets_ref, $mod,$hier, $instname) = @_;  Christian Fibich committed May 04, 2018 205   Christian Fibich committed May 04, 2018 206  my$thishier = $hier;  Christian Fibich committed May 04, 2018 207 $thishier .= HIERSEP if $thishier ne "";  208 209 210 211 212  if (defined$instname) { $thishier .=$instname; } else { $thishier .=$mod->name; }  Christian Fibich committed May 04, 2018 213   Christian Fibich committed May 04, 2018 214  foreach my $n ($mod->nets) {  Stefan Tauner committed May 04, 2018 215  if (defined($n->msb) && defined($n->lsb)) {  Stefan Tauner committed May 04, 2018 216  my ($low,$high) = _extract_low_high($n->lsb,$n->msb);  Stefan Tauner committed May 04, 2018 217  for (my $sub =$low ; $sub <=$high ; $sub++) {  Christian Fibich committed May 04, 2018 218  my$thisnet_ref = {name => $n->name . "[$sub]", path => $thishier, net =>$n, index => $sub};  Christian Fibich committed May 04, 2018 219 220 221 222 223 224 225  push(@{$nets_ref}, $thisnet_ref); } } else { my$thisnet_ref = {name => $n->name, path =>$thishier, net => $n}; push(@{$nets_ref}, $thisnet_ref); }  Christian Fibich committed May 04, 2018 226  }  Stefan Tauner committed May 04, 2018 227   Stefan Tauner committed May 04, 2018 228  foreach my$cell ($mod->cells) {  Christian Fibich committed May 04, 2018 229  if (defined($cell->submod)) {  230  $self->_get_subnets($nets_ref, $cell->submod,$thishier, $cell->name);  Christian Fibich committed May 04, 2018 231  }  Stefan Tauner committed May 04, 2018 232 233 234  } }  Christian Fibich committed May 04, 2018 235 236 237 ## @function private _check_name_in_hierarchy ($startmod,$name) # @brief checks if a given name exists # checks if the$name exists as port, net, or cell name in the instantiation tree.  Christian Fibich committed May 04, 2018 238 #  Christian Fibich committed May 04, 2018 239 240 # @param startmod the module to start with # @param name the name to check against  Christian Fibich committed May 04, 2018 241 sub _check_name_in_hierarchy {  Christian Fibich committed May 04, 2018 242   Christian Fibich committed May 04, 2018 243  my $logger = get_logger("");  Christian Fibich committed May 04, 2018 244  my ($startmod, $name) = @_;  Christian Fibich committed May 04, 2018 245 246  my$nl = $startmod->netlist;  247 $logger->debug("Checking \"" . $startmod->name . "\" for name \"$name\"");  Christian Fibich committed May 04, 2018 248 249  # check if a net is named the same  Stefan Tauner committed May 04, 2018 250  for my $net ($startmod->nets) {  Christian Fibich committed May 04, 2018 251  if ($net->name eq$name) {  252  my $msg = "Name \"$name\" does already exist as net in " . $startmod->name;  Christian Fibich committed May 04, 2018 253  return$msg;  Christian Fibich committed May 04, 2018 254 255 256 257  } } # check if a port is named the same  Stefan Tauner committed May 04, 2018 258  for my $port ($startmod->ports) {  Christian Fibich committed May 04, 2018 259  if ($port->name eq$name) {  260  my $msg = "Name \"$name\" does already exist as port in " . $startmod->name;  Christian Fibich committed May 04, 2018 261  return$msg;  Christian Fibich committed May 04, 2018 262 263 264  } }  Stefan Tauner committed May 04, 2018 265  for my $cell ($startmod->cells) {  Christian Fibich committed May 04, 2018 266  if ($cell->name eq$name) {  267  my $msg = "Name \"$name\" does already exist as cell in " . $startmod->name;  Christian Fibich committed May 04, 2018 268  return$msg;  Christian Fibich committed May 04, 2018 269 270 271 272  } } # find any module instantiating the current start module  Stefan Tauner committed May 04, 2018 273 274  foreach my $mod ($nl->modules) { foreach my $cell ($mod->cells) {  Christian Fibich committed May 04, 2018 275 276  if (defined $cell->submod &&$cell->submod == $startmod) { my$msg = _check_name_in_hierarchy($mod,$name);  Christian Fibich committed May 04, 2018 277  return $msg if defined$msg;  Christian Fibich committed May 04, 2018 278 279 280  } } }  Christian Fibich committed May 04, 2018 281   Christian Fibich committed May 04, 2018 282  return undef;  Christian Fibich committed May 04, 2018 283 284 }  Christian Fibich committed May 04, 2018 285 286 ## @function private _add_port_to_hierarchy ($startmod,$name,$function,$index,$indent) # @brief adds a port to all modules starting from a leaf node  Christian Fibich committed May 04, 2018 287 #  Christian Fibich committed May 04, 2018 288 289 290 291 292 293 294 295 # @param startmod the module to start with # @param name the port name to be generated # @param function the function of this port in FIJI (FIJI::VHDL->FIJI_PORTTYPE_xxx) # @param index for ORIGINAL,MODIFIED and FAULT_DETECT: the index of this net # @param indent optional, needed just for formatting logging output # # @returns undef if the given port$name is already found # @returns Verilog::Port reference to the new port if successful  Christian Fibich committed May 04, 2018 296 sub _add_port_to_hierarchy {  Christian Fibich committed May 04, 2018 297   Christian Fibich committed May 04, 2018 298  my $logger = get_logger("");  Christian Fibich committed May 04, 2018 299  my ($startmod, $name,$function, $index,$indent) = @_;  Christian Fibich committed May 04, 2018 300  my $nl =$startmod->netlist;  Christian Fibich committed May 04, 2018 301  my $direction = "undef";  Christian Fibich committed May 04, 2018 302  if (!defined$indent) {  Christian Fibich committed May 04, 2018 303 304 305 306 307  $indent = ""; } else {$indent .= " "; }  Christian Fibich committed May 04, 2018 308  return undef if ($startmod->find_port($name));  Christian Fibich committed May 04, 2018 309   310  $logger->debug($indent . "Adding port \"$name\" to module \"" .$startmod->name . "\"");  Christian Fibich committed May 04, 2018 311 312  # decide direction  Christian Fibich committed May 04, 2018 313  if ( $function == FIJI::VHDL->FIJI_PORTTYPE_MODIFIED  Christian Fibich committed May 04, 2018 314  ||$function == FIJI::VHDL->FIJI_PORTTYPE_RESET_TO_DUT)  Christian Fibich committed May 04, 2018 315  {  Christian Fibich committed May 04, 2018 316  $direction = "in";  Christian Fibich committed May 04, 2018 317  } else {  Christian Fibich committed May 04, 2018 318 319 320 321 $direction = "out"; } # generate port  Christian Fibich committed May 04, 2018 322  my $np =$startmod->new_port(name => $name, direction =>$direction);  Christian Fibich committed May 04, 2018 323 324  # set port type for wrapper generation  Christian Fibich committed May 04, 2018 325  $np->userdata(FIJI::VHDL->FIJI_USERDATA_PORTTYPE,$function);  Christian Fibich committed May 04, 2018 326 327  # set indices  Christian Fibich committed May 04, 2018 328  if ( $function == FIJI::VHDL->FIJI_PORTTYPE_MODIFIED  Christian Fibich committed May 04, 2018 329  ||$function == FIJI::VHDL->FIJI_PORTTYPE_ORIGINAL)  Christian Fibich committed May 04, 2018 330  {  Christian Fibich committed May 04, 2018 331 332 333  $np->userdata(FIJI::VHDL->FIJI_USERDATA_FIU_INDEX,$index); } elsif ($function == FIJI::VHDL->FIJI_PORTTYPE_FAULT_DETECTION) {$np->userdata(FIJI::VHDL->FIJI_USERDATA_FD_INDEX, $index);  Christian Fibich committed May 04, 2018 334 335  }  Christian Fibich committed May 04, 2018 336 337  # let Verilog-Perl create a new net for the new port.$startmod->link;  Christian Fibich committed May 04, 2018 338 339  # find all modules instantiating the current module  Christian Fibich committed May 04, 2018 340  foreach my $mod ($nl->modules_sorted) {  Stefan Tauner committed May 04, 2018 341  foreach my $cell ($mod->cells) {  Christian Fibich committed May 04, 2018 342  if (defined $cell->submod &&$cell->submod == $startmod) {  343 344 $logger->debug($indent . "Adding pin \"$name\" to cell \"" . $cell->name . "\"");$logger->debug($indent . "Connecting pin \"" .$cell->name . HIERSEP . $name . "\" to port \"" .$np->module->name . HIERSEP . $np->name . "\"");  Christian Fibich committed May 04, 2018 345 346 347 $cell->new_pin( name => $name, portname =>$np->name,  Christian Fibich committed May 04, 2018 348  netnames => [{'netname' => $np->net->name}],  Christian Fibich committed May 04, 2018 349 350  );  Christian Fibich committed May 04, 2018 351  # let verilog-perl find the net and port.  Stefan Tauner committed May 04, 2018 352 $startmod->link;  Christian Fibich committed May 04, 2018 353  _add_port_to_hierarchy($mod,$name, $function,$index, $indent);  Christian Fibich committed May 04, 2018 354 355 356  } } }  Christian Fibich committed May 04, 2018 357   Christian Fibich committed May 04, 2018 358 359 360  return$np; }  Christian Fibich committed May 04, 2018 361 362 363 ## @method public net_add_function($net,$function, $port_name,$index) # @brief Generate external access to a single net #  Christian Fibich committed May 04, 2018 364 365 366 367 368 369 # Performs the following steps: # 1. check if the default port name does not yet exist # 1a. if it exists, generate a new net name # 2. add a port through the entire hierarchy # 3. assign the net to the port using a contassign statement #  370 371 372 373 # @param net_descriptor a hash containing the keys 'net' => Net Object, 'net_name' => Net name string, 'msb', 'lsb', 'mod' => The module containing the net # @param function the function out of FIJI::VHDL->FIJI_PORTTYPE_xxx # @param port_name how the port shall be named (will be prefixed with "fiji_") # @param index for some FIJI_PORTTYPEs, an index is needed (FIU and Fault Detect)  Christian Fibich committed May 04, 2018 374 375 376 # # @returns undef sub net_add_function {  Christian Fibich committed May 04, 2018 377  my $logger = get_logger("");  378  my ($self, $net_descriptor,$function, $port_name,$index) = @_;  Christian Fibich committed May 04, 2018 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  if (ref($net_descriptor) ne "HASH") { return$net_descriptor; } my $net =$net_descriptor->{'net'}; my $net_name =$net_descriptor->{'net_name'}; my $msb =$net_descriptor->{'msb'}; my $lsb =$net_descriptor->{'lsb'}; my $mod =$net_descriptor->{'mod'}; my $idx = ''; my$idx_postfix = ''; # We need to produce names for the i/o ports that route the signals # to the FIC. To allow to instrument multiple indices of a single # signal we need to make these names unique thus we even include the # indices if used. if (defined $msb && defined$lsb) { if ($msb ne$lsb) { # We dont support the instrumentation of vectors (only sinlge indices of busses). return "The given net to instrument is a vector with multiple bits.\nThis is not supported.\nMaybe you want to instrument a single bit of said vector instead?"; # $idx = "[".$msb.":".$lsb."]"; #$idx_postfix = "_".$msb."_".$lsb."_"; } else { $idx = "[".$msb."]"; $idx_postfix = "_".$msb."_"; } } $logger->debug("Adding function to \"" .$mod . "\", net \"" . $net_name . "\"");  Christian Fibich committed May 04, 2018 410 411  my$prefix = "fiji_";  Christian Fibich committed May 04, 2018 412   413  my $unique_name = _unique_name($mod,$prefix.$port_name);  Christian Fibich committed May 04, 2018 414 415 416  if (!defined $unique_name) {$logger->error("Could not find a unique name for prefix ".$prefix.$port_name)  Christian Fibich committed May 04, 2018 417 418  }  Christian Fibich committed May 04, 2018 419 420  $logger->debug("\"" .$unique_name . "\" can be used as fiji connector"); my $op = _add_port_to_hierarchy($net->module, $unique_name,$function, $index);  Christian Fibich committed May 04, 2018 421   422 $logger->debug("Connecting Port \"" . $op->name . "\" to net \"" .$net_name.$idx . "\"");  Christian Fibich committed May 04, 2018 423   Christian Fibich committed May 04, 2018 424  # connect the net to the newly created port  Christian Fibich committed May 04, 2018 425 426 427 $net->module->new_contassign( keyword => "assign", lhs => $op->name,  428  rhs =>$net_name.$idx,  Christian Fibich committed May 04, 2018 429 430 431  module =>$op->module, netlist => $op->module->netlist );  Christian Fibich committed May 04, 2018 432   Christian Fibich committed May 04, 2018 433 434 435  return undef; }  Christian Fibich committed May 04, 2018 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 # tries to generate a unique but recognizable net name by appending a # random hex number if necessary sub _unique_name { my$logger = get_logger(""); my ($mod,$requested_name) = @_; # check if requested name is OK my $msg = _check_name_in_hierarchy($mod, $requested_name); if (!defined$msg) { return $requested_name; } # else try up to 10 times to generate a unique name by appending # a 4-digit random hex number for (my$tries = 0; $tries < MAX_UNIQUE_TRIES;$tries++) { my $name = sprintf("%s_%04x",$requested_name, rand(0xffff)); $msg = _check_name_in_hierarchy($mod, $name); return$name if (!defined $msg); } return undef }  460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 # take a possible escaped identifier and make it a legal _and_ sane verilog identifier sub _sanitize_identifier { my$insane = shift; # Verilog allows "non-alphanumeric" characters in identifiers if they start with a backslash and end with whitespace (escaped identifiers) but we don't want to. my $sane = ($insane =~ s/[^a-zA-Z0-9_]+/_/gr); # VHDL signals must not contain multiple subsequent underscores $sane =~ s/__+/_/g; return$sane } sub generate_contassign { my $logger = get_logger(""); my ($module, $lhs,$rhs) = @_; $logger->trace("Setting \"$lhs = $rhs\"");$module->new_contassign( keyword => "assign", lhs => $lhs, rhs =>$rhs, module => $module, netlist =>$module->netlist ); }  Christian Fibich committed May 04, 2018 484 485 486 487 ## @method public instrument_net($net,$fiu_idx, $driver,$driver_type) # @brief instruments a single net for fault injection # # This method performs the following steps  Stefan Tauner committed May 04, 2018 488 489 490 # 1. determine the connected objects (driver as well as driven nets, pins etc) # 2. generate external access output and input ports and intermediate nets # 3. interconnect these ports to the matching driver and driven cells via the intermediate nets  Christian Fibich committed May 04, 2018 491 #  492 # @param net_path the Verilog::Net to instrument  Christian Fibich committed May 04, 2018 493 # @param fiu_idx the FIU number this external access shall be connected to  494 495 # @param driver_path the path to the driver of this net (optional but depends on driver_type) # @param driver_type the type of the driver (can be PIN, PORT, ASSIGN) (optional but depends on driver_path)  Christian Fibich committed May 04, 2018 496 497 498 499 # # @returns STRING if an error occurred # @returns undef if successful sub instrument_net {  Christian Fibich committed May 04, 2018 500   Christian Fibich committed May 04, 2018 501  my $logger = get_logger("");  Christian Fibich committed May 04, 2018 502  my ($self, $net_path,$fiu_idx, $driver_path,$driver_type) = @_;  Christian Fibich committed May 04, 2018 503   Christian Fibich committed May 04, 2018 504  # split hierarchical net path  Stefan Tauner committed May 04, 2018 505  my $net_descriptor =$self->get_netdescriptor_from_path($net_path);  Christian Fibich committed May 04, 2018 506 507  if (ref($net_descriptor) ne "HASH") {  508  return $net_descriptor;  Christian Fibich committed May 04, 2018 509 510 511  } my$net = $net_descriptor->{'net'};  Stefan Tauner committed May 04, 2018 512  my$net_name = $net_descriptor->{'net_name'};  Christian Fibich committed May 04, 2018 513 514  my$msb = $net_descriptor->{'msb'}; my$lsb = $net_descriptor->{'lsb'};  Stefan Tauner committed May 04, 2018 515  my$mod = $net_descriptor->{'mod'};  Christian Fibich committed May 04, 2018 516 517 518  my$idx = ''; my $idx_postfix = '';  Stefan Tauner committed May 04, 2018 519 520 521 522 523 524  # We need to produce names for the i/o ports that route the signals # to the FIC. To allow to instrument multiple indices of a single # signal we need to make these names unique thus we even include the # indices if used. if (defined$msb && defined $lsb) { if ($msb ne $lsb) {  525  # We dont support the instrumentation of vectors (only sinlge indices of busses).  Stefan Tauner committed May 04, 2018 526  return "The given net to instrument is a vector with multiple bits.\nThis is not supported.\nMaybe you want to instrument a single bit of said vector instead?";  527 528  #$idx = "[".$msb.":".$lsb."]"; # $idx_postfix = "_".$msb."_".$lsb."_";  Christian Fibich committed May 04, 2018 529  } else {  Stefan Tauner committed May 04, 2018 530 531 $idx = "[".$msb."]";$idx_postfix = "_".$msb."_";  Christian Fibich committed May 04, 2018 532 533 534  } }  Stefan Tauner committed May 04, 2018 535 $logger->info("Instrumenting \"" . $net->module->name . "\", net \"" .$net->name.$idx . "\"");  Christian Fibich committed May 04, 2018 536   Stefan Tauner committed May 04, 2018 537 538 539 540 541  # we want to perceive the connection state before any changes (at least w/o changes by this invocation) my %connections; my$rv = $self->_get_net_connections($net, \%connections, $msb,$driver_path, $driver_type); return$rv if (defined $rv);  542 543 544 545  my$output_name = (FIJI_NAMESPACE_PREFIX . $net->name .$idx_postfix . FIJI_PORT_OUT_POSTFIX); $output_name = _sanitize_identifier($output_name); my $input_name = (FIJI_NAMESPACE_PREFIX .$net->name . $idx_postfix . FIJI_PORT_IN_POSTFIX);$input_name = _sanitize_identifier($input_name);  Christian Fibich committed May 04, 2018 546   Christian Fibich committed May 04, 2018 547  # generate unique name for output port, return with error message if that fails  Stefan Tauner committed May 04, 2018 548  my$unique_output_name = _unique_name($mod,$output_name);  Christian Fibich committed May 04, 2018 549  return "Could not generate unique name for prefix $output_name" if (!defined$unique_output_name);  Christian Fibich committed May 04, 2018 550   Christian Fibich committed May 04, 2018 551  $logger->debug("\"" .$unique_output_name . "\" will be used as fiji connector (output)");  Stefan Tauner committed May 04, 2018 552  my $op = _add_port_to_hierarchy($mod, $unique_output_name, FIJI::VHDL->FIJI_PORTTYPE_ORIGINAL,$fiu_idx);  Christian Fibich committed May 04, 2018 553   Stefan Tauner committed May 04, 2018 554 555  # generate unique name for input port, return with error message if that fails my $unique_input_name = _unique_name($mod, $input_name);  Christian Fibich committed May 04, 2018 556  return "Could not generate unique name for prefix$input_name" if (!defined $unique_input_name);  Christian Fibich committed May 04, 2018 557   Christian Fibich committed May 04, 2018 558 $logger->debug("\"" . $unique_input_name . "\" will be used as fiji connector (input)");  Stefan Tauner committed May 04, 2018 559  my$ip = _add_port_to_hierarchy($mod,$unique_input_name, FIJI::VHDL->FIJI_PORTTYPE_MODIFIED, $fiu_idx);  Christian Fibich committed May 04, 2018 560   Christian Fibich committed May 04, 2018 561   Stefan Tauner committed May 04, 2018 562 563 564  # Add an intermediate net to allow patching without rewriting connections everywhere # # We use the requested signal as sink/destination.  Stefan Tauner committed May 04, 2018 565  # That way we only need to change the driver to drive our intermediate net.  Stefan Tauner committed May 04, 2018 566  #  Stefan Tauner committed May 04, 2018 567 568 569  # We first generate a suitable name for the intermediate net, # then change the driver accordingly and handle other aspects of # the intermediate net at the very bottom of this function.  Stefan Tauner committed May 04, 2018 570   Stefan Tauner committed May 04, 2018 571  # Choose intermediate net name  Stefan Tauner committed May 04, 2018 572  my$net_name_tmp = _sanitize_identifier(FIJI_NAMESPACE_PREFIX . $net_name . "_in_tmp");  Stefan Tauner committed May 04, 2018 573  my$net_tmp = $mod->find_net($net_name_tmp);  Stefan Tauner committed May 04, 2018 574  my $name_check = _check_name_in_hierarchy($mod, $net_name_tmp);  Christian Fibich committed May 04, 2018 575   Stefan Tauner committed May 04, 2018 576 577 578  # Switch the driver from the original signal to the intermediate net. my$driver_is_vector = 0; my $driver_is_port = 0;  Stefan Tauner committed May 04, 2018 579  my$driver_bit = $msb;  Stefan Tauner committed May 04, 2018 580  my$driver;  Stefan Tauner committed May 04, 2018 581  foreach my $connection (@{$connections{'drivers'}}) {  Christian Fibich committed May 04, 2018 582  if (ref($connection) eq "Verilog::Netlist::Pin") {  Stefan Tauner committed May 04, 2018 583 584  # If the driver is a pin of a (sub)cell, connect this pin to the intermediate net$logger->debug("Connecting (output) pin \"" . $connection->cell->name . HIERSEP .$connection->name . "\" to intermediate net \"$net_name_tmp\"");  Stefan Tauner committed May 04, 2018 585  for my$netname ($connection->netnames) {  586  if ($netname->{'netname'} eq $net->name) {  Stefan Tauner committed May 04, 2018 587 $driver = $connection;  Stefan Tauner committed May 04, 2018 588 $netname->{'netname'} = $net_name_tmp; # FIXME: do we need to force a re-link (by deleting$connection->nets)?  Stefan Tauner committed May 04, 2018 589  # The intermediate net is a vector if the underlying net is a bus and we do not just select a single bit  590  # This is the case if  Stefan Tauner committed May 04, 2018 591 592 593 594 595 596 597  # - the underlying net is a vector and the driver covers all indices (implicitly by having no msb/lsb set) # - the underlying net is a vector and the driver covers some indices (by having two different indices set) # Also, if we instrument a second bit of a vector we need to make sure this instrumentation is handled as if the # the driver itself is a vector. if (defined($net->msb) && (!defined($netname->{'msb'}) || ($netname->{'msb'} !=$netname->{'lsb'}))) { $driver_is_vector = 1; } elsif (defined($net_tmp) && defined($net_tmp->userdata("first_instrumented_bit"))) {  Stefan Tauner committed May 04, 2018 598 $driver_is_vector = 1;  599 600 601 602  } else { # Make sure we do not output the index unnecessarily (if the driver is a single bit of a vector) undef($netname->{'msb'}); undef($netname->{'lsb'});  Stefan Tauner committed May 04, 2018 603  }  Christian Fibich committed May 04, 2018 604  }  Christian Fibich committed May 04, 2018 605  }  Stefan Tauner committed May 04, 2018 606 607 608  # $connection->port(undef); # resolved by link } else { if (ref($connection) eq "Verilog::Netlist::Port") {  Stefan Tauner committed May 04, 2018 609  $driver_is_port = 1;  Stefan Tauner committed May 04, 2018 610 $driver = $connection;  Stefan Tauner committed May 04, 2018 611 612 613 614  # If we are changing the name of a port of the top module we need to inform the VHDL generator if ($mod->is_top) { $connection->userdata(FIJI::VHDL->FIJI_USERDATA_PREV_PORTNAME,$connection->name); }  Stefan Tauner committed May 04, 2018 615 616 617 618 619  # Change type of existing non-instrumented input to wire - # practically transforming it to an ordinary wire that can easily be intrumented. $logger->debug("Transforming previous port named \"".$connection->name . "\" into an ordinary wire"); $connection->net->decl_type(undef);$connection->net->net_type("wire");  Stefan Tauner committed May 04, 2018 620 621 622 623 624 625 626 627  my $data_type; # If instrumented net is a vector we will need an intermediate bus if (defined($net->msb)) { $driver_is_vector = 1;$data_type = "[".$net->msb.":".$net->lsb."]"; $connection->data_type($data_type); } $connection->net->data_type($data_type);  Stefan Tauner committed May 04, 2018 628 629 630  # Unsetting the port<->net inter-references forces their automatic re-setting at link time $connection->net->port(undef);$connection->net(undef);  Stefan Tauner committed May 04, 2018 631  # Eventually connect this port to the intermediate net by changing its name  Stefan Tauner committed May 04, 2018 632  $logger->debug("Connecting (input) port \"" .$connection->name . "\" to intermediate net \"$net_name_tmp\"");  Stefan Tauner committed May 04, 2018 633 $connection->name($net_name_tmp); # NB: this will automatically change the cell's configuration on the next link() call.  Stefan Tauner committed May 04, 2018 634 635  } elsif (ref($connection) eq "Verilog::Netlist::ContAssign") { # If the driver is an assignment, replace the LHS with the intermediate net  Stefan Tauner committed May 04, 2018 636 637 638 639 640 641 642 643  # Retrieve net object of LHS of the assignment to determine if it is a bus and if the assignment is to the complete net or a single bit. my $lhs_elems =$self->_extract_netstring_elements($connection->lhs); my$lhs_net_name = $lhs_elems->{'net_name'}; my$lhs_net = $mod->find_net($lhs_net_name); if (!defined($lhs_net)) { my$lhs_port = $mod->find_port($lhs_net_name); if (!defined($lhs_port)) { return "Could not find net or port in module \"" .$mod->name . "\" matching LHS of assignment \"" . $connection->lhs . "\" = \"" .$connection->rhs . "\"";  Stefan Tauner committed May 04, 2018 644  }  Stefan Tauner committed May 04, 2018 645 646 647 648  # FIXME: so this is actually a port... $logger->fatal("Found port name in continuous assignment. This is not supported yet."); return "BORKED"; }  Stefan Tauner committed May 04, 2018 649 $driver = $connection;  Stefan Tauner committed May 04, 2018 650 651 652  if (defined($connection->userdata->{'fiji_driver_bit'})) { $driver_is_vector = 1;$driver_bit = $connection->userdata->{'fiji_driver_bit'};  Stefan Tauner committed May 04, 2018 653  }  Stefan Tauner committed May 04, 2018 654 655 656 657 658 659 660 661  if (!defined($net_tmp) || !defined($net_tmp->userdata("first_instrumented_bit"))) {$logger->debug("Connecting to intermediate net \"" . $net_name_tmp . "\" the continuous assignment of \"" .$connection->rhs . "\""); # need to remember what was originally connected to this assign # to instrument two nets driven by one assign $connection->userdata('former_assign' => {'lhs' =>$connection->lhs, 'rhs' => $connection->rhs});$connection->lhs($net_name_tmp); }  Christian Fibich committed May 04, 2018 662   Stefan Tauner committed May 04, 2018 663  } else {  Stefan Tauner committed May 04, 2018 664 $logger->error("Driver instance is neither pin, port nor contassign?");  Stefan Tauner committed May 04, 2018 665  }  Christian Fibich committed May 04, 2018 666 667  } }  Christian Fibich committed May 04, 2018 668   Stefan Tauner committed May 04, 2018 669 670 671 672 673 674 675  # Below we create the intermediate net as needed. # A suitable name for the tmp net was already determined. # 1.) Generate the tmp net. # 2.) Assign injected signal from input pin to original signal. # 3.) If original signal is a bus forward orignal data from tmp net to untouched bits of original signal # 4.) Forward (injected bit of) intermediate net to FIC by assigning it to the output pin #  Stefan Tauner committed May 04, 2018 676 677 678 679 680  # However, if the net is already instrumented we need to jump through some hoops: # In that case we either have an error, or we need to instrument another bit of a bus. # The latter complicates things a bit... if (defined($net_tmp) && defined($net_tmp->userdata("first_instrumented_bit"))) { # FIXME: maybe we should try harder to find out the reason why _check_name_in_hierarchy failed  Stefan Tauner committed May 04, 2018 681 682 683 684 685  if (!defined($net->msb)) { my$err = "Tried to instrument non-vector signal (\"$net_name\") twice or we really have a naming conflict.";$logger->error($err); return$err; }  Stefan Tauner committed May 04, 2018 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  if (!defined($net_tmp->msb)) { # If we instrument the second bit of a net (as wittnessed by the missing msb field) # then we need to make sure the intermediate net is or becomes a vector my$prev_bit = $net_tmp->userdata("first_instrumented_bit"); my$prev_driver = $net_tmp->userdata("first_driver");$logger->debug(" widening \"" . $net_tmp->name . " to [" .$net->msb . ":" . $net->lsb . "]");$net_tmp->msb($net->msb);$net_tmp->lsb($net->lsb);$net_tmp->data_type("[".$net->msb.":".$net->lsb."]"); # Additionally the previous exporting of the original signal needs to be adepted foreach my $statement ($mod->statements) { if ($statement->rhs =~ /^[ \t]*~?[ \t]*\Q$net_name_tmp\E$/) {$statement->rhs($net_name_tmp."[".$prev_bit."]"); $logger->debug(" reassigning \"" .$statement->lhs . " = " . $statement->rhs . "\" --> \"".$net_name_tmp."[".$prev_bit."]\""); } } # We also need to fix the previous assignment of the respective bit... if (ref($prev_driver) eq "Verilog::Netlist::Pin") { $logger->debug(" reassigning pin \"" .$prev_driver->name . "\": $net_name_tmp -->$net_name_tmp$prev_bit$"); for my $netname ($prev_driver->netnames) { if ($netname->{'netname'} eq$net_name_tmp) { $netname->{'msb'} =$prev_bit; $netname->{'lsb'} =$prev_bit; last; } } } elsif (ref($prev_driver) eq "Verilog::Netlist::Port") {$logger->debug(" reassigning port \"" . $prev_driver->name . "\""); return "BORKED"; # not implemented yet } elsif (ref($prev_driver) eq "Verilog::Netlist::ContAssign") { $logger->debug(" reassigning ContAssign \"" .$prev_driver->lhs . " = " . $prev_driver->rhs . "\"");$prev_driver->rhs($net_name_tmp."[".$prev_bit."]"); } # And add the default assignments of the (possibly yet) uninstrumented bits my ($low,$high) = _extract_low_high($net->lsb,$net->msb); $logger->debug(" assigning \"" .$net_name."[".$low."-".$high."] = ..."); for (my $i =$low ; $i <=$high ; $i++) { if ($i != $driver_bit &&$i != $prev_bit) { generate_contassign($mod, $net_name."[".$i."]", $net_name_tmp."[".$i."]"); } } } else { # For all additional bits (starting with the third one) # the previous assignment of the respective bit needs to be undone foreach my $statement ($mod->statements) { if ($statement->rhs =~ /^[ \t]*~?[ \t]*\Q$net_name_tmp\E($(\Qdriver_bit\E)$)$/) {$logger->debug(" unassigning \"" . $statement->lhs . " = " .$statement->rhs . "\""); $statement->delete(); }  Stefan Tauner committed May 04, 2018 739 740 741  } }  Stefan Tauner committed May 04, 2018 742 $logger->debug(" assigning to currently processed signal \"" . $net_name."[".$driver_bit."] = " . $ip->net->name . "\"");  Stefan Tauner committed May 04, 2018 743  generate_contassign($mod, $net_name."[".$driver_bit."]", $ip->net->name);  Stefan Tauner committed May 04, 2018 744 $driver_is_vector = 1;  Stefan Tauner committed May 04, 2018 745 746  } else { # 2.) Generate intermediate (tmp) net for easier input and output routing  Stefan Tauner committed May 04, 2018 747 748 749  # For ports we don't need to do that ourselves because Verilog::Perl will # generate a new apropriate net when linking the port. if ($driver_is_port) {  Stefan Tauner committed May 04, 2018 750 $logger->debug("Intermediate port named \"" . $net_name_tmp . (defined($net->msb) ? "[" . $net->msb .":".$net->lsb . "]" : "") . "\" to patch \"$net_name\" will be generated automatically later");  Stefan Tauner committed May 04, 2018 751  } else {  Stefan Tauner committed May 04, 2018 752 753 754 755 756 757 758 759 760 761 762 763 764  # If the driver is a vector then we will generate a vectored intermediate net as well. # However, if the driver is a single-bit net or a single bit of a vector we generate # a simple intermediate net (and could get away with none at all actually). my @net_cfg = (name =>$net_name_tmp); if ($driver_is_vector) {$logger->debug("Generating intermediate wire named \"" . $net_name_tmp . "[" .$net->msb .":". $net->lsb . "]\" to patch \"$net_name\""); push(@net_cfg, msb => $net->msb, lsb =>$net->lsb, ); } else { $logger->debug("Generating intermediate wire named \"" .$net_name_tmp . "\" to patch \"$net_name\""); }  Stefan Tauner committed May 04, 2018 765 766 767 768 769 770 771 $net_tmp = $mod->new_net(@net_cfg); # If we possibly instrument other bits we need to remember some things if (defined($net->msb)) { $net_tmp->userdata("first_instrumented_bit",$driver_bit); $net_tmp->userdata("first_driver",$driver); $logger->debug("Remembering the first instrumented bit ($driver_bit) assigned to \"" . $net_name_tmp . "\" driven by \"" .$driver->name . "\""); }  Stefan Tauner committed May 04, 2018 772 773 774 775 776 777 778 779 780 781  } # 3+4.) Assign injected (and uninjected bits of vectors) to previous signal. # Below we assign the altered signal from the FIC to the original signal. # For busses we need to connect all non-instrumented bits of the tmp net # additionally to preserve their unmodified values. if (!defined($net->msb)) { # If the instrumented net is not a vector we simply assign the injected signal generate_contassign($mod, $net_name,$ip->net->name);  Stefan Tauner committed May 04, 2018 782  } elsif (!$driver_is_vector) {  Stefan Tauner committed May 04, 2018 783 784  # If the net is a vector but the driver was driving only one bit # then we need to drive the originally driven bit only  Stefan Tauner committed May 04, 2018 785  generate_contassign($mod, $net_name."[".$driver_bit."]", $ip->net->name);  Stefan Tauner committed May 04, 2018 786 787 788  } else { # For drivers of complete busses we need to connect all non-instrumented bits of the tmp net # additionally to preserve their unmodified values.  Stefan Tauner committed May 04, 2018 789  # In case of concatenations the index might be different to the one given.  Stefan Tauner committed May 04, 2018 790  my ($low, $high) = _extract_low_high($net->lsb, $net->msb);  Stefan Tauner committed May 04, 2018 791  for (my$i = $low ;$i <= $high ;$i++) {  Stefan Tauner committed May 04, 2018 792  if ($i ==$driver_bit) {  Stefan Tauner committed May 04, 2018 793 794 795 796 797 798 799 800 801  generate_contassign($mod,$net_name."[".$i."]",$ip->net->name); } else { generate_contassign($mod,$net_name."[".$i."]",$net_name_tmp."[".$i."]"); } } } } # 5.) Connect the tmp net to the output pin that forwards the signal to the FIC  Stefan Tauner committed May 04, 2018 802 803  # If the driver is not a vector a simple assignment is fine, else if (!$driver_is_vector) {  Stefan Tauner committed May 04, 2018 804 805 806  $logger->debug(" assigning \"" .$op->net->name . " = " . $net_name_tmp . "\""); generate_contassign($mod, $op->net->name,$net_name_tmp); } else {  Stefan Tauner committed May 04, 2018 807 808  $logger->debug(" assigning \"" .$op->net->name . " = " . $net_name_tmp ."[".$driver_bit."]\""); generate_contassign($mod,$op->net->name, $net_name_tmp."[".$driver_bit."]");  Stefan Tauner committed May 04, 2018 809  }  Stefan Tauner committed May 04, 2018 810  $mod->link;  Stefan Tauner committed May 04, 2018 811 812 813 814 815 816  # Normally we set first_instrumented_bit way earlier but since we autogenerate # the port we don't have the respective net available before linking thus... if ($driver_is_vector && $driver_is_port && !defined($net_tmp)) { my $port_net =$mod->find_net($net_name_tmp);$port_net->userdata("first_instrumented_bit", $driver_bit); }  Christian Fibich committed May 04, 2018 817 818 819  return undef; }  Christian Fibich committed May 04, 2018 820 821 822 ## @method public validate_driver($net_path, $driver_path,$driver_type) # @brief Check if the given driver is valid for the given net #  Christian Fibich committed May 04, 2018 823 824 # Check if the driver specified by $driver_type and$driver_path # is actually connected to the net specified by $net_path  Christian Fibich committed May 04, 2018 825 826 827 828 829 830 831 # # @param net_path The hierarchical path of the net, separeted by HIERSEP # @param driver_path The hierarchical path of the driver object, separated by HIERSEP # @param driver_type The type of the driver object, one of {PIN, PORT, ASSIGN} # # @returns STRING if an error occurred # @returns undef if successfull  Christian Fibich committed May 04, 2018 832 sub _validate_driver {  Christian Fibich committed May 04, 2018 833  my$logger = get_logger("");  Christian Fibich committed May 04, 2018 834  my ($self,$net_path, $driver_path,$driver_type) = @_;  Christian Fibich committed May 04, 2018 835   Christian Fibich committed May 04, 2018 836  my $connection_object =$self->get_connection_object($driver_path,$driver_type);  Christian Fibich committed May 04, 2018 837  my $connections = {};  Christian Fibich committed May 04, 2018 838 $self->_get_net_connections_from_path($net_path,$connections);  Christian Fibich committed May 04, 2018 839   Christian Fibich committed May 04, 2018 840 841  goto FAIL if (!defined $connection_object);  Christian Fibich committed May 04, 2018 842 843  my @in_drivers = grep {$_ == $connection_object } @{$connections->{'drivers'}}; my @in_connections = grep { $_ ==$connection_object } @{$connections->{'connected'}};  Christian Fibich committed May 04, 2018 844   Christian Fibich committed May 04, 2018 845  goto FAIL if (@in_drivers == 0 && @in_connections == 0);  Christian Fibich committed May 04, 2018 846 847  return undef;  Christian Fibich committed May 04, 2018 848 849 850 851 852  FAIL: my$msg = "No possible driver found"; $logger->error($msg); return $msg;  Christian Fibich committed May 04, 2018 853 854 }  Christian Fibich committed May 04, 2018 855 856 857 858 859 860 861 862 863 ## @function private _select_driver($connected,$net) # @brief Prompt the user to select a driver for a net from a set of given cells/outputs # # @param connected list reference containing connected Verilog::Perl instances # @param net the Verilog::Perl::Net instance to select the driver for # # @returns STRING if an error occurred # @returns Driver object if successful sub _select_driver {  Christian Fibich committed May 04, 2018 864  my ($connected, $net) = @_;  Christian Fibich committed May 04, 2018 865   Christian Fibich committed May 04, 2018 866  print "Select driver for net " .$net->name . ": \n";  Christian Fibich committed May 04, 2018 867  my $di;  Christian Fibich committed May 04, 2018 868 869  for ($di = 0 ; $di < @{$connected} ; $di++) { printf("[%d] %s\n",$di, FIJI::Netlist->_connection_tostr(@{$connected}[$di]));  Christian Fibich committed May 04, 2018 870  }  Christian Fibich committed May 04, 2018 871  printf("[x] none of the above.\n", $di);  Christian Fibich committed May 04, 2018 872  my$sel;  Christian Fibich committed May 04, 2018 873  while (1) {  Christian Fibich committed May 04, 2018 874  $sel = ;  Christian Fibich committed May 04, 2018 875  if ($sel =~ m/[0-9]+/ && defined @{$connected}[$sel]) {  Christian Fibich committed May 04, 2018 876  last;  Christian Fibich committed May 04, 2018 877  } elsif ($sel =~ m/[xX]/) {  Christian Fibich committed May 04, 2018 878  my$msg = "No driver selected for net " . $net->name;  Christian Fibich committed May 04, 2018 879  return$msg;  Christian Fibich committed May 04, 2018 880 881  } else { print "Invalid driver.\n";  Christian Fibich committed May 04, 2018 882 883 884  } } return @{$connected}[$sel];  Christian Fibich committed May 04, 2018 885 886 }  Christian Fibich committed May 04, 2018 887 888 889 ## @method private _connection_tostr ($connection,$conn_str_list_ref) # @brief Stringifies a connection information #  Christian Fibich committed May 04, 2018 890 # The string is in the format \: \  Christian Fibich committed May 04, 2018 891 # Where '|' can be any HIERSEP and TYPE is one of {PIN, PORT, ASSIGN}  Christian Fibich committed May 04, 2018 892 # and optionally pushes a hash {path=>...,type=>...,} onto the list @$conn_str_list_ref  Christian Fibich committed May 04, 2018 893 #  Christian Fibich committed May 04, 2018 894 895 896 # @param connection the connection to print # @param conn_str_list_ref optional list where a hash describing the connection is pushed #  Christian Fibich committed May 04, 2018 897 # @returns STRING in the format \: \  Christian Fibich committed May 04, 2018 898 sub _connection_tostr {  Christian Fibich committed May 04, 2018 899  my ($self, $connection,$conn_str_list_ref) = @_;  900 901  my $path; my$type;  Stefan Tauner committed May 04, 2018 902  my $str;  Christian Fibich committed May 04, 2018 903   Christian Fibich committed May 04, 2018 904  if (ref($connection) eq "Verilog::Netlist::Pin") {  Stefan Tauner committed May 04, 2018 905  $path =$connection->cell->module->name . HIERSEP . $connection->cell->name . HIERSEP .$connection->name;  906  $type = "PIN";  Stefan Tauner committed May 04, 2018 907 $str = $type . ": " .$path  Christian Fibich committed May 04, 2018 908  } elsif (ref($connection) eq "Verilog::Netlist::Port") {  Stefan Tauner committed May 04, 2018 909 $path = $connection->module->name . HIERSEP .$connection->name;  910  $type = "PORT";  Stefan Tauner committed May 04, 2018 911 $str = $type . ": " .$path  Stefan Tauner committed May 04, 2018 912  } elsif (ref($connection) eq "Verilog::Netlist::ContAssign") {  Christian Fibich committed May 04, 2018 913 $path = $connection->module->name . HIERSEP .$connection->lhs . EQUALSEP . $connection->rhs;  914 $type = "ASSIGN";  Christian Fibich committed May 04, 2018 915  $str =$type . ": " . $connection->lhs . EQUALSEP .$connection->rhs;  Christian Fibich committed May 04, 2018 916  }  Stefan Tauner committed May 04, 2018 917 918  push @{$conn_str_list_ref}, {path =>$path, type => $type} if defined$conn_str_list_ref; return $str  919 920 }  Christian Fibich committed May 04, 2018 921 922 923 ## @method public get_connection_object ($connection_path,$connection_type) # @brief Retrieves the connection object specified by path and type #  Stefan Tauner committed May 04, 2018 924 # Retrieves a reference to the Verilog::Pin, Verilog::Port or Verilog::ContAssign  Christian Fibich committed May 04, 2018 925 926 927 928 929 # Object specified by the parameters # # @param connection_path the hierarchichal PATH|To|the|object # @param connection_type the type of the object {PIN,PORT,ASSIGN} #  Stefan Tauner committed May 04, 2018 930 # @returns the Verilog::Pin, Verilog::Port or Verilog::ContAssign Object specified by the parameters  Christian Fibich committed May 04, 2018 931 sub get_connection_object {  Christian Fibich committed May 04, 2018 932  my$logger = get_logger("");  Christian Fibich committed May 04, 2018 933  my ($self,$connection_path, $connection_type) = @_;  934 935  my$rv;  Christian Fibich committed May 04, 2018 936  my $SEP = HIERSEP;  937   Christian Fibich committed May 04, 2018 938 939  my @path_elements = _split_path($connection_path);  Christian Fibich committed May 04, 2018 940  if ($connection_type eq "PIN") {  Christian Fibich committed May 04, 2018 941 942 943  if (@path_elements == 3) { my ($module_name, $cell_name,$pin_name) = @path_elements;  944   Christian Fibich committed May 04, 2018 945  $logger->trace("Looking for pin named \"$pin_name\" in cell \"$cell_name\" of module \"$module_name\"...");  946   Christian Fibich committed May 04, 2018 947 948 949  my $mod =$self->{'nl'}->find_module($module_name); my$cell = $mod->find_cell($cell_name) if (defined $mod); my$pin = $cell->find_pin($pin_name) if (defined $cell);  950 951 $rv = $pin; }  Christian Fibich committed May 04, 2018 952  } elsif ($connection_type eq "PORT") {  Christian Fibich committed May 04, 2018 953  if (@path_elements == 2) {  954   Christian Fibich committed May 04, 2018 955  my ($module_name,$port_name) = @path_elements;