How to fix Verilog::VCD::Writer error: Can't locate object method addSignal? - perl

I suspect I made an import error in Perl.
There is a Perl module Verilog::VCD::Writer to write a VCD file. However, when I copy its SYNOPSIS code to have a try, it always raises the error:
Can't locate object method "addSignal" via package
"Verilog::VCD::Writer" at tester.pl line 10.
The SYNOPSIS calls addComment and addModule before addSignal so there should be no problems in my installation.
addSignal is a function defined in Verilog/VCD/Writer/Module.pm, and the other two are defined in Verilog/VCD/Writer.pm. Even I add Verilog::VCD::Writer::Module, still the debugger go to package Writer to find the addSignal method.
If I call the addSignal function in this way:
$writer->Verilog::VCD::Writer::Module::addSignal("TX",7,0);
Can't locate object method "signals_push" via package
"Verilog::VCD::Writer" at
/home/cqsun/lib/perl5/lib/site_perl/5.18.2/Verilog/VCD/Writer/Module.pm
line 41.
Module.pm defined signals_push in a hash, and clearly the debugger didn't find it.
I suspect there is something wrong, but I don't know where it is.
The webpage for this package is http://search.cpan.org/~jvs/Verilog-VCD-Writer-0.002/lib/Verilog/VCD/Writer.pm

