Package edu.byu.ece.rapidSmith.bitstreamTools.configuration

Source Code of edu.byu.ece.rapidSmith.bitstreamTools.configuration.FrameAddressRegister

/*
* Copyright (c) 2010-2011 Brigham Young University
*
* This file is part of the BYU RapidSmith Tools.
*
* BYU RapidSmith Tools is free software: you may redistribute it
* and/or modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* BYU RapidSmith Tools is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* A copy of the GNU General Public License is included with the BYU
* RapidSmith Tools. It can be found at doc/gpl2.txt. You may also
* get a copy of the license at <http://www.gnu.org/licenses/>.
*
*/
package edu.byu.ece.rapidSmith.bitstreamTools.configuration;

import edu.byu.ece.rapidSmith.bitstreamTools.bitstream.BitstreamUtils;
import edu.byu.ece.rapidSmith.bitstreamTools.configurationSpecification.AbstractConfigurationSpecification;
import edu.byu.ece.rapidSmith.bitstreamTools.configurationSpecification.BlockSubType;
import edu.byu.ece.rapidSmith.bitstreamTools.configurationSpecification.BlockType;
import edu.byu.ece.rapidSmith.bitstreamTools.configurationSpecification.XilinxConfigurationSpecification;

/**
* Represents the contents of a Xilinx Frame Address Register and performs proper
* frame address register incrementing. This class stores the FAR as
* a set of fields in the FAR rather than as a 32 bit number. This facilitates
* the FAR incrementing.
*
* This class contains many static methods that are used to evaluate Frame Address information
* based on configuration specifications. These static methods form a bridge between the
* values in the configuration specification and the frame adddress.
*/
public class FrameAddressRegister {

  /**
   * Creates an initial frame address register initialized to 0.
   */
  public FrameAddressRegister(XilinxConfigurationSpecification xcs) {
    configSpec = xcs;
    initFAR();
  }

  public FrameAddressRegister(XilinxConfigurationSpecification xcs, int farAddress) {
    configSpec = xcs;
    setFAR(farAddress);
  }
 
  public void initFAR() {
    top_bottom = 0;
    blockType = 0;
    row = 0;
    column = 0;
    minor = 0;   
  }

  public void setFAR(int address){
    top_bottom = getTopBottomFromAddress(address);
    blockType = getBlockTypeFromAddress(address);
    row = getRowFromAddress(address);
    column = getColumnFromAddress(address);
    minor = getMinorFromAddress(address);
  }

  /**
   * This function will increment the Frame Address Register (FAR) to the next address.
   * The frame address register does not follow a sequential increment pattern.  Instead,
   * it follows a very particular pattern. There are smaller counters within the FAR that
   * in the following order (from first to last): minor, column, row, top_bottom, and then
   * type.  See Xilinx UG071, Virtex-4 FPGA Configuration User Guide for more detail and
   * Xilinx UG191, Virtex-5 FPGA Configuration User Guide.
   * 
   * @return true if the resulting FAR is valid. return false if increment is invalid.
   *
   * Need better error checking and feedback
   */
  public boolean incrementFAR() {

    // Check to see if the block number is beyond the last block number.
    // If so, we can't increment and return false (bad FAR address - beyond the end)
    if (blockType >= configSpec.getBlockTypes().size())   
      return false;
       
    // Check to see if we have reached the last frame in a given COnfifguration block.
    if(minor == getFramesPerConfigurationBlock(configSpec, blockType, column) - 1){
      // End of a block. Initialize minor and check column.
      minor = 0;

      //If we have reached the max column for the specified type of block
      //set it to zero the check the row
      if(column == getNumberOfColumns(configSpec, blockType) - 1) {
        column = 0;
        // Last column. Move to a new row.
        //If we have reached the max row, then check the top_bottom,
        //else increment row
        if ((top_bottom == 0 && row == configSpec.getTopNumberOfRows() - 1) ||
            (top_bottom == 1 && row == configSpec.getBottomNumberOfRows() - 1)) {
          row = 0;         
          //If max top_bottom has been reached, set top_bottom to zero and check the
          //block type, else increment top_bottom
          if(top_bottom == 0){
            top_bottom = 1;
          }
          else if(top_bottom == 1){
            top_bottom = 0;
            //If the incremented type is greater than two, it is invalid and we
            //will return false. Otherwise, we are finished and return true.
            blockType++;
            if(blockType >= configSpec.getBlockTypes().size() ){
              return false;
            }
          }
        } else
          // not last row. Increment.
          row++;
      } else
        // Not last column. Increment.
        column++;
    }
    else {
      // Still in the middle of a block. Just increment the minor number.
      minor++;
    }
    return true;
  }
 
