Tuesday, December 20, 2016

SOAP and REST.

Web Services
  • Transport Protocols : SOAP, REST
  • Respective registries to shared data.
  • Message integrity and non-repudiation
  • Reliable messaging
  • Business process flow
  • Protocol negotiation
  • Security
  • Transactions and process flow
  • Data independence for programming languages, middle-ware systems and DBMS
    • typing
    • structure
    • semantic information associated with data (mapping, transformation, creation)

Components for Web Services
  • XML: Extensible Markup Language
  • WSDL : fundamental abstraction of Web services as interface to underlying software
  • SOAP/REST : communication protocol over internet and networks
  • UDDI : Providing registry and repository services for storing and retrieving Web services interfaces

WSDL : Web Services Description Language
  • A mechanism to describe Web Services
    • data types
    • data structures
    • define interfaces
    • associate services with underlying implementations in each interface
      • how to map the types and structures into the messages to be exchanged
      • how to tie the messages to underlying implementations
  • A definition of service to map to communication protocols and transports such as SOAP messages.
    • both parties interact by sharing a common WSDL file.
    • sender uses the WSDL file to generate the messages.
    • receiver uses the WSDL file to parse the message and map it to underlying program.
  • The goal is that the parts can be developed separately and integrated as a comprehensive WSDL file.

UDDI : Universal Description, Discovery, and Integration

SOAP : Simple object Access Protocol

  • Understanding SOAP from IBM
  • Defines a common format for XML messages over HTTP and other protocols.
  • SOAP is designed so that it can be extended to additional features and functions.
  • SOAP is a one-way asynchronous messaging technology.
  • SOAP can be used in various messaging styles, from RPC (remote procedure calls) to document oriented publishing and subscription.
  • Minimum criterion for a Web service must support SOAP.

Example of Simple SOAP Envelope
<?xml version='1.0' ?>
<env:envelope xmlns:env="http://www.w3.org/2003/05/SOAP-envelope"> 
  <env:header>
  </env:header>
  <env:body>
  </env:body>
</env:Envelope>
Example of SOAP Header with Routing Information
<?xml version='1.0' ?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/SOAP-envelope"> 
  <env:header>
    <wsa:ReplyTo xmlns:wsa=
        "http://schemas.xmlSOAP.org/ws/2004/08/addressing">
      <wsa:Address>
         http://schemas.xmlSOAP.org/ws/2004/08/addressing/role/anonymous
      </wsa:Address>
    </wsa:ReplyTo>
  </env:header>
  <env:body>
  </env:body>
</env:Envelope>

REST, RESTlet, RESTful : REpresentation State Transfer



Wednesday, December 7, 2016

Software Terms.

Framework and Software Testing
  • A framework is a semi-complete application that provides a reusable and common structure to share among developers who can incorporate it into their own application and extend it to their specific needs. 
  • A framework has a more coherent structure than a toolkits with a set of utility classes.
  • For example, JUnit (www.junit.org) is a framework created by Erich Gamma and Kent Beck in 1997, following an earlier work called SUnit.
  • Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides wrote the classic "Design Patterns : Elements of Reusable Object-Oriented Software" book in 1995 and the four authors are often referred to as the Gang of Four (GoF).
  • Kent Beck's software discipline: Extreme Programming

Types of Testing
  • Programmer Test or customer test
  • Unit test: confirms the method (or a unit of work) accepts the expected range of input and returns the expected output value for each input.
    • API contract provides a view of expected behavior by method signature.
    • Notion of API contract
    • An exception should be thrown if the method cannot fulfill the contract.
  • Integration tests
  • Acceptance tests
  • Functional tests / Behavioral tests
    • web page links
    • database connection
    • forms
    • cookies
  • Usability tests
    • efficiency
    • navigation
    • UI
    • content checking
    • visual style
  • Compatibility tests
    • browser compatibility
    • OS
    • mobile browser
    • printing options
  • Performance tests
    • traffic
    • loads
    • stress testing
  • Security tests
    • authentication and authorization
    • session management
    • cryptography and SSL
    • data validation
    • denial of service
    • risky activities



Tuesday, December 6, 2016

Java Interface and Exception.

Understanding Interfaces and Abstract Methods
  • To define what a class must do but not how to do it until later in specific application.
    • An abstract class define its signature and return types, namely, its interface for multiple processes or methods without implementations.
  • How? Specify methods with no body ({}).
  • Actions are defined in a class that implements the interface.
  • One interface, multiple methods is the essence of polymorphism.
  • Prior to JDK 8, interfaces could not define any implementation whatsoever. JDK 8 changes the rule so that default implementation to an interface method is allowed.
  • The original intent behind interface/abstract class remains. and default implementation in essence is a special use feature.
  • JDK 8 also added the ability to define static methods in interfaces.
    • Same as static methods in a class, static methods in interfaces can be called independently of any object created from it.
    • Yes, no implementation or instance of the interface is required to call a static method.
    • To call, specify the interface name, a period and the method name.
    • Static interface methods are not inherited by implementing class or a sub-interface extended from the parent interface.

Using Interface References
  • You can create an interface reference variable and use it to refer to any object that implements its interface. 
  • When you call a method on an object through an interface reference, you are calling the version of the method implemented by the object that is executed at runtime. 
  • This is similar as using a superclass reference to access a child class's methods on its objects. 

Using Interface to Share Constants
  • Though controversial, one usage of interface is to share constants among multiple classes.
  • Variables in interfaces are implicitly public, static and final and these are the characteristics of constants.
  • Examples of applications includes array size, various limits, special values and the like.

Extending Interface
  • An interface can inherit another interface by extending. 
  • When a class implements the derived interface, it must implement all methods in the inheritance chain.
interface X {
   void method1 ();
   void method2 ();
}

interface Y extends X {
   void method3 ();
}

class Z implements Y {
   public void method1 () {
      // do something...
   }
   public void method2 () {
      // do something...
   }
   public void method3 () {
      // do something...
   }
}

class Z2 implements Y {
   // implements all three methods
}

// Using Interface References
class Demo {
   public static void main (String args[]) {
   Z  obz  = new Z();
   Z2 obz2 = new Z2();
   X  obx  = new X();
   obx = obz;
   System.out.println ("Class z attribute is " + obx.getAttribute());
   obx = obz2;
   System.out.println ("Class z2 attribute is " + obx.getAttribute());
}


Exceptions
  • All exceptions are represented by classes.
  • All exceptions are derived from "Throwable" class.
  • When an exception occurs, an object of some exception class is generated.
  • Two direct subclasses of Throwable: Exception and Error.
    • Class Error exceptions are those occur in JVM, not in the program.
    • Class Error exceptions are usually beyond programmer's control.
    • Class Exception exceptions are those from program activity, such as divide-by-zero, array out-of-boundary and file-not-found errors. These are called standard exceptions.
    • Class Exception exceptions should be handled in the program.
      • RuntimeException is an important subclass of Exception class and is used to represent various common types of runt-time errors.
  • Another type of exceptions are those thrown manually by using throw statement.

Exceptions Handling
  • try
    • If an exception occurs within the try block, it is thrown.
  • catch
    • If an exception is thrown by try block, it will be handled here in a predictable way.
  • throw
    • Use throw to manually throw an exception.
  • throws
    • Use throws clause in the declaration of a method to specify an exception could be thrown out of a method.
  • finally
    • Use finally block to specify any activity that must be executed upon exiting from a try block.


Monday, December 5, 2016

JAVA Tips and Gotchas.


  • Overloading - if the number of parameters are different, the return type can be different. But the return type cannot be used to differentiate the methods.
  • Static blocks is executed when the class is first loaded before the class can be used anywhere else, and thus can be used to initialize members before the class is constructed.
  • Recursive versions of many routines may execute a bit more slowly than their iterative equivalents because of the additional overhead of the additional method calls.
  • Inner class - a class inside a class but outside of any method.
  • Nested class - a class inside a method.
  • Autoboxing - occurs when a primitive type must be converted into an object. Vice versa, auto-unboxing happens whenever an object must be converted into a primitive type. (Say, between int and Integer)
  • Use 'import static' - called static import - to refer to static members of a class directly by their names, without  having to qualify them with the class name.
  • @Annotation (Metadata) - used by frameworks in development and deployment.
    • @Retention
    • @Target
    • @Inherited
    • @Override
    • @Deprecated
    • @SafeVarargs
    • @SuppressWarnings
    • @FunctionalInterface
  • In Java 8, you can specify a variable-length argument (varargs) by three periods (...)
Example
// If mixing normal and varargs parameters, the variable-length
// parameter must be the only and the last one.
static void myVarMethod (int a, double b, String c, int ... v) {
   for ( int i=0; i < v.length; i++ ) {
      system.out.println ("index-" + i + " = " + v[i]);
   }
}

public void main (String args[]) {
   myVarMethod (5, 1, 3);
   myVarMethod (2);
   myVarMethod ();
}


import static java.lang.Math.sqrt;
import static java.lang.Math.pow;
// Not a good practice as out.println is now ambiguous
import static java.lang.System.out;

// Now you can call these methods directly
double x = sqrt (pow(a, 4) - b*c);
double x = (-b + sqrt (pow(b, 2) - 4*a*c)) / (2*a);
out.println ("The solution is ", + x);


Java Generics
class ClassGeneric  {
   T obj;

   ClassGeneric (T o) {
      this.obj = o;
   }

   T getObj() {
      return obj;
   }

   void printType () {
      System.out.println ("Type of this object is " + 
         obj.getclass().getName() );
   }
}

// To use ClassGeneric
class Demo {
   public static void main (String args[]) {
      ClassGeneric  instanceOfT;
      instanceOfT = new ClassGeneric  (23);
      instanceOfT.printType();

      ClassGeneric  instanceOfStr = new ClassGeneric ("My String");
      instanceOfT.printType();
   }
}



Friday, December 2, 2016

JDBC demystified.


JDBC (Java DabaBase Connectivity) is an API interface for relational databases connections, such as Oracle RDBMS, SQL Server, MySQL, and Microsoft SQL DB.

In Java 7 includes JDBC 4.1 reduces the amounts of code required to work with databases. It is most commonly used as in web-based applications hosted in J2EE servers, including JBOSS, Tomcat, WebSphere.

Android has its own API SQLite to work with local database. Calls can be made from Android application to access larger databases through web services hosted by middleware servers.

The Spring application framework includes something called JDBC Template. It simplifies the amount of code using JDBC to talk to the database. Hibernate is the most popular data mapping APIs using an object-relational mapping mechanism. It represents the database structure with Java classes and objects. In the background it's still using JDBC to communicate with the database.

Applications that use the JDBC API require drivers. A JDBC driver is a software library that encapsulates the logic required to communicate between the application and the database management system. JDBC driver rules are defined in Java Standard Edition.

A driver library package will contain specific implementations of these Java interfaces.
  • Connection - which lets you connect to the database, 
  • ResultSet - which encapsulates data returned from the database, 
  • Statement - requests to the database
  • PreparedStatement - represent requests to the database
  • CallableStatement - represent requests to the database

Typically, a driver package can be downloaded from the database vendors themselves, a MySQL driver from MySQL an Oracle driver for Oracle, et cetera. Most of JDBC drivers will support these five interfaces.

There are four distinct types of drivers, distinguished by their architecture.

Type 1 JDBC Driver
  • JDBC-ODBC bridge driver + ODBC driver
    • it is the oldest type. 
    • Installed on the client system.
    • Started in the mid to late '90s when JDBC got started, ODBC or the Open Database Connectivity protocol was the dominant model for communicating with the database. 
    • At runtime, requests go from the application through the JDBC API to the Bridge driver from there to the ODBC driver and then to the database. 
  • Not fast, but it is dependable, 
  • Can work with any database for which an ODBC driver existed (pretty much every RDBMS) 
  • Cons: 
    • the ODBC Bridge driver is not 100% Java and therefore not portable between operating systems. 
    • working with two drivers and both have to be on the same computer as the application, so you have increased maintenance.
    • the ODBC driver has to match the database version, and so if database on the server, is updated, all the client applications have to be updated as well. 

Type 2 JDBC Driver
  • Native protocol API driver + Java driver
    • Both are installed on the client system just like the Bridge driver and ODBC driver.
  • Fast - because primarily working with native APIs, you get the best performance.

