Extending xdc.runtime Timestamps/Example 1

From RTSC-Pedia

Jump to: navigation, search
revision tip
—— LANDSCAPE orientation
[printable version]  offline version generated on 18-Nov-2017 00:11 UTC

Extending xdc.runtime Timestamps/Example 1

A TI C64-plus ITimestampProvider Module

Contents

A Device-Specific Timestamp Implementation

In the following sections we develop a simple ITimestampProvider that illustrates how to create leverage platform-specific timing facilities. In this case, we show how to leverage the TI C64-plus processor's 64-bit CPU clock register (TSCH:TSCL).

How to Use the C64-plus Timestamp Module

Before looking at the implementation of a C64-plus Timestamp module, we show how such a module might be used in an application. We begin with a simple "test" application which simply uses the xdc.runtime.Timestamp module and show how this application is configured.

app.c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
#include <xdc/std.h>
 
#include <xdc/runtime/System.h>
#include <xdc/runtime/Timestamp.h>
#include <xdc/runtime/Types.h>
 
/* ======== main ======== */
Int main(Int argc, String argv[])
{
    Types_FreqHz freq;
 
    Timestamp_getFreq(&freq);
    System_printf("freq = {0x%x : 0x%x}\n", freq.hi, freq.lo);
 
    System_printf("time = 0x%x\n", Timestamp_get32());
    System_printf("time = 0x%x\n", Timestamp_get32());
 
    return (0);
}

The full name of the timestamp provider is examples.runtime.c64p.Timestamp and the application above explicitly references the System and Timestamp modules from the xdc.runtime package. So, the following configuration script suffices to declare all used modules and "bind" examples.runtime.c64p.Timestamp as the timestamp provider for the xdc.runtime package's Timestamp module used by the application.

app.cfg
 
 
 
 
 
var System = xdc.useModule("xdc.runtime.System");
var Timestamp = xdc.useModule("xdc.runtime.Timestamp");
 
Timestamp.SupportProxy =
    xdc.useModule("examples.runtime.c64p.Timestamp");

The name examples.runtime.c64p.Timestamp might seem to be a poor choice for the C64-plus timestamp provider; the module name Timestamp within the examples.runtime.c64p package might conflict with the same named module in the xdc.runtime package. In fact, because these modules are in separate packages and all module symbols are scoped by the package name, both the xdc.runtime.Timestamp and examples.runtime.c64p.Timestamp modules can be linked into a single application without problems. But why use the same name, isn't it confusing?

The examples.runtime.c64p.Timestamp name was chosen for this example to illustrate an interesting design pattern that makes it possible and even desirable to confuse this module with the xdc.runtime.Timestamp module. Both modules inherit the xdc.runtime.ITimestampClient interface and, in fact, xdc.runtime.Timestamp module's C interface only provides the methods declared in ITimestampClient. So what? Any use of xdc.runtime.Timestamp in your code can be replaced with examples.runtime.c64p.Timestamp without affecting you program's behavior. Even better, you can replace all uses of xdc.runtime.Timestamp within any source file with examples.runtime.c64.Timestamp by making a one line change to the file.

For example, in the application above, we can replace all calls to xdc.runtime.Timestamp methods with calls to corresponding examples.runtime.c64p.Timestamp methods by simply changing the module header file include statement.

app.c
 
 
 
 
 
>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
#include <xdc/std.h>
 
#include <xdc/runtime/System.h>
#include <xdc/runtime/Types.h>
 
#include <examples/runtime/c64p/Timestamp.h>
 
/* ======== main ======== */
Int main(Int argc, String argv[])
{
    Types_FreqHz freq;
 
    Timestamp_getFreq(&freq);
    System_printf("freq = {0x%x : 0x%x}\n", freq.hi, freq.lo);
 
    System_printf("time = 0x%x\n", Timestamp_get32());
    System_printf("time = 0x%x\n", Timestamp_get32());
 
    return (0);
}

Comparing this example with the original application, to only line that changed is the module include header >. All references within the application to the module Timestamp now reference the examples.runtime.c64p.Timestamp module rather than the xdc.runtime.Timestamp module, but no change to these references is required!

This is cute, but is it useful? Imagine an application which uses Timestamp services throughout the code bases. In most cases, the services provided by xdc.runtime.Timestamp are sufficient but if there are a file parts of the system that require C64-plus specific features it is easy to simply replace a single line. Code that relies on just the xdc.runtime.Timestamp services can be moved freely throughout the code base without much thought. Code that uses c64-plus features can be moved into previously platform-independent portions by simply changing the header file; any existing use of xdc.runtime.Timestamp will operate exactly as before.