  public boolean incrementFAR(int num) {
    for (int i = 0; i < num; i++)
      if (!incrementFAR())
        return false;
    return true;
  }
 
  public boolean validFARAddress() {
    if (blockType >= configSpec.getBlockTypes().size())   
      return false;
    return true;
  }
  /**
   * Convert the current FAR address into a consecutive address
   */
  public int getConsecutiveAddress() {
    int address = 0;
    int i=0;
    // add addresses of block types that are *before* the current block type
    for (i = 0; i < blockType; i++)
      address += getFramesPerFARBlockType(configSpec, i);
    // add addresses of top for current block type if we are in the bottom
    if (top_bottom > 0)
      address += getFramesInTop(configSpec, blockType);
   
    // add addresses of rows in current block type that are *before* the current row
    // but in the same FAR block type
    address += row * getFramesPerRow(configSpec, blockType);
    // Add addresses of columns in current row that are *before* the current column
    for (i = 0; i < column; i++)
      address += getFramesPerConfigurationBlock(configSpec, blockType, i);
    // Add addresses of frames *before* current frame
    address += minor;
    return address;
  }
 
  public void setFARAddressFromConsecutiveAddress(int consecutiveAddress){
    int address = consecutiveAddress;
    //int i=0;

    // Determine block number
    blockType = 0;
    for (blockType = 0;                                      // Initialize block type to 0
      address >= getFramesPerFARBlockType(configSpec, blockType);      // See if address is large enough to skip current block
      address -= getFramesPerFARBlockType(configSpec, blockType++))    // If so, reduce the address count and increment block count
      ;

    // Determine Top or Bottom
    if (address >= getFramesInTop(configSpec, blockType)) {
      top_bottom = 1;
      address -= getFramesInTop(configSpec, blockType);
    }

    // Determine Row
    row = address / getFramesPerRow(configSpec, blockType);
    address -= getFramesPerRow(configSpec, blockType) * row;
   
    // Determine column
    for (column = 0;                                      // Initialize block type to 0
      address >= getFramesPerConfigurationBlock(configSpec, blockType, column);
      address -= getFramesPerConfigurationBlock(configSpec, blockType, column++))
      ;
    // detrmine minor
    minor = address;
  }

  public int getTopBottomFromAddress(int address) {
    return getTopBottomFromAddress(configSpec,address);
  }
  public int getAddressFromTopBottom(int topBottom) {
    return getAddressFromTopBottom(configSpec, topBottom);
  }
  public int getBlockTypeFromAddress(int address) {
    return getBlockTypeFromAddress(configSpec, address);
  }
  public int getAddressFromBlockType(int blockType) {
    return getAddressFromBlockType(configSpec, blockType);
  }
  public int getColumnFromAddress(int address) {
    return getColumnFromAddress(configSpec, address);
  }
  public int getAddressFromColumn(int column) {
    return getAddressFromColumn(configSpec, column);
  }
  public int getRowFromAddress(int address) {
    return getRowFromAddress(configSpec, address);
  }
  public int getAddressFromRow(int row) {
    return getAddressFromRow(configSpec, row);
  }
  public int getMinorFromAddress(int address) {
    return getMinorFromAddress(configSpec, address);
  }
  public int getAddressFromMinor(int minor) {
    return getAddressFromMinor(configSpec, minor);
  }

  public XilinxConfigurationSpecification getConfigurationSpecification() {
    return configSpec;
  }

  /**
   * Returns the FAR address as an integer based on the values of the FAR
   * address fields.
   */
  public int getAddress() {
    int far = 0;
    far |= getAddressFromTopBottom(top_bottom);
    far |= getAddressFromBlockType(blockType);
    far |= getAddressFromRow(row);
    far |= getAddressFromColumn(column);
    far |= getAddressFromMinor(minor);   
    return far;
  }

  public String getHexAddress() {
    return BitstreamUtils.toHexString(getAddress());
  }
 
  public int getTopBottom() { return top_bottom; }
  public int getBlockType() { return blockType; }
  public int getRow() { return row; }
  public int getColumn() { return column; }
  public int getMinor() { return minor; }

  /**
   * Prints out information about a frame address.
   */
  public String toString() {
    return toString(1);
  }
 