This is a documentation bug.
The code in the SYNOPSIS section of the POD has a few problems. The error you see is from the line:
my $TX=$writer->addSignal("TX",7,0); #Add Signals to top
The code used the wrong object handle for the addSignal method. $writer is an object of the Verilog::VCD::Writer module, and it does not have an addSignal method. However, addSignal is a method of the Verilog::VCD::Writer::Module module. The code needs to use $top instead of $writer.
The next line has the same problem:
my $RX=$writer->addSignal("RX",7,0);
Finally, the following line has a syntax error because it is missing the comment delimiter (#) after the semicolon:
my $dut=$top->addModule("DUT"); Create SubModule
Here is a fixed version of the code which runs without errors and generates a VCD output file:
use Verilog::VCD::Writer;
my $writer = Verilog::VCD::Writer->new(timescale=>'1 ns',vcdfile=>"test.vcd");
$writer->addComment("Author:Vijayvithal");
my $top = $writer->addModule("top"); # Create toplevel module
my $TX = $top->addSignal("TX",7,0); #Add Signals to top
my $RX = $top->addSignal("RX",7,0);
my $dut = $writer->addModule("DUT"); #Create SubModule
$dut->dupSignal($TX,"TX",7,0); #Duplicate signals from Top in submodule
$dut->dupSignal($RX,"RX",7,0);
$writer->writeHeaders(); # Output the VCD Header.
$writer->setTime(0); # Time 0
$writer->addValue($TX,0); # Record Transition
$writer->addValue($RX,0);
$writer->setTime(5); # Time 1ns
$writer->addValue($TX,1);
$writer->addValue($RX,0);
I uploaded a patch to the bug report you opened:
https://rt.cpan.org/Ticket/Display.html?id=123724
Also, the Create SubModule comment seems misleading. Perhaps the author intended to use the addSubModule method instead of the addModule method.

Related

How to remove the ports from my include files from my file using Verilog::SigParser

I'm using Verilog package in Perl, so I can read a Verilog file and extract the ports the are inside. For this purpose, I'm using Verilog::SigParser, if you are new here you should know that Verilog::SigParser provide callbacks for when a signal is declared, a module instantiated or a module defined. The file you are passing is obviously a Verilog file. The problem here is I I'm trying to use SigParser in a file which includes inside another file (just it's name, not its content, scroll down for better understanding), and it looks like ports from the include file are getting inside my %arr(), which later on gives me some mistakes because of course I can't form the testbench. So let me show you some code:
This is my perl file:
#On top of the file
package MyParser
use Verilog::SigParser
$filename = /user/home/verilog.v
....
use base qw(Verilog::SigParser);
my %arr = (); #In this array, all module inputs and outputs are being saved.
#Process my verilog file
my $vf Verilog::Preproc->new(keep_comments->0);
$vf->open(filename=>$filename) or die $!;
open(FH,'>',/users/home/port_file);
print(FH, %arr()); #HERE IT IS INCLUDING NOT JUST THE PORTS FROM VERILOG.V BUT ALSO THE ONES FROM HAPPY.VP, I want only the ones from verilog.v
close(FH);
Top file verilog.v
`include happy.vp
module top();
.
#lots of inputs and outputs
.
.
endmodule
File happy.vp
module happy();
#some other inputs or outputs I don't want in my ports file.
endmodule
A SystemVerilog package cannot access any date type or data item declared outside of the scope of that package except via import from another previously compiled package. There is no way to import from a compilation unit.
typedef int t; // outside space is part of some compilation unit
package p;
t v; // reference to t is illegal
endpackage

Why does this halt my perl application package 'not registered for warnings'

I am working with an in house web gateway frame work in perl. And now I am trying to use Image::Magick::Thumbnail to create a thumbnail image.
But if I have this line
my ($thumb, $x, $y) = Image::Magick::Thumbnail::create($image, 50);
I get the following error.
package 'Image::Magick::Thumbnail' not registered for warnings
I have tracked this down to line 313 of warnings.pm
Croaker("package '$category' not registered for warnings")
But I'm not sure why this halts my program any ideas?
use warnings::register; creates a warnings category with the same name as the current package.
Image::Magick::Thumbnail checks if warnings of category Image::Magick::Thumbnail are enabled, but doesn't actually create such a category using use warnings::register;.
The line is there in the code, but it's commented out?! You could edit the module to uncomment that line to solve the problem. Including the following in your script should also do the trick:
{
package Image::Magick::Thumbnail;
use warnings::register;
}

Perl Win32::Console error

My little Perl script on Windows tried to call a dependency library C:/strawberry/perl/vendor/lib/Term/ReadPassword/Win32.pm which was written by somebody else.
Here is a part of C:/strawberry/perl/vendor/lib/Term/ReadPassword/Win32.pm:
package Term::ReadPassword::Win32;
use strict;
if (IsWin32()) {
eval('use Win32');
eval('use Win32::Console');
eval('use Win32API::File');
} else {
eval('use Term::ReadPassword');
}
...
my $CONIN = new Win32::Console(Win32::Console::STD_INPUT_HANDLE());
my $CONOUT = new Win32::Console(Win32::Console::STD_ERROR_HANDLE());
...
The following error showed up when running my script:
Undefined subroutine &Win32::Console::STD_INPUT_HANDLE called at C:/strawberry/perl/vendor/lib/Term/ReadPassword/Win32.pm line 58, <STDIN> line 2.
Using parens is legit, as discussed How can I optionally use Win32::Console and its constants in a cross platform way? and I've looked up http://metacpan.org/pod/Win32::Console.
Thanks.
eval('use Win32::Console');
doesn't do any error checking. If Win32::Console fails to load for any reason, the code will proceed anyway until it actually calls one of the subroutines that was supposed to have been loaded, but wasn't. At that point, you'll get failures like you describe.
What happens if you add use Win32::Console; to your script? (I'm guessing you'll get some kind of error saying Win32::Console couldn't be loaded.)

Overriding a module that is used by a program I'm testing

I am revising a Perl program and I wanted a test harness that could run the original version of the program (call it launch_rockets.pl) and collect the standard output, but somehow skip the system calls that occur inside launch_rockets.pl. The following code successfully overrides system inside launch_rockets.pl:
use subs qw(system);
my $SYSTEM_SUCCESS = 0;
sub system {
print "***\n";
print "system #_\n";
print "***\n\n";
return $SYSTEM_SUCCESS;
}
local #ARGV = #test_args;
do 'launch_rockets.pl';
So far so good. But launch_rockets.pl also contains
use Proc::Background;
and later
Proc::Background->new('perl', 'launch_missiles.pl');
I could copy launch_rockets.pl into a sandbox where Proc::Background is replaced by a stub, but I was wondering if there was any override strategy that would be effective inside a do FILE call in the file's original environment.
use lib '/my/test/library/path';
lib prepends the directory to #INC, so /my/test/library/path/Proc/Background.pm will be the file that gets loaded. Put whatever code you want in there.
Another alternative would be:
{
package Proc::Background;
... # Put stub code here
} # end of package Proc::Background
$INC{'Proc/Background.pm'} = 1; # Make Perl think Proc::Background is loaded

How can I access the Apache server configuration in a BEGIN block in mod_perl?

I've been trying to switch from using PerlSetEnv to using custom configuration directives. I have my configuration module with a copy of set_val from the docs:
sub set_val
{
local our ($key, $self, $parms, $arg) = #_;
$self->{$key} = $arg;
unless ($parms->path)
{
local our $srv_cfg = Apache2::Module::get_config($self, $parms->server);
$srv_cfg->{$key} = $arg;
}
}
...which is called by every custom directive sub. Then I have in my .conf:
PerlLoadModule MyModule::ServerConfig
MyCustomDirective 'hello'
This works fine in that httpd -t okays the file's syntax. The problem is that I can't seem to get at the value from the config file from within a BEGIN block, which I need to do.
I've tried tinkering with all sorts of things:
BEGIN
{
use Apache2::CmdParms ();
# use Apache2::Directive ();
use Apache2::Module ();
# use Apache2::ServerUtil ();
# use Apache2::RequestUtil ();
use Data::Dump;
warn ddx(Apache2::Module::get_config('MyModule::ServerConfig', Apache2::CmdParms->server));
# warn ddx(Apache2::Directive->as_hash);
# warn Apache2::ServerUtil->dir_config('MyCustomDirective);
# warn Apache2::CmdParms->server->server_hostname();
}
...but to no avail. Most of my efforts (trying to access CmdParms->server for instance) result in Parent: child process exited with status 3221225477 -- Restarting and an automatic restart of Apache as it says. If I pass ServerUtil->server to get_config(), the server stays alive but the warning only prints out '1'.
I read somewhere that this is because you can't get at anything request-related within a BEGIN block, because requests vary. It kind of makes sense, except that with PerlOptions +GlobalRequest I have been able to see $ENV within a BEGIN block, so why wouldn't I be able to see my own directives, just as dependent as they are on how the request happens? Especially confusing is that if I try to pass Apache2::RequestUtil->request->per\_dir\_config() to get_config(), it says Global $r object is not available. If that's true in a BEGIN block, how is it I can get at $ENV?
Try add what you want to import function to other module and use this module in code where you usually put BEGIN block. It should work same. May be it helps.
Partly, Dump isn't being used correctly. This works better:
use Data::Dump qw(pp);
warn pp(Apache2::Module::get_config('MyModule::ServerConfig', Apache2::ServerUtil->server));
However, it doesn't show any directives that appear within <Directory> blocks.
In my particular case, though, I don't need that functionality, on second thought; that just happens to be where I had stuck them.