  • Not 100% Java so it's not portable between operating systems.
  • The native API driver has to be installed on the application client and maintained, and once again, if the database is updated, the client software has to be updated as well.

Type 3 JDBC Driver
  • Net protocol + Java driver
    • installed in multiple locations
    • 100% Java driver that's installed in the client along with the application
    • a middleware server which hosts its own application
  • requests go at runtime from the application to the Type 3 driver that's installed on the client, to the network to the middleware server and then to the database.
  • The middleware driver can be native, and so the communication between the middleware and the database can be very fast.
    • but at the cost of the maintenance challenges with more than one driver to maintain. 

Type 4 JDBC Driver
  • All 100% Java thin driver + 100% Java driver
    • the most common.
    • Only one driver package with Java application itself.
    • Can be on a client computer, in a web environment on J2EE server.
  • Requests go from the application to the driver that's on the client and then through JDBC through the thin driver to the database server if it's out on the web, or to the database file if it's on the local hard disk. 
  • With the Java thin driver, you're communicating directly from the application to the database. No additional layers to install or maintain so maintenance is greatly simplified. 
  • Cons: a different driver package is needed for each database to work with.

Working with Multiple Database Types in Single Application
  • Most applications will only use a single database type, but if you're working with more than one database management system, you'll need to provide multiple drivers. 
  • For example, you may have one MySQL database server hosted in the Cloud that is accessible over the web and an Apache Derby SQL Database that is initialized with local files and runs in the same Java process of the application.
  • Use Type 4 pure Java drivers to make the code as portable as possible. That's the idea of encapsulated applications.

Simple Type 4 Java driver example
private Connection getConnection (String dbName) {
    Connection connection = null;
    try {
        String dbDirectory = "./Resources";
        System.setProperty("derby.system.home", dbDirectory);
        String dbUrl = "jdbc:derby:" + dbName + ";create=true";

        connection = DriverManager.getConnection (dbUrl);
        return connection;
    }
    catch (SQLException e) {
        for (Throwable t : e) t.printStackTrace();
        System.err.println(e);
        return null;
    }
}

private void getResultSet (Connection cn) {
    String sql  = "SELECT * FROM Runners ";
        try ( PreparedStatement ps = cn.prepareStatement(sql);
              ResultSet rs = ps.executeQuery();
        ) {
              readRS(rs);
              disconnect();
        }
        catch (SQLException e) {
              System.err.println(e);
        }
}

private void readRS (ResultSet rs) {
    try {
        while (rs.next()) {
            ThreadRunner t = new ThreadRunner 
                (rs.getString(1), rs.getInt(2), rs.getInt(3));
            t.setName(rs.getString(1));
            runners.add( t );
         }
     }
     catch (SQLException e) {
         System.err.println(e);
     }
}

private boolean disconnect () {
    try {
        String shutdownURL = "jdbc:derby:;shutdown=true";
        DriverManager.getConnection(shutdownURL);
    }
    catch (SQLException e) {
        if (e.getMessage().equals(
             "Derby system shutdown."))
        return true;
    }
    return false;
}


Wednesday, November 30, 2016

Java Thread of an Applet.

Threading an Applet
public class RenewApplet extends java.applet.Applet
    implements Runnable
{
    Thread thread;
    boolean running;
    int renewInterval = 500;

    public void run() {
        while ( running ) {
            redoAction ();
            try {
                Thread.sleep( renewInterval );
            }
            catch ( InterruptedException e) {
                System.out.println( "Interrupted..." );
                return;
            }
        }
    }

    public void start() {
        if ( !running ) {
            running = true;
            thread = new Thread (this);
            thread.start();
        }
    }

    public void stop() {
        thread.interrupt();
        running = false;
    }
}



Monday, November 28, 2016

C++ Compile, Link Process and Characters.

C++ compilation is a two-step process. First, the source code is compiled into an object file that contains the machine code equivalent of the source file. Secondly, the linker combines the object files for a program into a file containing the complete executable program. The linker will also integrate any functions from the Standard Library used in the second step.

Imagining the intermediate object files from each .cpp source file are similar to the Java .class files, which you then run with JVM. However, the Java compiler interprets the source code into bytecode that is OS and platform independent and without saying, is not machine code.

Similar to Java, you can compile each source file independently in separate compiler runs. This is convenient since in the coding process, there will be typographical and other errors to be coded iteratively. Even if it compiles, it may have logical errors to be revised.

Regarding Characters

Talking about computer characters, ASCII was defined in 1960s as 7-bit code so that there are 128 code values. ASCII values 0 to 31 represent non-printing control characters such as carriage return (0x0F) and line feed (0X0C). Code value 65 yo 90 are the uppercase letters A to Z and 141 to 172 correspond to the lowercase a to z. The codes for uppercase and lowercase letters are only different in the sixth bit.

Enter Universal Character Set (UCS) around 1990s to overcome the limitations of ASCII codes and extend it to include codes for foreign languages. UCS is defined to code up to 32 bits.

However, it is very inefficient to use four bites when one byte can do the job.

UCS defines a mapping between characters and integer code values, called "code points". The code point is not the same as an encoding. It is an integer that can be represented in different ways of bytes or words in an computer system.

Unicode is a standard that defines the characters with the code points derived from UCS. Remember, with the same identical code point, you can have different encodings. Unicode standards provide such flexibility by dividing the codes into 17 code planes, each of which contains 65,536 code values.

Code plane 0 contains codes from 0x0 to 0xffff and code plane 1 with 0x10000 to 0x1ffff. Naturally code plane 0 contains most national languages.

As mentioned, Unicode provides more than one encoding method. The most commonly used are UTF-8 and UTF-16.

UTF-8 represents a character as a variable length of 1 to 4 bytes with ASCII character set appears in UTF-8 as single byte codes.

UTF-16 represents a character as one or two 16-bit values. UTF-16 includes UTF-8.

Java use UTF-16 unicode to represent internal text.

In C++, the default size of 'char' is 8-bit ASCII code and you can declare it as 'signed char' to have value -128 to 127. You also have wchar_t, char16_t and char32_t to store unicode characters.


Thursday, November 24, 2016

Maven 101.

mvn clean install
mvn clean test
Useful Links:
Phases:
  • validate 
  • compile
  • test 
  • clean 
  • package 
  • integration-test 
  • verify 
  • install 
  • deploy 
  • site

Wednesday, November 16, 2016

C++ Reference.

Create Tests
#include 
#include 
using namespace std;

void fa();
void fb();
void fc();
void func  ( const int & i );
void func  ( const string & fs );
void func2 ( const string * fs );
void func3 ( const string * fs );
const char * prompt();
int jump   ( const char * );
void (*funcs[])() = { fa, fb, fc, nullptr };


int main( int argc, char ** argv )
{
    int x = 24;
    string s = "Hello";
    puts ("this is main()");
    func(x);

    x = 73;
    printf ("x is %d\n", x);

    func(&s);
    printf ("string is %s\n", s.c_str());
    func2(&s);
    printf ("string2 is %s\n", s.c_str());
    printf ("returned string is %s\n", func3().c_str());

    // function pointer *fp
    void (*fp)() = func4;
    void (*fp)(&s) = &func4; // same as above
    fp(); // or (*fp)();

     while ( jump (prompt()) );
     puts ("\nDone\n");

    fflush(stdout);
    return 0;
}

void func( const int & i )
{
    // would result in error if you try to change i in function
    printf ("value is %d\n", i);
}

void func( const string & fs )
{
    printf ("String is %s\n", fs.c_str());
}

void func2 (const string * fs )
{
    printf ("String2 is %s\n", fs->c_str());
}

// declare to be const so you can't change the string
const string & func3 (const string * fs )
{
    // declare to be static storage so the stack for function won't 
    //    overflow and create security problem
    // auto is deprecated, because it's default and stored in stack
    // stack is created fresh for each function
    //
    // also if you have to return a reference, declare it to be static
    //     so it can be stored in static storage space
    //     auto storage on stack is small. Use reference if you have
    //     to return big object and return the reference in static storage
    static string s = "This is static";
    return s;
}

void func4()
{
    printf ("String2 is %s\n", fs->c_str());
    puts ("a string");
}

void func4(const string * fs)
{
    printf ("String2 is %s\n", fs->c_str());
    puts ("a string");
}

const char * prompt() {

    puts ("Choose an option:");
    puts ("1. do fa()");
    puts ("2. do fb()");
    puts ("Q. quit");
    puts ("Choose an option:");
    printf(">> ");

    fflush(stdout);                // flush after prompt
    const int buffsz = 16;         // constant for buffer size
    static char response [buffsz]; // static storage for response buffer
    fgets(response, buffsz, stdin);// get response from console
    return response;
}

int jump ( const char * rs ) {
    char code = rs[0];
    if (code == 'q' || code == 'Q') return 0;
    // count the length of the funcs array
    int func_length = 0;
    while ( funcs[func_length] != Null ) func_length++;

    int i = (int) code - '0'; // convert ASCII numeral to int
    i--; // list is zero-based
    if ( i < 0 || i >= func_length ) {
        puts ("invalid choice");
        return 1;
    } else {
        funcs[i]();
        return 1;
    }

}




Python 102.

Stddraw

import math
import stddraw

x0 = 0.0
y0 = 0.0
x1 = 1.0
y1 = 0.0
t = math.sqrt (3.0) / 2.0
stddraw.line (x0, y0, x1, y1)
stddraw.point(0.5, t/3.0)
stddraw.setXscale(x0, x1)
stddraw.setYscale(y0, y1)
stddraw.show()

# stddraw.setCanvasSize(w, h)
# stddraw.setXxcale (x0, x1)
# stddraw.setYsclae (y0, y1)
# stddraw.setPenRadius(r)

stddraw.setXscale (0,n)
stddraw.setYscale (0,n)
for i in range (n+1)
    stddraw.line (0, n-i, i, 0)
stddraw.show()

xd = [x-r, x, x+r, x]
yd = [y, y+r, y, y-r]
stddraw.polygon(xd, yd)

# stddraw.circle(x, y, r)
# stddraw.square(x, y, r)
# stddraw.rectangle (x, y, w, h)
# stddraw.polygon(x, y)
# stddraw.text (x,y,s)
# stddraw.setPenColor(color)
# stddraw.setFontFamily(font)
# stddraw.setFontSize(size)
# stddraw.clear(color)



SQL Tips

Guidelines
  • Document as you go.
  • Leave bread crumbs on the trail.
  • Keep it simple.
  • Use prefixes or suffixes to make it obvious.
  • Use consistent coding style.
  • Add comments when it's not obvious.
  • Anticipate disasters proactively.
  • Testing
    • DELETE
    • INSERT
    • SELECT
    • UPDATE
    • DELETE
Terms
  • DDL - Data Definition Language
  • DML - Data Manipulation Language
  • PL/SQL - Procedural Language for SQL
  • RDBMS - Relational DataBase Management System

Example
CREATE TABLE author (
id          number,
name        varchar2(100),
birth_date  date,
gender      varchar2(30)
);

Using IJ
% ./bin/ij
ij version 10.8
ij> connect 'jdbc:derby:myDB;create=true'; 

CREATE TABLE Products
     (
         ProductCode VARCHAR(10),
         Description VARCHAR(40),
         Price DOUBLE
);
0 rows inserted/updated/deleted
ij>

INSERT INTO Products
     VALUES ('candy', 'chocolate''s flavor', 5.25);
1 row inserted/updated/deleted
ij> disconnect;
ij> exit;

Running Script
% ./bin/ij
ij version 10.8
ij> connect 'jdbc:derby:myDB';
ij> run 'buildMyDB.sql';
ij> disconnect;
exit;

# to run script from command line
% java org.apache.derby.tools.ij myDBCreate.sql

# to start the Derby server
% java org.apache.derby.drda.NetworksServerControl start

# to stop the Derby server
% java org.apache.derby.drda.NetworksServerControl shutdown

Links



Tuesday, November 15, 2016

SQL 102.

Concepts