  /**
   * Level 0: hex address only
   * Level 1: Single line string that decodes the FAR
   */
  public String toString(int level) {
    if (level == 0)
      return getHexAddress();
       
    StringBuffer sb = new StringBuffer();

    // Print address
    sb.append("FAR="+BitstreamUtils.toHexString(getAddress())+", ");
        // Print top & bottom
    sb.append(AbstractConfigurationSpecification.getTopBottom(top_bottom));
    sb.append(" Type=" + AbstractConfigurationSpecification.getBlockType(configSpec, blockType) + " ("+blockType+")");   
    sb.append(", Row="+ row);
    sb.append(", Column=" + column +" (" +
        AbstractConfigurationSpecification.getBlockSubtype(configSpec, blockType, column) + "),");
    sb.append(" Minor="+ minor);
    return sb.toString();     
  }

  //////////////////////////////////////////////////////////////////////////////////////////////
  // Static Methods
  //////////////////////////////////////////////////////////////////////////////////////////////
 
  // Methods for extracting specific fields from a FAR address
  public static int getTopBottomFromAddress(XilinxConfigurationSpecification spec, int address) {
    return (address & spec.getTopBottomMask()) >>> spec.getTopBottomBitPos();
  }
  public static int getBlockTypeFromAddress(XilinxConfigurationSpecification spec, int address) {
    return (address & spec.getBlockTypeMask()) >>> spec.getBlockTypeBitPos();
  }
  public static int getColumnFromAddress(XilinxConfigurationSpecification spec, int address) {
    return (address & spec.getColumnMask()) >>> spec.getColumnBitPos();
  }
  public static int getRowFromAddress(XilinxConfigurationSpecification spec, int address) {
    return (address & spec.getRowMask()) >>> spec.getRowBitPos();
  }
  public static int getMinorFromAddress(XilinxConfigurationSpecification spec, int address) {
    return (address & spec.getMinorMask()) >>> spec.getMinorBitPos();
  }

  // Methods for creating FAR addresses from field values
  public static int getAddressFromTopBottom(XilinxConfigurationSpecification spec, int topBottom) {
    return topBottom << spec.getTopBottomBitPos();
  }
  public static int getAddressFromBlockType(XilinxConfigurationSpecification spec, int blockType) {
    return blockType << spec.getBlockTypeBitPos();
  }
  public static int getAddressFromColumn(XilinxConfigurationSpecification spec, int column) {
    return column << spec.getColumnBitPos();
  }
  public static int getAddressFromRow(XilinxConfigurationSpecification spec, int row) {
    return row << spec.getRowBitPos();
  }
  public static int getAddressFromMinor(XilinxConfigurationSpecification spec, int minor) {
    return (minor) << spec.getMinorBitPos();
  }

  // Methods for determining frame counts for various bitstream regions
  public static int getFramesPerFARBlockType(XilinxConfigurationSpecification spec, int block) { 
    return getFramesInTop(spec, block) + getFramesInBottom(spec, block);
  }
 
  public static int getFramesInTop(XilinxConfigurationSpecification spec, int block) {
    return getFramesPerRow(spec, block) * spec.getTopNumberOfRows();
  }
 
  public static int getFramesInBottom(XilinxConfigurationSpecification spec, int block) {
    return getFramesPerRow(spec, block) * spec.getBottomNumberOfRows();
  }
 
  public static int getFramesPerRow(XilinxConfigurationSpecification spec, int block) {
    int frames = 0;
    for (int i = 0; i < getNumberOfColumns(spec, block); i++) {
      frames += getFramesPerConfigurationBlock(spec, block,i);
    }
    return frames;
  }
  public static int getFramesPerConfigurationBlock(XilinxConfigurationSpecification spec, int blockNum, int column) {
    BlockType type = spec.getBlockTypes().get(blockNum);
    BlockSubType subType = spec.getBlockSubTypeLayout(type).get(column);
    int result = subType.getFramesPerConfigurationBlock();
    return result;
  }

  public static int getNumberOfColumns(XilinxConfigurationSpecification spec, int blockNum) {
      BlockType type = spec.getBlockTypes().get(blockNum);
      int result = spec.getBlockSubTypeLayout(type).size();
      return result;
  }

  public static int getNumberOfFramesPerBlockRow(XilinxConfigurationSpecification spec, int blockNum) {
    int columns = getNumberOfColumns(spec, blockNum);
    int frames = 0;
    for (int i = 0; i < columns; i++)
      frames+=getFramesPerConfigurationBlock(spec, blockNum, i);
    return frames;     
  }
 
  public static int getNumberOfFramesPerBlockTop(XilinxConfigurationSpecification spec, int blockNum) {
    return getNumberOfFramesPerBlockRow(spec, blockNum) * spec.getTopNumberOfRows();
  }
 
  public static int getNumberOfFramesPerBlockBottom(XilinxConfigurationSpecification spec, int blockNum) {
    return getNumberOfFramesPerBlockRow(spec, blockNum) * spec.getBottomNumberOfRows();
  }
 
