Overview

JavaScript is very rich and programmer-friendly, but Perl is probably still the most pervasive scripting language in use today. Giving programmers the ability to use DSS from Perl brings more customers on board. This can be achieved by using the Perl Inline::Java module.

How Does It Work?

The Perl Inline module has been around for many years. It lets Perl developers write/leverage C code from within a Perl environment. In the last several years, more language support has been added to the Inline module. Inline::Java was developed in 2001. With this we can access DSS Java classes in Perl. A Java compiler is launched and the Java code is compiled. Then Perl asks the Java classes what public methods have been defined. These classes and methods are available to the Perl program as if they had been written in Perl. Is it efficient? Yes, the process of interrogating the Java classes for public methods occurs the first time you run your Java code. The namespace is cached, and subsequent calls use the cached version.

Prerequisites

Software

  • Code Composer Studio (CCS)
  • Installation of Java 2 Software Development Kit (JDK). Depending on your version of CCS, you will need a 32-bit or 64-bit version of the JDK.
    OS Requires 32-bit JDK Requires 64-bit JDK
    Windows Up to CCS v8.x CCS v9 and above
    MacOS None All
    Linux Up to CCS v6.1.3 CCS v6.2.0 and above

    You likely already have a Java Runtime Environment (JRE) installed (one comes bundled with CCS), but you need the JDK to get the Java compiler (javac).

  • Installation of Perl. ActivePerl and StrawberryPerl are two of the more popular ones on Windows.
  • Installation of Inline::Java. Note that you will need to have both the JDK and Perl installed to install Inline::Java.

    You can install Inline::Java from CPAN. You can find more details on installing CPAN modules here. For example, to install Inline::Java via CPAN from the command line using StrawberryPerl (assuming proxy configuration is set or unneeded), run cpan and type install Inline::Java at the prompt.

    > cpan
    cpan> install Inline::Java
    

    This may take a while as it will bring in all the dependent modules.

    Problems installing Inline::Java?

    • You might need to set the JAVA_HOME environment variable to the install location of the JDK. For example set JAVA_HOME=C:\Java\jdk1.8.0_202.

    • If you use a proxy server or firewall, you may need to set the HTTP_PROXY environment variable (for example set HTTP_PROXY=http://proxy.company.com:8008, this will vary based on your setup).

    • If the command above doesn't work, you can also try the more direct

      > cpan
      cpan> install ETJ/Inline-Java-0.66.tag.gz
      

    What about Cygwin? Linux? Unix?

    Also works fine. In addition, Cygwin JNI support got added in 0.52.

Environment Setup

The dss.jar file must be added the the CLASSPATH. The file can be found in

<CSS_DIR>/ccs_base/DebugServer/packages/ti/dss/java/dss.jar

where <CSS_DIR> refers to the location of your version of CCS. (For example in CCS 8 on Windows it might be C:\ti\ccsv8).

You may also want to set the PERL_INLINE_JAVA_J2SDK environment variable as the location of the JDK you want Inline::Java to use. If this variable is not set, Inline::Java will default to the JDK that was used when it was installed.

This can be done manually, or it can be automated by a batch or shell script. An example batch file (setpath.bat) is provided in the perl_inlinejava example folder (found in <CCS_DIR>/ccs_base/scripting/examples/DebugServerExamples/perl_inlinejava). Simply update the paths for DSS_ROOT and PERL_INLINE_JAVA_J2SDK.

@echo off
REM
REM File: setpath.bat
REM
REM This batch file will set up the environment to run DSS with Perl
REM Inline::Java. Contents of this batch file must be modified to match the
REM user's environment
REM

REM ============================================================================
REM Modify these paths to match the user's environment.

REM Root DSS install location
set DSS_ROOT=C:\ti\ccsv8

REM Root JDK install location
REM If omitted, Inline::Java will default to the JDK used when it was installed
set PERL_INLINE_JAVA_J2SDK=C:\Program Files\Java\jdk1.8.0_202

REM ============================================================================

REM Set CLASSPATH
set CLASSPATH=%CLASSPATH%;%DSS_ROOT%\ccs_base\DebugServer\packages\ti\dss\java\dss.jar

Creating a Script

Using Inline::Java

To use Inline::Java with DSS you must:

  • tell Inline::Java to explicitly STUDY the main DSS class (ScriptingEnvironment) so it can be used from Perl,
  • turn on AUTOSTUDY which makes Inline::Java automatically study unknown classes as it encounters them,
  • proxy Java's importPackage() by assigning a new namespace TraceLevel to the fully scoped package name so we can then use the shorter namespace $TraceLevel::ALL instead of $DSS_SCRIPTING::com::ti::ccstudio::scripting::environment::TraceLevel::ALL,
  • enable access to the ScriptingEnvironment Java class constructor.

For reuse and usability purposes, the steps described above have been added to a Perl module (DSS_SCRIPTING.pm) which is provided with DSS (in the perl_inlinejava example folder).

#=============================================================================
# POD Documentation First ...
#=============================================================================

=head1 NAME

DSS_SCRIPTING.pm

=head1 SYNOPSIS

Perl module for using Debug Server Scripting. Leverages Inline::Java to
interface with DSS's Java classes

=head1 USAGE

   use DSS_SCRIPTING;

=head1 DESCRIPTION

Perl module for using Debug Server Scripting. Leverages Inline::Java to
interface with DSS's Java classes

Main purpose is to hide the funky details of 'STUDY' and 'CLASSPATH'
that perl users dont need to know.

This module lets perl users leverage the Scripting package to call the core
APIs. In addition we also use config option 'AUTOSTUDY' which brings in all
other DSS Java classes we need to work with.

=head1 FUNCTIONS DEFINED

Nothing - no 'wrappers' required at present

=cut

#=============================================================================
# Code starts here ...
#=============================================================================

package DSS_SCRIPTING;

use strict;
use warnings;

require Exporter;
our @ISA = qw(Exporter);
our @EXPORT_OK = qw();

#
# Base Java CLASSPATH is set as an environment variable and must have at least
# <myDssdir>/scripting/lib/dss.jar in it
#

#
# Bring in the Java classes from DSS that we need.
# AUTOSTUDY helps in not requiring us to list out all classes we need
# individually. For example openSession() returns a DebugSession class
# which Inline::Java automatically 'studies' by virtue of AUTOSTUDY.
#
# Note, however that we *must* (a) STUDY 1 class to guide AUTOSTUDY's
# context (b) explicitly specify the TraceLevel class since we
# explicitly use its member data (ie its context is not returned by
# a TraceLevel() API like the other classes)
#
use Inline  ( Java  => 'STUDY',
             STUDY => ['com.ti.ccstudio.scripting.environment.ScriptingEnvironment',
                       'com.ti.ccstudio.scripting.environment.TraceLevel',
                       'java.lang.System',
                      ],
             AUTOSTUDY => 1,
#             DEBUG => 5,
           );

#
# Our perl proxy for Java's importPackage(). We assign a new namespace TraceLevel
# to the fully scoped package name so we can then use the shorter namespace
# $TraceLevel::ALL instead of
# $DSS_SCRIPTING::com::ti::ccstudio::scripting::environment::TraceLevel::ALL
# Internally this creates a TraceLevel symbol table which holds typeglobs
# to each of the class fields.
#
BEGIN {
    %{TraceLevel::} = %{DSS_SCRIPTING::com::ti::ccstudio::scripting::environment::TraceLevel::};
}

# enable access to the DebugserverEnvironment Java class constructor
sub new {
    my $class = shift;
    return DSS_SCRIPTING::com::ti::ccstudio::scripting::environment::ScriptingEnvironment->instance();
}

1;

To ensure Perl can find the DSS_SCRIPTING package, you can add the file to you package path. One way is to add the containing folder to the PERL5LIB environment variable. DSS_SCRIPTING.pm can then be leveraged in a Perl script by

# import module abstracting the DSS class details
use DSS_SCRIPTING;

# call the DSS class constructor(s) we need to create our scripting environment object
my $dss = new DSS_SCRIPTING();

With the main scripting object, the rest of the DSS APIs are available for use:

# Create a log file to log script execution
$dss->traceBegin("dssScriptLog.xml", "DefaultStylesheet.xsl");

# The default timeout is 'infinite'.  Set ours to something shorter, 10s
$dss->setScriptTimeout(10000);

# Make the log and console file really verbose
$dss->traceSetConsoleLevel($TraceLevel::INFO);
$dss->traceSetFileLevel($TraceLevel::ALL);

# Open a debug session
my $debugServer = $dss->getServer("DebugServer.1");

...

Example

An example Perl script (dss_simple.pl) is provided in the perl_inlinejava examples folder. The script takes a *.out file and a *.ccxml setup file as its parameters.

> perl dss_simple.pl my_out.out my_target_config.ccmxl

Error Handling

Starting in version 0.31, Inline::Java lets you catch exceptions in Perl as objects when they are thrown from Java using the regular Perl exception tools: eval and $@.

There are many good reasons for using exception handling. One reason might be in running 1000 tests on 1000 different .out files—if one of the .out files is misspelled or passed incorrectly, you might not want to kill the entire script. Instead you might want to catch the exception and simply warn the user indicating which file was problematic.

#
# Load the program from the out file.
# Example of how to handle Java exceptions in perl with Inline::Java
# This is Perl's equivalent of Java try-catch
#
eval { $tgt->{memory}->loadProgram($out_file); };
if ($@) {
     die "Failed to load $out_file $!";
}

Performance

When you use Inline::Java, the Java compiler (javac) is launched and the DSS Java code is compiled. Then, Perl asks the Java classes what public methods have been defined. The process of interrogating the Java classes for public methods occurs the first time you run your Java code. The namespace is cached, and subsequent calls use the cached version. The bottom line is that there is an initial 1-2sec hit but then calls to the methods are near identical to calls from Javascript directly.

Inline::Java now also provides a JNI extension that allows you to load the JVM as shared object instead of running it as a separate process.

Known Issues

  • If CCS is installed in a path with spaces in it (like C:\Program Files\Texas Instruments), there may be an issue running the Perl example (dss_simple.pl) from within the directory. This can be worked around by changing the working directory to a path without spaces.