  • Primary Key vs Foreign Key
  • Scale
  • Schema
  • Records/Rows
  • Fields/Columns
  • Using Alias to shorten SQL syntax
SELECT RTrim(name) + ' ( ' + RTrim(country) + ')' AS 
title
FROM Students
ORDER BY name;

SELECT name, contact
FROM customers AS c, orders AS o, orderitems AS oi
WHERE c.cust_id = o.cust_id
  AND oi.order_num = o.order_num
  AND prod_id = 'THISID';


Using JOIN
// to retrieve all order from the customer who ordered
// '123' 
SELECT id, name
FROM orderlist
WHERE id = (SELECT id
            FROM orderlist
            WHERE id = '123');

// Using JOIN for the same query
SELECT p1.id, p1.name
FROM orderlist AS p1, orderlist AS p2
WHERE p1.id = p2.id
  AND p2.id = '123';

// Standard Join/Inner Join vs Outer Join
// Natural Joins eliminate repeated columns from the inner join
SELECT c.*, o.order_num, o.order_date, oi.prod_id, 
       oi.quantity, OI.item_price
FROM customers AS c, orders AS o, orderitems as oi
WHERE c.cust_id = o.cust_id
  AND oi.order_num = o.order_num
  AND prod_id = 'FB';

// Use outer Join to include rows that have no related rows
// INNER JOIN example
SELECT customers.cust_id, orders.order_num
FROM customers INNER JOIN orders
  ON customers.cust_id = orders.cust_id

// OUTER JOIN
//    must use RIGHT or LEFT keyword to specify 
//    which table to include all rows
SELECT customers.cust_id, orders.order_num
FROM customers LEFT OUTER JOIN orders
  ON customers.cust_id = orders.cust_id;

SELECT customers.cust_id, orders.order_num
FROM customers LEFT OUTER JOIN orders
  ON orders.cust_id = customers.cust_id;

// Simplified OUTER JOIN
SELECT customers.cust_id, orders.order_num
FROM customers, orders
WHERE customers.cust_id *= orders.cust_id;

// Using JOIN with Aggregate Functions
SELECT customers.cust_name, 
       customers.cust_id,
       Count(orders.order_num) AS num_order
FROM customers LEFT INNER JOIN orders
  ON customers.cust_id = orders.cust_id
GROUP BY customers.cust_name, 
         customers.cust_id;

SELECT customers.cust_name, 
       customers.cust_id,
       Count(orders.order_num) AS num_order
FROM customers LEFT OUTER JOIN orders
  ON customers.cust_id = orders.cust_id
GROUP BY customers.cust_name, 
         customers.cust_id;


SubQuery and Combined Queries Using UNION
SELECT vend_id, prod_id, prod_price
FROM products
WHERE prod_price >= 5 OR vend_id IN (1001,1002);

SELECT vend_id, prod_id, prod_price
FROM products
WHERE prod_price >= 5 
// without UNION ALL, SQL eliminate duplicate rows
UNION     
SELECT vend_id, prod_id, prod_price
FROM products
WHERE vend_id IN (1001,1002);
// ORDER BY vend_id, prod_price;

Full-Text Searching
EXEC sp_fulltext_database 'enable';
CREATE FULLTEXT CATALOG catalog_my;
CREATE FULLTEXT INDEX ON productnotes (note_text)
KEY INDEX key_productnotes
ON catalog_my;
// KEY INDEX is used to provide the name of the table's primary key.

ALTER FULLTEXT CATALOG catalog_my REBUILD;
SELECT * FROM sys.fulltext_catalogs;

// FulltextCatalogProperty() function
//    accepts a catalog name and the property to be checked
//    IndexSize
//    PopulateStatus

// FREETEX - simple search, matching by meaning or exact text match
// CONTAINS - search for phrases, synonyms
SELECT note_id, note_text
FROM notes
WHERE note_text LIKE '%bird food%';

SELECT note_id, note_text
FROM notes
WHERE FREETEXT(note_text, 'bird food'); // look for anything that
                                        // could mean bird food

// WHERE CONTAINS (note_text, '"iron*"'); // match anything with iron
// WHERE CONTAINS (note_text, 'bird food');
//    CONTAINS is functionally identical to LIKE note_text = '%match%'
//    CONTAINS search typically is quicker, especially as table size
//        increases.

// More CONTAIN examples
WHERE CONTAINS (note_text, 'safe AND sound');
WHERE CONTAINS (note_text, 'bird AND NOT food');
WHERE CONTAINS (note_text, 'grass NEAR cheese');
// look for any words that share the same stem as 'vary', such as 'varies'
WHERE CONTAINS (note_text, 'FORMSOF (INFLECTIONAL, vary)');

// Ranking
// The following query use FREETEXTTABLE function to return a table that
//     contain words meaning bird and food and gives the table an alias 
//     of 'f'
SELECT f.rank, note_id, note_text
FROM notes,
    FREETEXTTABLE (notes, note_text, 'bird food') f
WHERE notes.note_id = f.[key]
ORDER BY rank DESC;



Sunday, November 13, 2016

JAVA IO and NIO.

java.io.file
  • path interface
    • get(String, String)
    • getFileName()
    • getName(int)
    • getNameCount()
    • getParent(), getRoot()
    • toAbsolutePath()
    • toFile()
  • paths class
    • exists(path)
    • notExists(path)
    • isReadable(path)
    • isWritable(path)
    • isDirectory(path)
    • isRegularFile(path)
    • size(path)
    • newDirectoryStream(path)
    • createFile(path)
    • createDirectory(path)
    • createDirectories(path)
  • files class
  • Exceptions
    • IOException
      • EOFException
      • FileNotFoundException
    • FileAlreadyExistsException
    • DirectoryNotEmptyException
import java.io.*;
import java.nio.file.*;

Path myp = Paths.get("./mydir");

String dir = "./src/db/files";
String filename = "db.txt";
Path dirPath = Paths.get(dir);
Path fPath = Paths.get(dir, filename);
File fName = fPath.toFile();

if (Files.notExists(fPath)) {
    Files.createDirectories(fPath);
}

// fPath.getFileName() -> return String
// fPath.toAbsolutePath() -> return String
// Files.isWritable(fPath) -> return boolean
// Files.exists(dirPath) -> return boolean
// Files.isDirectory (dirPath) -> return boolean

DirectoryStream dirs = Files.newDirectoryStream(dirPath);
for (Path p: dirs) {
    if (Files.isRegularFile (p) {
        System.out.println (" " + 
            p.getFileName());
    }
}

// Write data to file
// layered approach to get an object using constructor
try (PrintWriter out = new PrintWriter (
                       new BufferedWriter (
                       new FileWriter (productsFile))))
{
    out.println ("printout line");
}
catch (IOException e)
{
    System.out.println(e);
}

//Read data from the file
try (BufferedReader in = new BufferedReader(
                         new FileReader(myFile)))
{
    String line = in.readLine();
    while (line != null)
    {
        System.out.println(line);
        line = in.readLine();
        String[] columns = line.split("\t");
        String name = columns[0];
        String value = columns[1];
        int type = Integer.parseInteger(columns[2]);
        System.out.println(type);
    }
}
catch (IOException e)
{
    System.out.println(e);
}
// flush the buffer and close the input stream
in.close();

// Code that handles I/O exceptions
Path productsPath = Paths.get("products.txt");
if (Files.exists(productsPath)){  //defensive prog.
    //prevent the FileNotFoundeException
    File productsFile = productsPath.toFile();
    try (BufferedReader in = new BufferedReader(
                             new FileReader(productsFile)))
    {
        String line = in.readLine();
        //prevent EOFException
        while(line != null){
            System.out.println(line);
            line = in.readLine();
        }
    }
    catch (IOException e){
        System.out.println(e);
    }
} else{
    System.out.println(
              productsPath.toAbsolutePath() + " doesn't exist");
}

// ProductDAO interface
public interface ProductDAO
          extends ProductReader, ProductWriter,
          ProductConstants {}

import java.util.ArrayList;
public interface ProductReader
{
    Product getProduct(String code);
    ArrayList getProducts();
}

//The ProductWriter interface
public interface ProductWriter
{
    boolean addProduct(Product p);
    boolean updateProduct(Product p);
    boolean deleteProduct(Product p);
}
//The ProductConstants interface
public interface ProductConstants
{
    int CODE_SIZE = 4;
    int DESCRIPTION_SIZE = 40;
}


java.nio.file (JDK 1.7+)

Wednesday, November 9, 2016

JAVA Threads.

Basics
  • Threading in JAVA is built-in.
    • Java supports threading natively and at a high level.
    • Java concurrency utilities address common patterns and practices in multithreaded applications and raise them to the level of tangible Java APIs.
    • Not all applications need explicit use of threads or concurrency but most will use some features that is impacted by multithreading.
  • Threads are integral to client side Java APIs
    • GUI, sound.
      • Ex. using separate thread within JVM for drawing.
    • APIs with lots of I/O activities which are slow in nature.
  • Threads are not common and are discouraged on the server side in the context of application servers and web applications.
    • Server environment should control the allocation of CPU time/resources.
  • java.util.concurrent
  • You don't want to put the run() method directly in the object often time.
    • Make an adapter class that serves as the Runnable Object with the run() method and use that to call any method it wants to after the thread is started.
Concept
  • All execution in Java is associated with a Thread object, beginning with "main" thread.
  • New thread is create by java.lang.Thread class.
  • Thread Methods:
    • start
    • run
    • wait
    • sleep
    • notify
    • notifyAll
    • stop is deprecated and don't use it anymore.
  • Since Java has no pointer system to the method to tell it to run, we can't specify one directly. Instead, we use java.lang.Runnable interface to create or mark an object that contains a "runnable" method, which is run().
  • Thread begin its life by executing the run() method in a Runnable object (the target object) that was passed to the thread's constructor.
  • run() must be public, return void, takes no arguments and throws no checked exceptions.
  • Any class that contains an run() method can declare that it implements the Runnable interface.
    • An instance of this class is a runnable object that can serve as the target of a new thread.
Thread States
  • New
  • Runnable
  • Blocked
  • Waiting
  • Terminated

Example
class MyClass implements Runnable {
   boolean choice = ture;

   public void run() {
      while (choice) {
         // do what myClass has to...
      }
   }
}

MyClass item = new MyClass ("message");
thread myThread = new Thread (item);
myThread.start(); // This will cause run() in MyClass to execute

// To make an object to create and handle its own threads so to fit
// OOP concept, the following shows to have the actions in its
// constructor

class MyClass implements Runnable {
   boolean choice = ture;

   Thread myThread;
   public void MyClass (String name) {
      myThread = new Thread(this);
      myThread.start();
   }

   public void run() {
      while (choice) {
         // do what myClass has to...
      }
   }
}


Natual Born Thread Example
class Runner extends Thread {
    boolean running = true;

    public void run() {
        while (! isInterrupted()) {
            // by default, the Thread executes its own run() method when
            // we call the start() method
        }
    }
}

// to call Runner
Runner horse = new Runner ("horse");
horse.start();

// alternatively,
class Runner extends Thread {
    Runner (String name) {
        start();
    }
}

// Use adapter
class Runner {
    public void startRunner() {
        Thread myThread = new Thread (new Runnable () {
            public void run() { doAction(); }
        } );
        myThread.start();
    }

    private void doAction () {
        // do something...
    }
}

// Another way to write the code
new Thread () {
    public void run() { doAction(); }
}.start();


Thread Methods
  • Thread.sleep() -> require try/catch (InterruptedException e)
  • myThread.wait()
  • myThread.join()
  • myThread.interrupt()
  • stop(), suspend() and resume()

More about interrupt() method
Any thread that is not running (hard loop) must be in one of three states - sleep(), wait() or lengthy I/O operation - where it can be flagged to stop by interrupt() method. When a thread is interrupted, its interrupt status flag is set and this can happen at any time. Use isInterrupted() method to test this status like in the example above. You can also use isInterrupted(boolean toClear) as a flag and a signal to clear the interrupt status.

That said, this is historically a weak spot and it may not work correctly in all cases in early JVM, and more often with interrupting I/O calls blocked in a read() or write() method, moving bytes from a file or network. To address this in Java 1.4, a new I/O framework (java.nio) was introduced with one of its goals to address these problems. When the thread associated with an NIO operation is interrupted, the thread wakes up and the I/O stream (called a "channel") is automatically closed. (Check about the NIO package for more information.)


JAVA GUI 101.


  • import javax.swing.JFrame;
  • import javax.swing.ImageIcon;
  • import javax.swing.JLabel;
import javax.swing.JFrame;
import javax.swing.ImageIcon;
import javax.swing.JLabel;

class showPicture {
   public static void main (String args[]) {
      JFrame frame = new JFrame();
      ImageIcon icon = new ImageIcon ("some.jpg");
      JLabel label = new JLabel (icon);
      frame.add(label);
      frame.setDefaultCloseOperation 
         (JFrame.EXIT_ON_CLOSE);
      frame.pack();
      frame.setVisible(true);
   }
}
import java.awt.Font;
import java.awt.GridLayout;

import javax.swing.JFrame;
import javax.swing.JLabel;

public class myGui {
   public static void myGui {
      JFrame frame = new JFrame();
      JLabel label = new JLabel (icon);

      JLabel labels[] = {
         new JLabel ("Name"), new JLabel("Phone"),
         new JLabel ("Alice"), new JLabel("555-1234"),
         new JLabel ("Bob"), new JLabel("222-9876") 
      };

      frame.add(label[0]);
      frame.add(label[1]);

      JLabel boldLabel = new JLabel("Name");
      Font boldFont = boldLabel.getFont();
      Font plainFont = new Font(boldFont.getName(),
         Font.PLAIN, boldFont.getSize() );

      for (int i=2; i<8; i++) {
         labels[i].setFont(plainFont);
         frame.add(labels[i]);
      }
      frame.pack();
      frame.setvisible(true);
   }
}

package application;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class myJFXApp extends Application {
   @Override
   public void start (Stage primaryStage) {
      try {
         // BorderPane root = new Borderpane();
         Parent root = FXMLLoader.load (getClass().
                        getResource ("Root.fxml"));
         Scene scene = new Scene (root, 400, 400);
         scene.getStylesheets().
            add(getClass().getResource("application.css").
                             toExternalForm());
         primaryStage.setScene(scene);
         primaryStage.show();
      }
      catch (Exception e) {
         e.printStackTrace();
      }
   }

   public static void main (String[] args) {
      launch (args);
   }
}

import javafx.fxml.FXML;
import javafx.event.ActionEvent;
import javafx.scene.control.Textfield;

public class myJFXApp2...
{
   @FXML
   private TextField textfield;

   @FXML
   protected void onClick (ActionEvent event) {
      textField.setText (textField.getText().
         toUpperCase());
   }
}

Tuesday, November 1, 2016

SQL 101.

COMMANDS
  • SELECT <column-1> [, column-2] ...
    • FROM <table-1>
         { INNER | LEFT OUTER | RIGHT OUTER} JOIN table-2
         ON table-1.column-1 {=|<|>|<=|>=|<>} table-2.column-2
    • WHERE selection-criteria
    • ORDER BY column-1 [ASC | DESC] [, column-2 [ASC | DESC]] ...
  • INSERT INTO <table-name> [(column-list)]
    • VALUES (value-list)
  • UPDATE <table-name>
    • SET  <expression-1> [, expression-2] ...
    • WHERE selection-criteria
  • DELETE FROM <table-name>

SELECT
SELECT ProductCode, Description, Price
FROM Products
WHERE Price > 50
ORDER BY ProductCode ASC

SELECT * FROM PRODUCTS

SELECT p.ProductCode, p.Price, li.Quantity,
            p.Price * li.Quantity AS Total
     FROM Products p
           INNER JOIN LineItems li
           ON p.ProductCode = li.ProductCode
     WHERE p.Price > 50
     ORDER BY p.ProductCode ASC;

SELECT p.ProductCode, p.Price, li.Quantity,
             p.Price * li.Quantity AS Total
     FROM Products p, LineItems li
     WHERE p.ProductCode = li.ProductCode AND p.Price > 50
     ORDER BY p.ProductCode ASC;

SELECT TOP(5) p.prod_name FROM products p, LineItem li
TABLESAMPLE (3 ROWS)
ORDER BY p.prod_price;

SELECT products.prod_name FROM products
ORDER By products.prod_price DESC, products.prod_name
TABLESAMPLE (50 PERCENT);

// Use [] to delimit the column name when there is space btwn
// and alias it using 'AS' to be 'LastName'
SELECT [Last Name] AS LastName


INSERT
INSERT INTO Products (ProductCode, Description, Price)
VALUES ('casp', 'ASP.NET Web Programming with C#', 54.50)

// without the column list
INSERT INTO Products
VALUES ('casp', 'ASP.NET Web Programming with C#', 54.50)


UPDATE
// Update a single row
UPDATE Products
SET Description =
       'Murach''s ASP.NET Web Programming with C#',
    Price = 49.50
WHERE ProductCode = 'casp'
// Update multiple rows
UPDATE Products
SET Price = 49.95
WHERE Price = 49.50

DELETE
DELETE FROM Products WHERE ProductCode = 'casp'
DELETE FROM Invoices WHERE AmountDue = 0
DELETE FROM Invoices

WHERE, IN, NOT
SELECT prod_name, prod_price
FROM products p, LineItem li
TABLESAMPLE (3 ROWS)
WHERE prod_price <> 10, prod_name = 'fuses'
ORDER BY price;

...
WHERE price BETWEEN 5 AND 10;
WHERE vend_id = 1002 AND price <= 10;
WHERE vend_id = 1002 OR vend_id = 2001 AND price <= 10;
WHERE prod_name LIKE 's%e'; // % is wildcard, 
WHERE prod_name LIKE 'jet%'; // matching any 'jet' in the beginning
WHERE prod_name LIKE '%anvil%'; // %...%, match anywhere

WHERE name LIKE '_ley'; // _ match one char
WHERE name LIKE '[EJ]%'; // match E or J as the start char
WHERE name LIKE '[^EJ]%'; // ^ NOT match, any name not begin with E or J
WHERE NOT name LIKE '[EJ]%'; // same as '[^EJ]%'

// WHERE OPERATOR:
// =, <>, !=, <, <=, !<, >, >=, !>, BETWEEN, IS NULL

Fields/Column Concatenation
SELECT name + ' (' + age + ')'
FROM students
ORDER BY name;

// T-SQL RTrim: trim all space from the right
//       LTrim: trim all space from the left
SELECT RTrim(name) + ' (' + LTrim(age) + ')' AS
student_title
FROM students
ORDER BY name;


Using MATH
SELECT id, quantity, price,
    quantity * price AS total_price
FROM orderlist
WHERE order_num > 2000;
// T-SQL math operators: + - * / %


Using Function
// Common Text Functions
// CharIndex()
// Left(), Right()
// Len()
// Lower(), Upper()
// LTrim(), RTrim()
// Replace()
// Soundex() : soundex value when they sound similar
// Str()
// SubString()

SELECT name, UPPER(name) AS name_upper
FROM orderlist
WHERE order_num > 2000;

// Common Data and Time functions
// DateAdd()
// DateDiff()
// DateName()
// DatePart()
// Day()
// GetData()
// Month()
// Year()

// Supported Date Parts:
// day (dd or d)
// dayofyear (dy or y)
// hour (hh)
// millisecond (ms)
// minute (mi or n)
// month (m or mm)
// quarter (q or qq)
// second (ss or s)
// week (wk or ww)
// weekday (DatePart() only), (dw)
// year (yy or yyyy)

SELECT name, 
    DatePart(weekday, orderdate) AS weekday
FROM orderlist;

// to return named weekdays instead of numbered day
SELECT name, 
    DateName(weekday, DatePart(weekday, orderdate) ) AS weekday
FROM orderlist;

// Day(),          Month(),         and Year() are shortcuts for 
// DatePart(day,), DatePart(month,) and DatePart(year,)

// when comparing dates, always use DateDiff()
SELECT name, id
FROM orderlist
WHERE DateDiff (month, order_date, '2005-09-01') = 0;

...
Where Year(order_date) = 2005 AND Month(order_date) = 9;

// Numeric Functions
// Abs()
// Cos()
// Exp()
// Pi()
// Rand()
// Round()
// Sin()
// Sqrt()
// Square()
// Tan()

// SQL Aggregate Functions
// Avg(), Count(), Max(), Min(), Sum()
SELECT Avg(price) AS avg_price // Null columns are ignored by Avg()
FROM products
WHERE id = 1003;

SELECT Count(*) AS num_customers // count all rows
FROM customers;
SELECT Count(customer_email) AS num_customers // count only those with emails
FROM customers;
SELECT Sum(price*quantity) AS total_price
FROM orderlist
WHERE order_num = 2000;

// Use ALL (default) or DISTINCT for unique items
SELECT Avg(DISTINCT price) AS avg_price_ofunique
FROM products
WHRE id = 1002;


Filtering Groups
// group by vend_id and calcute all products from that
// vendor
SELECT vend_id, Count(*) AS num_prods
FROM products
GROUP BY vend_id;

SELECT cust_id, Count(*) AS orders
FROM orderlist
WHERE price >= 10
GROUP BY cust_id
HAVING Count(*) >= 2;

// HAVING support all WHERE operators
// HAVING filters after data is grouped.
// WHERE filters before data is grouped 
//    (rows eliminated by WHERE are not included in the group)
//    (This can change the calculated values used in HAVING clause.

// ORDER BY
//    sorts generated output, can use any column, not required
// GROUP BY
//    groups rows but may not be in order,
//    only selected columns or expression columns may be used
//    every selected column expression must be used
//    required if using columns (or expressions) with Count/Avg/Sum/Min/Max

SELECT order_num, Sum(quantity*price) AS ordertotal
FROM orderlist
GROUP BY order_num
HAVING Sum(quantity*price) >= 50;
// ORDER BY ordertotal; // optional


SQL Servre 2005
% USE mydatabase;
% sp_databases;
% sp_tables;
% sp_tables NULL, dbo, mydatabase, "'TABLE'";
% sp_columns customers;
% sp_server_info;
% sp_space_used;
% sp_statistics;
% sp_helpuser;
% sp_helplogins;



Sunday, October 30, 2016

UVM Virtual Sequence Example.

// Base Virtual Sequence Class
class base_vseq extends uvm_sequence #(uvm_sequence_item);
   `uvm_object_utils(base_vseq)
 
   // Target Agent Sequencers
   uvm_sequencer #(ahb_txn) SQR_AHB;
   uvm_sequencer #(axi_txn) SQR_AXI;
 
   // Constructor
   function new (string name = "base_vseq");
      super.new(name);
   endfunction: new
 
endclass: vseq_base

// Virtual Sequence Class
class my_vseq extends base_vseq;
   `uvm_object_utils(my_vseq)
 
   // Constructor
   function new (string name = "my_vseq");
      super.new(name);
   endfunction: new
 
   // Sequence Body Task
   task body();
 
      ahb_seqeunce ahb_seq;
      axi_sequence axi_seq;
 
      ahb_seq = ahb_sequence::type_id::create("ahb_seq");
      axi_seq = axi_sequence::type_id::create("axi_seq");
 
      fork
         abh_seq.start(SQR_AHB);
         axi_seq.start(SQR_AXI);
     join
   endtask
 
endclass: my_vseq

// Base Test Class
class base_test extends uvm_test;
   `uvm_component_utils(base_test);
 
   // Environment Class Instantiation
   top_env Env;
 
   // Constructor
   function new (string name = "base_test", uvm_component parent = null);
      super.new(name, parent);
   endfunction: new
 
   // Build Phase
   function void build_phase (uvm_phase phase);
      Env = top_env::type_id::create("Env");
   endfunction: build_phase
 
   // Method to Connect Sequencer Handles in VSEQ
   function void init_vseq (base_vseq vseq);
      vseq.SQR_AHB = test.env.ahb_agent.SQR_AHB;
      vseq.SQR_AXI = test.env.axi_agent.SQR_AXI;
   endfunction: init_vseq
 
endclass: base_test

// Main Test
class test extends base_test;
   `uvm_component_utils(test)
 
   // Constructor
   function new (string name = "test", uvm_component parent = null);
      super.new(name, parent);
   endfunction: new
 
   // Run Phase
   task run_phase (uvm_phase phase);
      // Create the Virtual Sequence
      my_vseq vseq = my_vseq::type_id::create("vseq");
      phase.raise_objection(this);
      // Virtual Sequence Initialization
      init_vseq(vseq);
      // Start the Virtual Sequence
      vseq.start(null);
      phase.drop_objection(this);
   endtask: run_phase
 
endclass: test

UVM AHB Driver Example.

////////// Sequence Item //////////
class ahb_seq_item extends uvm_sequence_item;
   `uvm_object_utils(ahb_seq_item)
 
   // Master to Slave Data Flow
   rand logic [31:0] HADDR;
   rand logic [31:0] HWDATA;
   rand logic HWRITE;
   ahb_burst_e HBURST;
 
   // Slave to Master Data Flow
   logic [31:0] HRDATA;
   ahb_resp_e HRESP;
 
   // Constructor
   function new (string name);
      super.new(name);
   endfunction: new
 
   // Constraints
   constraint addr_for_32bit {HADDR[1:0] == 0;}
 
endclass: ahb_seq_item


////////// AHB Interface //////////
interface ahb_interface;
 
   // TO both Master & Slave
   logic HCLK;
   logic RESETn;
 
   // Master to Slave
   logic [31:0] HADDR;
   logic [31:0] HWDATA;
   logic HWRITE;
   ahb_burst_e HBURST;
 
   // Slave to Master
   logic [31:0] HRDATA;
   ahb_resp_e HRESP;
   logic HREADY;
 
endinterface: ahb_interface


////////// Pipelined UVM Driver //////////
class ahb_pipelined_driver extends uvm_driver #(ahb_seq_item);
   `uvm_component_utils(ahb_pipelined_driver)
 
   // Virtual Interface
   virtual ahb_interface ahb_if;
 
   // Constructor
   function new (string name, uvm_component parent);
      super.new(name, parent);
   endfunction: new
 
   // Semaphore Declaration
   semaphore pipeline_lock = new(1);
 
   // Run Phase Task
   task run_phase (uvm_phase phase);
 
      @(posedge ahb_if.HRESETn);
      @(posedge ahb_if.HCLK);
 
      fork
         do_pipelined_transfer;
         do_pipelined_transfer;
      join
 
   endtask: run_phase
 
   // do_pipelined_transfer task
   task automatic do_pipelined_transfer;
 
    ahb_seq_item req;
 
    forever begin
      pipeline_lock.get();
      seq_item_port.get(req);
      accept_tr(req, $time);
      void'(begin_tr(req, "pipelined_driver");
      ahb_if.HADDR <= req.HADDR;
      ahb_if.HWRITE <= req.HWRITE;
      ahb_if.HBURST <= req.HBURST;
      @(posedge ahb_if.HCLK);
      while(!ahb_if.HREADY == 1) begin
         @(posedge ahb_if.HCLK);
      end
      // Command phase ends here
      // Unlock semaphore
      pipeline_lock.put();
      // Data phase starts here
      if (req.HWRITE == 0) begin
         @(posedge ahb_if.HCLK);
         while(ahb_if.HREADY != 1) begin
            @(posedge ahb_if.HCLK);
         end
        req.HRDATA = ahb_if.HRDATA;
        req.HRESP = ahb_if.HRESP;
      end
      else begin
         ahb_if.HWDATA <= req.HWDATA;
         @(posedge ahb_if.HCLK);
         while(ahb_if.HREADY != 1) begin
            @(posedge ahb_if.HCLK);
         end
         req.HRESP = ahb_if.HRESP;
      end
      // Return the Request as Response
      seq_item_port.put(req);
      end_tr(req);
    end
   endtask: do_pipelined_transfer
 
 endclass: ahb_pipelined_driver


////////// Pipelined Sequence ////////// 
 class ahb_pipelined_seq extends uvm_sequence  #(ahb_seq_item);
   `uvm_object_utils(ahb_pipelined_seq)
 
   logic [31:0] addr[10]; // To save addresses
   int count; // To ensure that the seq does'nt complete too early
 
   // Constructor
   function new (string name);
      super.new(name);
   endfunction: new
 
   // Task body()
   task body;
 
      ahb_seq_item req;
      req = ahb_seq_item::type_id::create("req", this);
      use_response_handler(1); // Enable Response Handler
      count = 0;
 
      for(int i=0; i<10; i++) begin
        start_item(req);
        assert(req.randomize() 
            with {MWRITE == 1; HBURST == SINGLE; HADDR 
            inside {[32'h0010_1000:32'h0010_1FFC]};});
        addr[i] = req.HADDR;
        finish_item(req);
      end
 
      foreach (addr[i]) begin
        start_item(req);
        req.HADDR = addr[i];
        req.HWRITE = 0;
        finish_item(req);
      end
 
      // Wait till last seq item is over
      wait(count == 20);
   endtask: body
 
   // This response_handler function is enabled 
   // to keep the sequence response FIFO empty
   function void response_handler(uvm_sequence_item response);
      count++;
   endfunction: response_handler
 
 endclass: ahb_pipelined_seq

UVM APB Driver Example.

// APB Bus Interface
interface apb_interface;
 
   logic clk;
   logic rstn;
   logic [31:0] Addr;
   logic [31:0] Write_Data;
   logic RNW;
   logic Valid;
   logic Ready;
   logic [31:0] Read_Data;
   logic Error;
 
endinterface: apb_interface

// APB Bus Sequence Item Class
class apb_seq_item extends uvm_sequence_item;
   `uvm_object_utils(apb_seq_item)
 
   // Request fields
   rand logic [31:0] addr;
   rand logic [31:0] write_data;
   rand bit read_not_write;
   rand int delay;
 
   // Response fields
   bit error;
   logic [31:0] read_data;
 
endclass: apb_seq_item

// APB Bus Driver Class
class apb_bus_driver extends uvm_driver #(apb_seq_item);
   `uvm_component_utils(apb_bus_driver)
 
   apb_seq_item req;
 
   virtual apb_interface apb_if;
 
   function new (string name, uvm_component parent);
      super.new(name, parent);
      endfunction: new
 
   task run_phase (uvm_phase phase);
 
      apb_if.Valid <= 0;
      apb_if.RNW <= 0;
 
      // Out of Reset
      @(posedge apb_if.rstn);
      // Pin Level Transfer
      forever begin
         seq_item_port.get_next_item(req);
         repeat(req.delay) begin
            @(posedge apb_if.clk);
         end
         apb_if.Valid <= 1;
         apb_if.Addr <= req.addr;
         apb_if.RNW <= req.read_not_write;
         if (req.read_not_write == 0) begin
            apb_if.Write_Data <= req.write_data;
         end
         while(apb_if.Ready != 1) begin
            @(posedge apb_if.clk);
         end
         // At the end of pin level bus transaction
         // Copy response data into the req related fields
         if (req.read_not_write == 1) begin
            req.read_data <= apb_if.Read_Data;
         end
         req.error <= apb_if.Error;
         apb_if.Valid <= 0;
         seq_item_port.item_done();
      end
   endtask: run_phase
endclass: apb_bus_driver

// APB Bus Sequence
class apb_bus_seq extends uvm_sequence #(apb_seq_item)
   `uvm_object_utils(apb_bus_seq)
 
   function new(string name);
      super.new(name);
   endfunction: new
 
   // No. of iterations
   rand int iti = 30
 
   apb_seq_item req;
 
   task body();
      req = apb_seq_item::type_id::create("req", this);
      repeat(iti) begin
         start_item(req);
         assert (!req.randomize() 
            with {addr inside {[32`h1000_0000:32`h1000_001C]};}) 
         begin
            `uvm_error("Body", "Randomization Error");
         end 
         finish_item(req);
         `uvm_info ("Response Fields", 
            $sformatf("Read Data = %h", req.read_data), UVM_LOW)
      end
   endtask: body
 
endclass: apb_bus_seq

UVM PCM Driver Example.

// Interface Declaration
interface adpcm_int;
 
   logic clk;
   logic frame;
   logic [3:0] data;
 
endinterface: adpcm_int


// Transaction item class adpcm_txn
class adpcm_txn extends uvm_sequence_item;
   `uvm_object_util(adpcm_txn)
 
   rand logic[3:0] data;
   rand int delay;
 
   function new (string name);
      super.new(name);
   endfunction: new
 
   constraint del_bet_pac {delay inside {[1:20]};}
 
endclass: adpcm_txn


// Driver class adpcm_drv
class adpcm_drv extends uvm_driver #(adpcm_txn);
   `uvm_component_utils (adpcm_drv)
 
   adpcm_txn req;
 
   virtual adpcm_int adpcm_if;
 
   function new(string name, uvm_components parent)
      super.new(name, parent);
   endfunction: new
 
   task run_phase (uvm_phase phase);
 
      // Default conditions
      adpcm_if.frame <= 0;
      adpcm_if.data <= 0;
      forever begin
         seq_item_port.get_next_item(req);
         repeat(req.delay) begin
            @(posedge adpcm_if.clk);
         end
 
         adpcm_if.frame <= 1;
         for (int i = 0; i < 8; i++) begin
            @(posedge adpcm_if.clk);
            adpcm_if.data <= req.data[3:0];
            req.data = req.data >> 4;
         end
         adpcm_if.frame <= 0;
         seq_item_port.item_done();
      end
   endtask: run_phase
 
endclass: adpcm_drv

                                                                                                                                                                   
// Sequence Class adpcm_seq
class adpcm_seq extends uvm_sequence #(adpcm_txn);
   `uvm_component_utils (adpcm_seq)
 
   adpcm_txn req;
 
   rand int no_of_reps = 10;
 
   function new (string name);
      super.new(name);
   endfunction: new
 
   task body;
      req = adpcm_txn::type_id::create("req", this);
      for (int i = 0; i < no_of_reps; i++) begin
         start_item(req);
         if (!req.randomize()) begin
            `uvm_error("BODY", "req randomization failed")
         end
         finish_item(req);
         `uvm_info("ADPCM_SEQ BODY", 
            $sformatf("Transmitted frame %0d", i), UVM_LOW)
      end
   endtask: body
 
endclass: adpcm_seq

Saturday, October 29, 2016

AMBA 101.

Advanced Microcontroller Bus Architecture by ARM
  • ASB - advanced system bus
  • APB - advanced peripheral bus (used for low power peripheral modules)
  • AHB - advanced high performance bus
    • Arbitration
      • round robin priority scheme (default priority: master0)
      • fair chance
      • random access
      • high priority
    • burst transfer 
      • undefined length or 4, 8, 16 in length
      • fixed address, incremental address, or wrap address for cache line
    • split transactions
    • multiple masters
      • through a central arbiter
      • through  multiple slave level arbiters in multi-layer AHB-Lite system.
      • masters could be DMA controller, a peripheral core master interface, etc.
    • wider address bus, separate read or write data bus
    • larger data paths (multiplexed, not tri-state)
    • pipelined operation
    • wait-state insertion
    • data-valid signal HREADY
  • AHB and APB is linked through a bridge that acts as the master to the peripheral bus slave devices.

AHB Signals
  • General
    • HCLK
    • HRESET
  • Arbiter / Master
    • HBUSREQ (one from each master) 
    • HGRANT (one for each master)
  • Master / Slave
    • HRESP ([1:0] or [0] in AHB-Lite)
      • 00 - OKAY
      • 01 - ERROR
      • 10 - RETRY
      • 11 - SPLIT
    • HREADY (used by slave to insert wait state)
      • when it's low (from slave) all control signals shall hold their values.
    • HTRANS[1:0] (set according to RD or WR)
      • 00 - IDLE
      • 01 - BUSY (master can use BUSY to insert wait state during bursting)
      • 10 - NONSEQ
        • First transfer of an AHB sequence is always NONSEQ
      • 11 - SEQ
        • All transfer following the first shall be SEQ in nature.
    • HWRITE
    • HADDR [31:0] (muxed from individual masters to slaves and address decoder)
    • HRDATA / HWDATA
  • Slave / Arbiter
    • HMASTER [3:0] / HMASTLOCK - from arbiter
    • HSPLIT# [15:0] - one from each slave
  • Address Decoder / Slave
    • HSEL# (one for each slave unit)
  • More from Masters to Slave
    • HSIZE[2:0]
    • HBURST[2:0]
      • 4, 8, 16 in size
      • incremental
      • wrapping
      • 000 - single
      • 001 - INCR
      • 010 - WRAP4
      • 011 - INCR4
      • 100 - WRAP8
      • 101 - INCR8
      • 110 - WRAP16
      • 111 - INCR16
    • HPROT[3:0] - protection control
    • HLOCK# - locked transfer, one from each master
      • lowered during the last transfer of an AHB sequence
  • Example Auxilary Signals for AHB Masters
    • REQ_VLD - input to bus master, asserted when HBUSREQ is asserted
    • WR - input to bus master, high when HWRITE is high
    • RD -  input to bus master, high when HWRITE is low
    • IN_ADDR[31:0] - input to bus master, used to decide HADDR[31:0]
    • IN_DATA[31:0]
    • LEN#
    • LAST
    • OUT_DATA[31:0] - output from bus master
    • REQ_WR_DATA - output from bus master
      • It shall be high when (REQ_ADDR & WR) to ensure data shall be put on data bus one cycle after address is on.
      • When REQ_WR_DATA ==1, IN_DATA will be put to data bus in next cycle.
    • REQ_RD_DATA - output from bus master
      • It shall be high when it's a read transfer and HREADY == 1.
    • REQ_ADDR - output from bus master
      • It shall be high when (HREADY & HGRANT) to ensure master can put address in next cycle.
      • When REQ_ADDR == 1, IN_ADDR will be put to address bus in next cycle.

AHB Phases
  • address/control 
  • phase data phase

AHB Protocols
  1. bus master sends HBUSREQ to arbiter and an address, decoded by central decoder to provide a dedicated HSEL to selected slave unit.
  2. Slaves should only sample address when both HSEL and HREADY are high.
  3. If the slave is under re-configuration or needs to terminate a transaction, it saves the Hmaster number, and sends RETRY or SPLIT to arbiter and arbiter remove the requesting master from list until the targeted slave de-assert Hsplit. If RETRY is sent, the transaction is dropped.
  4. When the slave is ready, it signals the arbiter with the saved master number and the arbiter grants the bus access to the master to restart the transaction.
  5. No master can have more than one pending split transaction.
  6. Otherwise, master gets Hgrant and lock the bus. 
  7. During burst mode (size indicated by HBURST[2:0]), master can insert wait state by sending HTRANS == BUSY. The slave has to send immediate OKAY in next cycle as for the case of IDLE and ignore the transfer.
  8.  First burst cycle is always NONSEQUENTIAL.
  9. HADDR must be aligned to the HBURST size, that is, A[1:0] == 2'b00 in word transfer and A[0] == 1'b0 in halfword transfer.
  10. If a master is granted the bus without requesting it, it has to drive the transfer type IDLE.

APB Signals
  • PCLK
  • PRESETn - active LOW
  • PSEL# - APB select
  • PEN or PENABLE - APB strobe
  • PADDR[31:0] - Address bus
  • PWRITE - Transfer direction
  • PWDATA[31:0] - Write data bus (can be 8, 16, 32 bit)
  • PRDATA[31:0]  - Read data bus
  • PREADY

APB States
  • IDLE       : (~PSEL & ~PEN)
  • SETUP    : (  PSEL & ~PEN)
  • ACCESS : (  PSEL &   PEN)

AHB/APB Bridge Approach
  • Cross clock domain data transfer
    • handshake signaling method (double stage synchronizer)
    • asynchronous FIFO

ASB Signals
  • AGNT# - Bus grant
  • AREQ# - Bus request
  • BA[31:0] - Address bus
  • BCLK - Bus clock
  • BD[31:0] - Data bus
  • BERROR - Error response
  • BLAST - Last response
  • BLOK - Locked transfer
  • BnRES - Reset
  • BPROT[1:0] - Protection control
  • BSIZE[1:0] - Transfer size
  • BTRAN[1:0] - Transfer bype (driven when AGNT# is asserted)
    • ADDRESS-ONLY
    • NON-SEQUENTIAL
    • SEQUENTIAL
  • BWAIT - Wait response
  • BWRITE - Transfer direction
  • DSEL# - Slave select


UVM Coverage.

Basics
  • Put all covergroups in a class or module
  • Use local variables in the class or module
  • Make covergroups sensitive to a variable or explicitly sample a variable
  • Have a coverage test plan
  • Use automatic bins for simple covergroup
  • Code coverage is not functional coverage
    • line coverage
    • block / statement coverage
    • branch coverage
    • path coverage
    • toggle coverage
    • expression coverage
    • FSM coverage
    • transition coverage

<coverpoint_name>  :  coverpoint  <expression>  { bins <bin_name> = { <list of values > } }
class coverage extends uvm_agent;
   `uvm_component_utils (coverage)

   tlm_analysis_fifo #(mem_req) req_fifo;
   mem_req req;
   mem_op op;
   logic [15:0] addr;

   covergroup mem_ops;
      coverpoint memop {
         bins action[] = {read, write};
      }

   coverpoint addr {
         bins zeros  = {0};
         bins others = {[1 : 16'hFFFE]};
         bins ones   = {16'hFFFF};
      }
      edges : cross op, addr;
   endgroup

   covergroup alu_cv;

      all_ops : coverpoint op;
      a_op: coverpoint A {bins Ais0 = {'h00};}
      b_op: coverpoint B {bins Bis0 = {'h00};}

   endgroup

   function new (string name, uvm_component parent);
      super.new(name, parent);
      mem_ops = new();
      alu_cv = new();
   endfunction : new

   task run();
      mem_data cln;
      mem_req req_tx;
      forever begin : run_loop
         req_fifo.get (req_tx);
         op = req_tx.op;
         addr = req_tx.addr;
         mem_ops.sample();
      end
   endtask : run

endclass


Example: automatic bins
   typedef enum {add, and, xor, mul, rst, nop} op_t;

   covergroup opcov;
      coverpoint op;
   endgroup : opcov

   task sample_req;
      A = req.A;
      B = req.B;
      op = req.op;
      opcov.sample();
   endtask

   covergroup alu_cv2;

      coverpoint op;
      coverpoint A;
      coverpoint B;

      option.auto_bin_max = 4; // default to 64 bins

   endgroup


Example: Basic Bins
   covergroup opcov;
      coverpoint op;
      A00FF : coverpoint A {
         bins zeros = { 0 };
         bins ones  = { 8'hFF };
      }
      B00FF : coverpoint B {
         bins zeros_ones  = { 0, 8'hFF };
      }
   endgroup


Bins with Ranges, Bins with sequences
   typedef enum {add, and, xor, mul, rst, nop} op_t;

   covergroup opcov;
      coverpoint op {
         bins single_cyc = {[add : xor] , rst, nop};
         bins multi_cyc  = {mul};
      }
   endgroup : opcov

   // Automatic bins with ranges
   bins onepervalue [] = {< list of="" values="" >};
   bins n_bins [n] = { < list of="" values="" >};
   bins threebins [3] = {[1:2],[2:6]};
   // same as 
   // bins threebins [3] = {1,2,2,3,4,5,6};

   // Bins with sequences
   // run multi-cycle after reset
   // bins bin_name = ( < value1 > => < value2 >);

   covergroup opcov;
      coverpoint op {
         bins single_cycle = {[add : xor], rst, nop};
         bins multi_cycle  = {mul};
         bins mult_rst = (mul => rst);
         bins rst_mult = (rst => mul);
      }
   endgroup


Bins with multiple value transitions in sequences
 
   // Bins with multiple value transitions
   // bins bin_name = (< value list >  =>  < value list >);
   // 1, 2 => [3:5], 7
   // 1=>3, 2=>3, 1=>4, 2=>4, 1=>5, 2=>5, 1=>7, 2=>7
   bins op_rst[]   = ( [add : nop ] => rst );
   bins rst_mult[] = ( rst => [add : nop]);

   // multi-cycle after single-cycle
   bins singl_mul[]   = ( [add : xor ], nop => mul );

   // single-cycle after multi-cycle
   bins mul_sngl[]   = ( mul => [add : xor ], nop );

   // Run all operations twice in a row 
   // bins <name> = (<value list> [* n]); bins <name> = (<value list> [* n:m]);
   // Ex: Run 3-5 Multiplies in a row
   bins twoops[] = ([add:nop] [*2]);
   bins manymult = (mul [* 3:5]);

   // Nonconsecutive Repetition
   // <value list> [= n:m];     // nonconsecutive operator 
   // <value list> [-> n:m]; // goto operator
   // • Nonconsecutive Operator (=) matches if n:m values occur 
   //        in a list of value regardless of the terminating value.
   // • Goto Operator (->) matches if n:m values occur in a list 
   //        of values and then a terminating value appears.

   bins rstmulrst   = (rst => mul [=  2] => rst);
   // rstmulrst (match): rst => mul => xor => mul => and => rst
   bins rstmulrstim = (rst => mul [-> 2] => rst);
   // rstmulrst and rstmulrstim (match): rst => mul => xor => and => mul => rst


Cross Coverage : Use Cross and Binsof to capture combinations of values
 
   covergroup zeros_ones_ops;

      all_ops : coverpoint op {
         ignore_bins null_ops = {rst, nop};
      }
      a_op: coverpoint A {
         bins zeros  = {'h00};
         bins others = {['h01:'hFE]};
         bins ones   = {'hFF};
      }
      b_op: coverpoint B {
         bins zeros  = {'h00};
         bins others = {['h01:'hFE]};
         bins ones   = {'hFF};
      }

      basic : cross a_op, b_op, all_ops;

      with_a0bin : cross a_op, b_op, all_ops {
         bins a0bin  = binsof (a_op.zeros);
      }

      // bins <bin> = binsof(<somebins>) && binsof(<otherbins>); 
      // bins <bin> = binsof(<somebins>) || binsof(<otherbins>);
      zeros_ones : cross a_op, b_op, all_ops {
         bins AorBzero  = binsof (a_op.zeros) || binsof (b_op.zeros);
         bins AorBones  = binsof (a_op.ones)  || binsof (b_op.ones);
         ignore_bins the_others =
                binsof (a_op.others) && binsof (b_op.others);
      }

      // intersect qualifier
      // bins <bin> = binsof(<somebins> intersect (<value_list>))
      zeros_ones_2 : cross a_op, b_op, all_ops {
         bins add_bin  = binsof (all_ops) intersect {add};
         ignore_bins x = ! binsof (all_ops) intersect {add};
      }

   endgroup



Friday, October 28, 2016

SystemVerilog Question.


  • Automatic vs Static
    For a static task, multiple invocations of the same task will reference the same local variables. For an automatic task, the local variables will be unique to each invocation of the task. The function should be automatic so that there will be multiple memory allocations for the index variable to show increasing values instead of a single value.
  • packed vs unpacked
    Unpacked array is an array with gap between variables.
  • Join / Join_any / Join_none
    Join (and all done) / Join_any (or any done) / Join_none (none is done, non-blocking)
    (use "wait fork;" or implement watch_dog timer for "join_none" for synchronization)
  • Wire vs Logic
    Logic and wire are almost the same except wire can be driven by multiple sources. Logic can only driven by single source.
  • Virtual
    Means "abstract"

Randomization.


  • $random : return an 32-bit signed random number.
  • $urandom : return an 32-bit unsigned random number.
  • $srandom(seed) : set random seed for $urandm.
  • use run-time switch : +ntb_random_seed=seed_value
  • $urandom_range(min, max)
  • randcase

randcase
   10 : f1();
   20 : f2();
   30 : x = 100;
   50 : randcase ... endcase; // nested
endcase

Thursday, October 27, 2016

UVM Report.


  • Formatting
    • $sformat (str, "%m : a = $2h", a);
    • $timeformat (-9, 2, " ps", 4);
    • timeunit 100ps;
    • timeprecision 10ps;
  • System Calls
    • $display
    • $fdisplay - to write to files.
    • $time, $stime, $realtime,
  • Opening Files
    • integer fha = $fopen("fileaname");
    • integer fhb = $fopen("filebname");
    • integer fhboth = filea | fileb;
    • $fdisplay (fha, "string");
    • $fclose (fhboth);
  • UVM_macros for Reporting
    • $display (`__FILE__);
    • `uvm_info ("message_ID", "This is info message", verbose_level, UVM_INFO);
    • `uvm_warning ("message_ID", "message", Severity);
    • `uvm_error ("message_ID", "message", Severity);
    • `uvm_fatal ("message_ID", "message", Severity);
    • Each reporting method call gets a verbosity number
    • The object has a reporting verbosity number
    • The method acts only if its verbosity number is below the object's verbosity number
    • inst.set_report_verbosity_level_hier (800);
  • UVM Report Control
    • Verbosity level set
    • Reporting methods for actions
      • in end_of_elaboration_phase
      • UVM_DISPLAY
      • UVM_LOG - write to a file
        • Open the file(s) and get the MCDs
        • Set the logging action on the ID's
        • Attach the MCDs to the severities or ID's
          • set_report_default_file() 
          • set_report_id_file ("printer", printer_file);
          • set_report_severity_action
            (UVM_WARNING, UVM_DISPLAY | UVM_LOG);
          • set_report_severity_file (UVM_WARNING, warning_file);
          • dump_report_state();
          • set_report_max_quit_count (10);
      • UVM_COUNT
      • UVM_EXIT
      • UVM_CALL_HOOK - call user defined method
      • UVM_STOP
    • Reporting action controls
      • set_severity_action (severity sv, action a)
      • set_id_action (string id, action a)
      • set_severity_id_action (severity sv, string id, action a)
      • set_severity_action_hier (severity sv, action a)
      • set_id_action_hier (string id, action a)
      • set_severity_id_action_hier (severity sv, string id, action a)
      • Default:
        • UVM_INFO            : UVM_DISPLAY
        • UVM_WARNING  : UVM_DISPLAY
        • UVM_ERROR        : UVM_DISPLAY  |  UVM_COUNT
        • UVM_FATAL         : UVM_DISPLAY  |  UVM_EXIT
    • File ID

UVM Test Analysis.

Analysis Layer

  • Scoreboard / Subscriber / Monitor / Predictor
    • Watch / Observe
    • Recognize transactions
    • Place the transactions to the analysis ports
  • Coverage
  • Reporting
  • Simulation
    • Tests/Transactions -> Drivr -> DUT -> Responder -> TLM models
  • Can connect to multiple objects (unlike uvm_put_port)
  • Analysis Ports, Exports, Imps
  • Port, Export and Imp

Example of Monitor Class
class monitor extends interface_base;
   `uvm_component_utils(monitor)
   uvm_analysis_port #(mem_data) rspa;
   uvm_analysis_port #(mem_req)  reqa;

   function new (string name = "driver",
                uvm_component parent = null);
      super.new (name, parent);
   endfunction : new

   virtual function void build_phase(uvm_phase phase);
      super.build_phase(phase);
      reqa = new ("reqa", this);
      rspa = new ("rspa", this);
   endfunction: build_phase

   task run_phase(uvm_phase phase);
      mem_req  req = new(), c_req;
      mem_data rsp = new(), c_rsp;

      forever begin : monitor_loop

         @(posedge mif.clk);
         #UNIT_DELAY;
         req.load_data (mif.addr, mif.data, nop);
         rsp.load_data (mif.addr, mif.data);
         if (mif.wr) req.op = write;
         if (mif.rd) req.op = read;
         if (req.op != nop) begin
            $cast(c_req, req.clone());
            reqa.write (c_req);
         end
         if (mif.rd) begin
            $cast (c_rap, rsp.clone());
            rspa.write (c_rsp);
         end

      end : monitor_loop
   endtask
endclass : monitor


Create a Subscriber
  • Instantiate a "uvm_tlm_analysis_fifo"
  • Connect to the analysis_port at the top level
  • Use get() to block and take data out of the analysis fifo



Create a Predictor
  • It gets a request from the analysis_port connected to the monitor.
  • It predicts what response transaction will appear.

class predictor extends uvm_agent;
   `uvm_component_utils (predictor)
   logic [15:0] mem [2**16-1 : 0];

   uvm_tlm_analysis_fifo #(mem_req) reqfifo;
   uvm_put_port #(mem_data) rsp_p; // to connect to comparator
   mem_data rsp = new();

   function new (string name, uvm_component parent);
      super.new (name, parent);
   endfunction: new

   virtual function void build_phase (uvm_phase phase);
      super.build_phase(phase);
      req_fifo = new("req_fifl", this);
      rsp_p = new ("rsp_po", this);
   endfunction : build_phase

   task run_phase (uvm_phase phase);
      mem_data cln;
      mem_req req_txn;
      forever begin : run_loop
         req_fifo.get (req_tx);
         case (req_tx.op)
            write : mem[req_tx.addr] = req_tx.data;
            read  : begin : read_op
               rsp.load_data (req_tx.addr, mem[req_tx.addr]);
               $case (cln, rsp.clong());
               rsp_p.put(cln);
            end : read_op
         endcase
      end : run_loop
   endtask : run_phase

endclass : predictor


Create a Comparator and a Printer to Report
  • It gets a response transaction from the monitor.
  • It compares the actual response transaction to the predicted response transaction.

class comparator extends uvm_agent;

   `uvm_component_utils (comparator)

   uvm_tlm_analysis_fifo #(mem_data) actual_f;
   uvm_get_port #(mem_data) predicted_p;
   mem_data actual_rsp, predicted_rsp;

   function new ...

   virtual function void build_phase (uvm_phase phase);
      super.build_phase (phase);
      actual_f = new ("actual_f", this);
      predicted_p = new ("predicted_p", this);
   endfunction : build_phase

   task run_phase (uvm_phase phase);
      forever begin : run_loop
         actual_f.get (actual_rsp);
         predicted_p.get (predicted_rsp);
         if (actual_rsp.comp(predicted_rsp))
            uvm_report_info ("run",
               $psprintf ("passed: %s", 
                          actual_rsp.convert2string()) );
         else
            uvm_report_info ("run",
               $psprintf ("ERROR: expected: %s does not match actual: %s", 
                          predicted_rsp.convert2string(),
                          actual_rsp.convert2string()) );
      end : run_loop
   endtask : run_phase
endclass : comparator

class printer #(type T = mem_data) extends uvm_agent;
   `uvm_component_utils (printer#(T))

   uvm_tlm_analysis_fifo #(T) a_fifo;

   function new ...

   virtual function void build_phase (uvm_phase phase);
      super.build_phase (phase);
      a_fifo = new ("a_fifo", this);
   endfunction : build_phase

   task run_phase (uvm_phase phase);
      forever begin
         T data;
         a_fifo.get(data);
         uvm_report_info ("run", data.convert2string());
      end
   endtask : run_phase
endclass : printer


class mem_data extends uvm_transaction;
   `uvm_object_utils (mem_data)
   rand logic [15:0] data;
   rand lobic [15:0] addr;

   virtual function bit comp (uvm_object rhs);
      mem_data RHS;
      $cast (RHS, rhs);
      return ((RHS.addr == addr) && (RHS.data == data));
   endfunction : comp
endclass : mem_data

class mem_req extends mem_data;
...
endclass : mem_req


Top Leven Test Environment
class test_env extends uvm_env;
   `uvm_component_utils (test_env)

   tester tst;
   driver drv;
   uvm_tlm_fifo #(mem_req) tester2driv;

   printer #(mem_req)  req_prt;
   printer #(mem_data) rsp_prt;
   monitor mon;
   predictor pred;
   comparator cmp;
   uvm_tlm_fifo #(mem_data) pred2cmp;

   function new (string name = "tester_env",
                 uvm_component parent = null );
      super.new (name, parent);
   endfunction : new

   virtual function void build_phase (uvm_phase phase);
      super.build_phase (phase);
      tst = tester::type_id::create ("tst", this);
      drv = driver::type_id::create ("drv", this);
      tester2drv = new ("tester2drv");

      req_prt = printer#(mem_req)::type_id::create("req_prt", this);
      rsp_prt = printer#(mem_data)::type_id::create("rsp_prt", this);

      mon = monitor::type_id::create ("mon", this);
      pred = predictor::type_id::create ("pred", this);
      cmp = comparator;:type_id::create ("cmp", this);
      pred2cmp = new("pred2cmp"< this);
   endfunction : build_phase

   virtual function void connect_phase (uvm_phase phase);
      super.connect_phase(phase);
      tst.tb_port.connect (tester2drv.put_export);
      drv.req_f.connect (tester2drv.get_export);
      cmp.predicted_p.connect (pred2cmp.get_export);
      pred.rsp_p.connect(pred2cmp.put_export);
      mon.req_a.connect (pred.req_fifo.analysis_export);
      mon.rsp_a.connect (cmp.req_fifo.analysis_export);
      mon.req_a.connect (req_prt.a_fifo.analysis_export);
      mon.rsp_a.connect (rsp_prt.a_fifo.analysis_export);

   endfunction : connect_phase

endclass : test_env

class bucket #(type T = mem_data) extends printer #(T);

   typedef bit_bucket#(T) thistype;
   `uvm_component_param_utils (thistype)

   function new ...

   task run_phase (uvm_phase phase);
      forever begin
         T data;
         a_fifo.get(data);
      end
   endtask : run_phase

endclass : bucket

class qtest extends uvm_test;
   `uvm_component_utils (qtest)

   test_env t_env;

   function new ...

   virtual function void build_phase (uvm_phase phase);
      super.build_phase (phase);
      printer#(mem_data)::type_id::set_type_override
         (bucket#(mem_data)::get_type());
      printer#(mem_req)::type_id::set_type_override
         (bucket#(mem_data)::get_type());
      t_env = test_env::type_id::create ("t_env", this);
   endfunction : build_phase

endclass : qtest



SystemVerilog Demystified.

Virtual (Abstract) vs Concrete
The clone method is used to provide a deep (nested) copy of an object. clone first allocates new memory for the object, then copies over each field to the new object. If a field is an object handle, then instead of copying the handle (which would do a "shallow" copy) you would call fieldname.clone() to recursively allocate memory for that field (a "deep" copy).

Clone (Virtual) vs Copy (Concrete)

class base;
int p1;
  function void copy(base orig);
    this.p1 = orig.p1;
  endfunction
endclass
class ex_base;
  int p2;
  function void copy(base orig);
    super.copy(b);
    this.p2 = orig.p2;
  endfunction
endclass
 
base b1,b2;
ex_base eb1, eb2;
initial begin
   eb1 = new; eb2 = new();
   eb2.p2 = 5;
   b1 = eb1; b2 = eb2;
   b1.copy(b2); // p2 is not copied
   eb1.copy(eb2); // p2 is copied
end

// Since copy() is not virtual, calling b1.copy() calls base::copy(), 
// and the additional property p2 is not copied even though it exists 
// in object referenced by b1.

Wednesday, October 26, 2016

UVM Configuration DB Gotchas.


  • Missing super.build_phase()
  • Missing field macro
  • UVM_READONLY on field
  • Missing get() after set() changes the entry
  • uvm_config_object::set() writes a null object
  • Wrong or mismatched types
  • Missing $cast in explicit get()
  • Wrong string in field names, wrong context
  • Not a good practice to use wildcard in ::set() - creating too much visibility

 References:

UVM Configuration DB.

Concepts
  • Share information between
    • Test
      • Top environment
        • sub environment
          • agents
            • sequencers
            • monitors
            • drivers
  • Need a consistent way of storing shared data 
  • Need simple, flexible access from anywhere
  • Need automatic access (done by uvm_component::build_phase())
  • Compare to traditional
    • enclosing pushes
    • ex. env.m_this_config = m_cfg
How to Use
  • Share the information of Physical IFs (between DUT and uvm_test)
    • Put into configuration db at top test module and get it in
      uvm_env.uvm_agent
      uvm_env.uvm_agent.uvm_driver
      uvm_env.uvm_agent.uvm_sequencer
      uvm_env.uvm_agent.uvm_monitor
  • Share DUT specific information

Syntax
//
// UVM 1.1
set_config_int(...) => uvm_config_db#(uvm_bitstream_t)::set(cntxt,...)
set_config_string(...) => uvm_config_db#(string)::set(cntxt,...)
set_config_object(...) => uvm_config_db#(uvm_object)::set(cntxt,...)
//
// UVM 1.2
// type T=int
// class uvm_config_db#(type T=int) extends uvm_resource_db#(T)
//
//                   context, inst,  key,   value   
uvm_config_db#(T)::set(cntxt,"inst","field",value); // modify central entries
uvm_config_db#(T)::get(cntxt,"inst","field",value); // update local variabbles
// There is a uvm11-to-uvm12.pl conversion script
uvm_config_db#(T)::exists(cntxt,"inst","field");
uvm_config_db#(T)::wait_modified(cntxt,"inst","field");

// For objects use this
set_config_object::set(this,"env.agent1","config", m_config);
// For enums use this
set_config_int::set(this,"env.agent1","bus_sz", SZ_128 );

// cntxt must be of type uvm_component, null or uvm_root::get()
// m_config: recommend to use uvm_object and $cast 
// Examples:
uvm_config_db#(T)::set(uvm_root::get(),”test1.env.agent1”, ”config”, m_config);
uvm_config_db#(T)::set(this,”env.agent*”,”config”, m_config);
uvm_config_db#(T)::set(null,”*”,”global_cfg”, m_global_cfg);

// to fetch the entry
if (!uvm_config_db#(uvm_object)::get(this, "","config",m_config)) begin
   `uvm_fatal(...) 
end
// check if it exists
if(!uvm_config_db#(int)::exists(this,"","low_power_mode")) begin 
   // do something interesting
end

// To automate field configuration
// Use uvm_config_object typedef
// Use uvm_object and $cast to concrete type for get()
function void uvm_component::build_phase(...); 
   // find fields, do get(), $cast
   apply_config_settings(...); 
endfunction

// Gotchas: 1. Don't miss field-macro
//         2. Make sure it's not UVM_READONL
/          3. remember to use super.build

class my_comp extends uvm_component;
   `uvm_component_utils_begin(my_comp)
      `uvm_field_int(my_field,UVM_DEFAULT) 
      `uvm_field_object(my_special,(UVM_DEFAULT|UVM_READONLY))
      `uvm_field_object(my_config,UVM_DEFAULT)  

      function void build_phase(...);
         super.build_phase(...);
         ...
      endfunction

// Using uvm_object and $cast in set() and get()
my_config m_config;
   ...
uvm_config_object::set(..., m_config);

uvm_object tmp;
uvm_config_object::get(..., tmp); 
$cast(m_config, tmp); // back to original type

// Using enums (can be int, uvm_bitstream_t or uvm_integral_t
my_enum_t m_bus_sz;
uvm_config_int::set(... , "m_bus_sz", SZ16);

int tmp;
uvm_config_int::get(... ,"m_bus_sz", tmp)
m_bus_sz = my_enum_t'(tmp); // back to original type

// Recommend use the factory 
m_srio_config = uvc_srio_config::type_id::create("m_srio_config");


Hierarchy of Configuration Objects
class top_env_config extends uvm_object; 
   env1_config m_env1_config; 
   env2_config m_env2_config;
   ...
endclass

class env1_config extends uvm_object;
   int some_var;
   int some_other_var;
   agent1_config m_agent1_config;
   agent2_config m_agent2_config;
   ... 
endclass

class top_env extends uvm_env;
   env1 m_env1;
   env2 m_env2;
   top_env_config m_config;
   ...
   'uvm_component_utils_begin(top_env)
      'uvm_field_object(m_config, UVM_DEFAULT)
   'uvm_component_utils_end

   function build_phase();
      super.build_phase();
      set_config_object(this, "env1","m_config",
                       m_config.m_env1_config);
      set_config_object(this, "env2","m_config",
                       m_config.m_env2_config);
      m_env1 = env1::type_id::create("m_env1");
      m_env2 = env2::type_id::create("m_env2");
   endfunction
endclass

// Next Level Down
class env1 extends uvm_env; 
   env1_config m_config;
   ...
   'uvm_component_utils_begin(top_env)
      'uvm_field_object(m_config, UVM_DEFAULT)
   'uvm_component_utils_end

   function void build_phase();
      super.build_phase();
      set_config_object(this, "m_agent1","m_config",
                m_config.m_agent1_config); 
      set_config_object(this, "m_agent2","m_config",
                m_config.m_agent2_config); 
      m_agent1 = env1::type_id::create("m_agent1"); 
      m_agent2 = env2::type_id::create("m_agent2");
   endfunction
endclass


Turn on the debugging in simulation

% sim_cmd +UVM_TESTNAME=my_test +UVM_CONFIG_DB_TRACE