  public static int getNumberOfFramesPerBlock(XilinxConfigurationSpecification spec, int blockNum) {
    return getNumberOfFramesPerBlockTop(spec, blockNum) + getNumberOfFramesPerBlockBottom(spec, blockNum);
  }
 
  public static int getNumberOfFrames(XilinxConfigurationSpecification spec) {     
      int blockTypes = spec.getBlockTypes().size();
    int frames = 0;
    for (int i = 0; i < blockTypes; i++)
      frames += getNumberOfFramesPerBlock(spec, i);
    return frames;
  }

  // Misc. static methods

  /**
   * Create an integer frame address from the various fields that make up the frame address
   * register.
   */
  public static int createFAR(XilinxConfigurationSpecification spec, int topBottom, int blockType,
      int row, int column, int minor) {
    int far = 0;
    far |= getAddressFromTopBottom(spec, topBottom);
    far |= getAddressFromBlockType(spec, blockType);
    far |= getAddressFromRow(spec, row);
    far |= getAddressFromColumn(spec, column);
    far |= getAddressFromMinor(spec, minor);
   
    return far;
  }

  /**
   * Determine the starting FAR address for a given block type
   */
  public static int createBlockStartingFAR(XilinxConfigurationSpecification spec, int blockType) {
    return createFAR(spec,0,blockType,0,0,0);
  }

  /**
   * Deterimine the block type number from a fixed block type object.
   */
  public static int getBlockTypeNumber(XilinxConfigurationSpecification spec, BlockType blocktype) {
   
      return spec.getBlockTypes().indexOf(blocktype);
  }
 
  public static int getBRAMContentFrameAddress(XilinxConfigurationSpecification spec) {
    int blockTypeNum = getBlockTypeNumber(spec, spec.getBRAMContentBlockType());
    return createBlockStartingFAR(spec,blockTypeNum);
  }

  public static int getNumberOfBRAMContentFrames(XilinxConfigurationSpecification spec) {
    int blockTypeNum = getBlockTypeNumber(spec, spec.getBRAMContentBlockType())
    return getFramesPerFARBlockType(spec, blockTypeNum);
  }
 
  public static String toString(XilinxConfigurationSpecification spec, int address) {
    FrameAddressRegister far = new FrameAddressRegister(spec,address);
    return far.toString();
  }
 
  /**
   * Return the 'consecutive' address from a FAR address. This is usually
   * used for accessing frame data from the sequential frame data array.
   */
  public static int getConsecutiveAddress(XilinxConfigurationSpecification spec, int address) {
    FrameAddressRegister far = new FrameAddressRegister(spec,address);
    return far.getConsecutiveAddress();   
   
  }
 
  ////////////////////////////////
  // Class Fields
  ////////////////////////////////
 

 
  /**
   * The configuration specification object that this class needs to know
   * how to incrememnt and manipulate the FAR.
   */
  protected XilinxConfigurationSpecification configSpec;

  /**
   * Determines if we are accessing the top or bottom partition of the FPGA.
   *
   * 0 = top
   * 1 = bottom
   */
  protected int top_bottom;
 
  /**
   * Represents bits 21:19 (V4) or 23:21 (V5) of the Frame Address Register (FAR).
   * Determines the type of block currently addressed.
   *   Virtex-4 Block types are:
   *   Logic blocks, CLB/IO/CLK/DSP/MGT: 000
   *   Block RAM interconnect blocks: 001
   *   Block RAM content blocks: 010
   *   CFG_CLB blocks: 011
   *   CFG_BRAM blocks: 100
   *   A normal V4 bitstream does not include CFG_CLB or CFG_BRAM
   *   Virtex-5 Block types are:
   *   Logic blocks and interconnect, CLB/IO/CLK/DSP/BRAM interconnect: 000
   *   Block RAM content blocks: 001
   *   Interconnect and Block Special Frames (used in partial reconfiguration): 010
   *   Block RAM Non-Configuration Frames (not accessible by users): 011
   */
  protected int blockType;
 
  /**
   * Represents bits 18:14 (V4) or 19:15 (V5) of the Frame Address Register (FAR).
   * Determines the row currently being addressed.
   */
  protected int row;
 
  /**
   * Represents bits 13:6 (V4) or 14:7 (V5) of the Frame Address Register (FAR).
   * Determines the column currently being addressed.
   */
  protected int column;
 
  /**
   * Represents bits 5:0 (V4) or 6:0 (V5) of the Frame Address Register (FAR).
   * Determines the frame within the block currently being addressed.
   */
  protected int minor;
 
}
TOP

Related Classes of edu.byu.ece.rapidSmith.bitstreamTools.configuration.FrameAddressRegister

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.