Showing posts with label medium. Show all posts
Showing posts with label medium. Show all posts

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;
    }
}



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());
   }
}

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 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

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