How to Implement the C64-plus Timestamp Module

The Timestamp Module

The Timestamp module must implement the ITimestampProvider interface. Notice that the name of this module is identical to the name of the Timestamp module in the xdc.runtime package. Since this module is in a separate package, there is no danger of link-time conflicts and, as shown above, it makes it very easy for clients to switch between a device specific timestamp module and the generic time stamp module xdc.runtime.Timestamp.

Timestamp.xdc
 
 
 
 
 
 
 
 
 
 
 
import xdc.runtime.Types;
 
/*!
 *  ======== Timestamp ========
 *  Example implementation of ITimestampProvider
 */
@ModuleStartup
module Timestamp inherits xdc.runtime.ITimestampProvider
{
    config Types.FreqHz freq = {hi:0, lo: 600 * 1000000};
}

The actual implementation of the specification above is shown below. In this case, the implementation involves both C and assembly language.

Timestamp.c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
#include <xdc/std.h>
 
#include <xdc/runtime/Startup.h>
#include <xdc/runtime/Types.h>
 
#include "package/internal/Timestamp.xdc.h"
 
extern void C64P_readtime(Bits32 *hi, Bits32 *lo);
extern void C64P_resetime(void);
 
/* ======== Timestamp_Module_startup ======== */
Int Timestamp_Module_startup(Int phase)
{
    C64P_resetime();  /* reset and start timer */
    return (Startup_DONE);
}
 
/* ======== Timestamp_get32 ======== */
Bits32 Timestamp_get32()
{
    Bits32 hi, lo;
    C64P_readtime(&hi, &lo);
    return (lo);
}
 
/* ======== Timestamp_get64 ======== */
Void Timestamp_get64(Types_Timestamp64 *result)
{
    C64P_readtime(&result->hi, &result->lo);
}
 
/* ======== Timestamp_getFreq ======== */
Void Timestamp_getFreq(Types_FreqHz *freq)
{
    freq->lo = Timestamp_freq.lo;
    freq->hi = Timestamp_freq.hi;
}
c64p_readtime.asm
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
; ======== _C64P_readtime ========
;
;  void C64P_readtime(Bits32 *hi, Bits32 *lo);
;
    .global _C64P_readtime
_C64P_readtime:
    .asmfunc
    b b3          ; return to caller & disable ints
    mvc TSCL, b6  ; get TSCL (must read this first)
    mvc TSCH, b5  ; get TSCH
    stw b6, *b4   ; *lo = a6
    stw b5, *a4   ; *hi = b5
    nop           ; additional delay for branch
    .endasmfunc
;
; ======== _C64P_resetime ========
;
;  void C64P_resetime(void);
;
    .global _C64P_resetime
_C64P_resetime:
    .asmfunc
    b    b3       ; return to caller 
    zero b4       ; b4 = 0
    mvc  b4, TSCL ; TSCL = 0
    nop  3        ; additional delay for branch
    .endasmfunc
 

The Package Files

Since all modules must live in a package we also need to create a two other files:

  1. package.xdc - a file that define the package's name and identifies the modules it contains, and
  2. package.bld - a file that specifies which targets should be used to build the sources contained in this package.

package.xdc
 
 
 
package examples.runtime.timestamp.c64p { 
    module Timestamp; 
}
package.bld
 
 
 
 
 
 
 
for (var i = 0; i < Build.targets.length; i++) {
    var targ = Build.targets[i];
    if (targ.isa == "64P") {
        var lib = Pkg.addLibrary("lib/" + Pkg.name, targ);
        lib.addObjects(["Timestamp.c", "c64p_readtime.asm"]);
    }
}

The package.xdc file is largely self explanatory; it defines the name of the package examples.runtime.logger and it specifies the modules contained in the package, Timestamp.

The package.bld file, on the other hand, requires some explanation. The existence of package.bld indicates that the package is (re)buildable - unless the end-user is expected to build the package, deployed packages omit this file. The contents of this package.bld file indicate that the package contains a library in the lib/ sub-directory containing the compiled version of Timestamp.c and an assembled version of c64p_readtime.asm. Remarkably, this package.bld file is sufficient to compile Timestamp.c and c64p_readtime.asm, archive it into a library, and create a binary release of this package that supports all targets supported by the producer's build environment that also generate code for the C64P ISA.

[printable version]  offline version generated on 18-Nov-2017 00:11 UTC
Copyright © 2008 The Eclipse Foundation. All Rights Reserved
Personal tools
package reference