URL
https://opencores.org/ocsvn/fpga-cf/fpga-cf/trunk
Subversion Repositories fpga-cf
[/] [fpga-cf/] [trunk/] [java/] [src/] [edu/] [byu/] [cc/] [plieber/] [fpgaenet/] [debug/] [llparse/] [LL_Virtex5.jj] - Rev 2
Compare with Previous | Blame | View Log
options {
STATIC = false;
}
PARSER_BEGIN(LL_Virtex5)
/*
@LICENSE@
*/
package edu.byu.cc.plieber.fpgaenet.debug.llparse;
import java.lang.*;
import java.util.*;
/**
* The Xilinx Logical Allocation file (.ll file) parser for Virtex2
* FPGAs. The parser fills two <code>Hashtable</code> objects with the
* readback bitstream information for state elements in the Virtex5
* design. One <code>Hashtable</code> is filled with RAM bitstream
* information keyed on physical location (block name) while the
* second holds the bitstream information for flip-flops keyed on
* physical location (block name). The grammar is not published but
* was developed from looking at the file format.
*
* @author Paul Graham
* @author Peter Lieber */
public class LL_Virtex5 {
/**
* A <code>HashTable</code> to allow quick access to {@link
* RAMGroup} objects based on block name and RAM type. The
* <code>RAMGroup</code> objects contain {@link RAMRBEntry} objects
* which hold the actual bitstream offsets. */
Hashtable<String, RAMGroup > RAMGroupHash;
/**
* A <code>Hashtable</code> of {@link LatchRBEntry} objects to allow
* quick access based on block name and latch type. The
* <code>LatchRBEntry</code> is used for flip-flops and stores
* bitstream offset information. */
Hashtable<String, LatchRBEntry > NetHashBlock;
/** The number of nets associated with latches in the .ll file */
int netCount;
/** The number of RAM entries in the .ll file */
int ramCount;
/**
* Indicates whether the LL file provides absolute offsets. First
* needed with the Xilinx 4.1 ISE tools*/
boolean absOffsets;
/**
* Instances and initializes the parser and parses the input from
* <code>System.in</code>
*
* @param args Command line arguments (ignored by the method)
* */
public static void main(String args[]) throws ParseException {
LL_Virtex5 parser = new LL_Virtex5(System.in);
parser.initTables();
parser.parseLL();
}
/**
* Initializes the <code>Hashtables</code> and counts. */
public void initTables() {
RAMGroupHash = new Hashtable<String, RAMGroup >();
NetHashBlock = new Hashtable<String, LatchRBEntry >();
netCount = 0;
ramCount = 0;
absOffsets = false;
}
/**
* Returns a reference to the <code>RAMGroupHash</code>, which holds
* a {@link RAMGroup} object for each RAM in the .ll file keyed on
* the location of the RAM and the RAM type (F, G, M, or B).
*
* @return Reference to <code>RAMGroupHash</code> */
public Hashtable<String, RAMGroup > getRAMGroupHash() {
return RAMGroupHash;
}
/**
* Returning a reference to the <code>NetHashBlock</code>, which
* holds a {@link LatchRBEntry} for each flip-flop in the .ll file
* keyed on the location and the latch type (XQ, YQ, etc.)
*
* @return Reference to <code>NetHashBlock</code> */
public Hashtable<String, LatchRBEntry > getNetHashBlock() {
return NetHashBlock;
}
/**
* Returns true if the LL file provides absolute offsets and false
* otherwise. Absolute readback bitstream offsets started appearing
* in the Xilinx ISE 4.1i series of tools.
*
* @return <code>true</code> if absolute offsets are provide,
* <code>false</code> otherwise. */
public boolean hasAbsoluteOffsets() {
return absOffsets;
}
}
PARSER_END(LL_Virtex5)
SKIP :
{
" "
|
"\t"
|
";" : IN_LINE_COMMENT
}
<IN_LINE_COMMENT> SKIP:
{
"\n" : DEFAULT
}
<IN_LINE_COMMENT> MORE:
{
< ~[] >
}
TOKEN :
{
< NUM: ( ["0"-"9"] )+ >
|
< HEXNUM: "0x" ( ["0"-"9","a"-"f","A"-"F"] )+ >
|
< EQUAL: "=" >
|
< TYPE : "Type" >
|
< LUT : ["A","B","C","D"] >
|
< BLOCKRAM : "B" >
|
< SLICEBLOCK : "SLICE_X" (["0"-"9"])+ "Y" (["0"-"9"])+ >
|
< BRAMBLOCK : "RAMB36_X" (["0"-"9"])+ "Y" (["0"-"9"])+ >
|
< GTPBLOCK : "GTP_DUAL_X" (["0"-"9"])+ "Y" (["0"-"9"])+ >
|
< DCMBLOCK : "DCM_ADV_X" (["0"-"9"])+ "Y" (["0"-"9"])+ >
|
< PINBLOCK : ["A"-"Z"] (["A"-"Z"])? ["0"-"9"] (["0"-"9"])? >
|
< AQ : "AQ">
|
< BQ : "BQ">
|
< CQ : "CQ">
|
< DQ : "DQ">
|
< Q1 : "Q1">
|
< Q2 : "Q2">
|
< I : "I">
|
< O : "O">
|
< DO : "DO" ["A","B"] ["0"-"9"] (["0"-"9"])? >
|
< COLON : ":" >
|
< LANGLE: "<" >
|
< RANGLE: ">" >
|
< LBRACKET: "[" >
|
< RBRACKET: "]" >
|
< REVISION : "Revision">
|
< BIT : "Bit" >
|
< BLOCK : "Block" >
|
< LATCH : "Latch" >
|
< RAM : "Ram" >
|
< ROM : "Rom" >
|
< NET: "Net" >
|
< YES: "YES">
|
< NO: "NO">
|
< COMPARE: "COMPARE">
|
< INFO: "Info">
|
< ID: ["a"-"z","A"-"Z"] (["a"-"z","A"-"Z","_","/","0"-"9","-",".","$"])* >
|
< NETEXT: ["/","_"](["a"-"z","A"-"Z","_","/","0"-"9","-","."])+ >
}
/**
* Defines the various flip-flop types and returns the type as
* a <code>String</code>.
*
* @return <code>String</code> for flip-flop type. */
String LatchType() :
{ }
{
<AQ> { return token.toString();}
|<BQ> { return token.toString();}
|<CQ> { return token.toString();}
|<DQ> { return token.toString();}
|<Q1> { return token.toString();}
|<Q2> { return token.toString();}
|<I> { return token.toString();}
|<O> { return token.toString();}
}
/**
* Initiates the parsing of an <code>.ll</code> file and prints out
* statistics about the number of flip-flops (latches) and RAMs it
* found.*/
void parseLL() :
{ }
{
Revision() ( BitStreamEntry() | InfoEntry() )* <EOF>
{
System.out.println("Total Block/Latch Entries: "+
Integer.toString(NetHashBlock.size())+ " Total Nets:" +
Integer.toString(netCount));
System.out.println("Number of RAMGroup Entries: "+
Integer.toString(RAMGroupHash.size())+
" Total RAM entries:" + Integer.toString(ramCount));
System.out.flush();
}
}
/**
* Parses the revision information for the .ll file.
*/
void Revision() :
{ }
{
<REVISION> <NUM> ("\r" | "\n" | "\r\n")
}
/**
* Parses the entire clause having the type of the flip-flop and
* returns the flip-flop type as a String.
*
* @return Flip-flop type as <code>String</code>. */
String Latch() :
{ String latchtype; }
{
<LATCH> <EQUAL> latchtype=LatchType() {return latchtype;}
}
/**
* Parses the net names associated with latches and stores a
* <code>LatchRBEntry</code> object in the <code>NetHashBlock
* Hashtable</code>. The method handles both angle brackets ("<>")
* and square brackets ("[]") for net names. In some strange
* circumstances, it was necessary to handle names which extended
* beyond the array naming construct (in other words, there was still
* part of the name after the last "]" or ">"). In these cases, the
* names are considered atomic (not multi-bit), so the index variable
* is reset to "-1".
*
* @param offset The first offset provided by the LL file for this
* flip-flop; it is actually a junk bit in the readback
* bitstream.
*
* @param frame The frame number for this flip-flops readback data
* provided by the LL file.
*
* @param frameOffset The offset within the frame for this flip-flop's
* readback data provided by the LL file.
*
* @param block The block's name and location.
*
* @param latchType The type of the flip-flop.
**/
void NetName(int offset, int frame, int frameOffset, String block, String latchType) :
{
String netname;
int index=-1;
boolean extended=false;
LatchRBEntry lrbe;
}
{
<ID> { netname = token.toString();}
[(<LANGLE>
<NUM> { index = Integer.parseInt(token.toString()); }
<RANGLE>
[<NETEXT>
{ netname = new String(netname+"<"+Integer.toString(index)+">"+token.toString());
index = -1;
extended = true;
} ]
| <LBRACKET>
<NUM> { index = Integer.parseInt(token.toString());}
<RBRACKET>
[<NETEXT>
{ netname = new String(netname+"["+Integer.toString(index)+"]"+token.toString());
index = -1;
extended = true;
} ]
)]
{
if(!block.equals("DUMMY")) {
lrbe = new LatchRBEntry(offset,frame,frameOffset,block,latchType,netname,index);
netCount++;
NetHashBlock.put(block+latchType, lrbe);
}
}
}
/**
* Parses the entire "Net=..." clause.
*
* @param offset The first offset provided by the LL file for this
* flip-flop; it is actually a junk bit in the readback
* bitstream.
*
* @param frame The frame number for this flip-flops readback data
* provided by the LL file.
*
* @param frameOffset The offset within the frame for this flip-flop's
* readback data provided by the LL file.
*
* @param block The block's name and location.
*
* @param latchType The type of the flip-flop.
*/
void Net(int offset, int frame, int frameOffset, String block, String latchType) :
{ }
{
<NET> <EQUAL> NetName(offset,frame,frameOffset,block,latchType)
}
/**
* Parses the "Ram=..." clauses of the RAM LL entries for lut rams and enters the
* data into the <code>RAMGroupHash</code>. Since a certain RAM may
* already have a <code>RAMGroup</code> entry in the
* <code>RAMGroupHash</code>, the method performs a lookup first to
* see if the RAM's <code>RAMGroup</code> entry exists. If the entry
* exists, the method adds a <code>RAMRBEntry</code> to the
* <code>RAMGroup</code> which was found. Otherwise, the method
* creates a new <code>RAMGroup</code> and adds an
* <code>RAMRBEntry</code> to it. This method handles both LUT RAMs
* and BlockRAMs.
*
* @param offset The first offset provided by the LL file for this
* flip-flop; it is actually a junk bit in the readback
* bitstream.
*
* @param frame The frame number for this flip-flops readback data
* provided by the LL file.
*
* @param frameOffset The offset within the frame for this flip-flop's
* readback data provided by the LL file.
*
* @param block The block's name and location. */
void SliceRam(int offset, int frame, int frameOffset, String block) :
{ String lutType;
int address;
RAMGroup rg;
RAMRBEntry rrb;
String key;
}
{
<RAM> <EQUAL>
<LUT> {lutType = token.toString();}
<COLON> <NUM>
{
try {
address = Integer.parseInt(token.toString());
rrb = new RAMRBEntry(offset,frame,frameOffset,block,lutType,address);
ramCount++;
key = new String(block+"."+lutType);
rg = (RAMGroup)RAMGroupHash.get(key);
if(rg == null) {
RAMGroupHash.put(key,new RAMGroup(rrb));
}
else {
rg.addRAMEntry(rrb);
}
}
catch (RAMTypeException rte) {
System.out.println("Caught Exception: " + rte.toString());
System.out.println("Wrong RAM Type: Are you using the proper part type? (Virtex5)");
rte.printStackTrace();
}
}
}
/**
* Parses the "Ram=..." clauses of the RAM LL entries for BRAMs and enters the
* data into the <code>RAMGroupHash</code>. Since a certain RAM may
* already have a <code>RAMGroup</code> entry in the
* <code>RAMGroupHash</code>, the method performs a lookup first to
* see if the RAM's <code>RAMGroup</code> entry exists. If the entry
* exists, the method adds a <code>RAMRBEntry</code> to the
* <code>RAMGroup</code> which was found. Otherwise, the method
* creates a new <code>RAMGroup</code> and adds an
* <code>RAMRBEntry</code> to it. This method handles both LUT RAMs
* and BlockRAMs.
*
* @param offset The first offset provided by the LL file for this
* flip-flop; it is actually a junk bit in the readback
* bitstream.
*
* @param frame The frame number for this flip-flops readback data
* provided by the LL file.
*
* @param frameOffset The offset within the frame for this flip-flop's
* readback data provided by the LL file.
*
* @param block The block's name and location. */
void BRam(int offset, int frame, int frameOffset, String block) :
{ String lutType;
int address;
RAMGroup rg;
RAMRBEntry rrb;
String key;
}
{
<RAM> <EQUAL>
<LUT> {lutType = token.toString();}
<COLON> <ID>
{
try {
String bitAddress = token.toString();
// We need to skip the PARBIT prefix used for block ram parity bits
if( bitAddress.charAt(0) == 'P' )
address = Integer.parseInt(bitAddress.substring(6));
// We need to skip the BIT prefix used for block ram data bits
else
address = Integer.parseInt(bitAddress.substring(3));
rrb = new RAMRBEntry(offset,frame,frameOffset,block,lutType,address);
ramCount++;
key = new String(block+"."+lutType);
rg = (RAMGroup)RAMGroupHash.get(key);
if(rg == null) {
RAMGroupHash.put(key,new RAMGroup(rrb));
}
else {
rg.addRAMEntry(rrb);
}
}
catch (RAMTypeException rte) {
System.out.println("Caught Exception: " + rte.toString());
System.out.println("Wrong RAM Type: Are you using the proper part type? (Virtex2, XC4K, etc.)");
rte.printStackTrace();
}
}
}
/**
* Parses "Rom=..." entries, but doesn't do anything with them.
*/
void Rom() :
{ }
{
<ROM> <EQUAL> <LUT> <COLON> <NUM>
}
/**
* Parses "YES/NO" clauses.
*/
void YesNo():
{ }
{
<YES>
|
<NO>
}
/**
* Parses "COMPARE=..." clauses, which are otherwise ignored.
*/
void Compare() :
{ }
{
<COMPARE> <EQUAL> YesNo()
}
/**
* Parses the "attributes" of a state bit in the readback bitstream,
* which define whether it belongs to a flip-flop, a RAM, or a ROM and
* other related information. This is really the core of the parsing work.
*
* @param offset The first offset provided by the LL file for this
* flip-flop; it is actually a junk bit in the readback
* bitstream.
*
* @param frame The frame number for this flip-flops readback data
* provided by the LL file.
*
* @param frameOffset The offset within the frame for this flip-flop's
* readback data provided by the LL file.
*
* @param block The block's name and location. */
void SliceAttributes(int offset, int frame, int frameOffset, String block) :
{ String latchType;}
{
latchType=Latch() (Net(offset, frame, frameOffset, block, latchType))? (Compare())?
|
SliceRam(offset,frame,frameOffset,block) (Compare())?
|
Rom() (Compare())?
}
/**
* Parses the "attributes" of a state bit in the readback bitstream,
* which define whether it belongs to a flip-flop, a RAM, or a ROM and
* other related information. This is really the core of the parsing work.
*
* @param offset The first offset provided by the LL file for this
* flip-flop; it is actually a junk bit in the readback
* bitstream.
*
* @param frame The frame number for this flip-flops readback data
* provided by the LL file.
*
* @param frameOffset The offset within the frame for this flip-flop's
* readback data provided by the LL file.
*
* @param block The block's name and location. */
void PinAttributes(int offset, int frame, int frameOffset, String block) :
{ String latchType;}
{
latchType=Latch() (Net(offset, frame, frameOffset, block, latchType))? (Compare())?
}
/**
* Parses the "attributes" of a state bit in the readback bitstream,
* which define whether it belongs to a flip-flop, a RAM, or a ROM and
* other related information. This is really the core of the parsing work.
*
* @param offset The first offset provided by the LL file for this
* flip-flop; it is actually a junk bit in the readback
* bitstream.
*
* @param frame The frame number for this flip-flops readback data
* provided by the LL file.
*
* @param frameOffset The offset within the frame for this flip-flop's
* readback data provided by the LL file.
*
* @param block The block's name and location. */
void BramAttributes(int offset, int frame, int frameOffset, String block) :
{ }
{
BRam(offset,frame,frameOffset,block) (Compare())?
}
/**
* Parses the information regarding location of the IOB/SLICE/BLOCKRAM
* and returns the information as a <code>String</code>.
*
* @return The Virtex2 block location string (for example, "A21",
* "CLB_R8C55", "RAMB4_R7C0").
**/
String Block(int offset, int frame, int frameOffset) :
{
String block;
}
{
<BLOCK> <EQUAL>
(
<SLICEBLOCK>
{block = token.toString();}
SliceAttributes(offset,frame,frameOffset,block) ("\r" | "\n" | "\r\n")
|
<BRAMBLOCK>
{block = token.toString();}
BramAttributes(offset,frame,frameOffset,block) ("\r" | "\n" | "\r\n")
|
( <GTPBLOCK> | <DCMBLOCK> )
{block = token.toString();}
<TYPE> <EQUAL> < ID > ("\r" | "\n" | "\r\n")
|
<PINBLOCK>
{block = token.toString();}
PinAttributes(offset,frame,frameOffset,block) ("\r" | "\n" | "\r\n")
) { return block;
}
}
/**
* Parses an entire readback bitstream location entry for a state
* element. */
void BitStreamEntry() :
{ int offset,frame,frameOffset;
String block;
}
{
<BIT> <NUM> {offset = Integer.parseInt(token.toString());}
(<NUM> {frame = Integer.parseInt(token.toString()); }
|<HEXNUM> {frame = Integer.decode(token.toString()).intValue(); absOffsets=true;})
<NUM> {frameOffset = Integer.parseInt(token.toString()); }
block = Block(offset, frame, frameOffset)
}
/**
* Parses the value of any the informational entries in the LL
* file. The information is ignored. */
void InfoValue() :
{ }
{
<ID>
|
<NUM>
}
/**
* Parses any entries in the LL file which do not directly associate
* state elements with readback bitstream locations. These entries
* describe some of the bitstream generation options used for the
* bitstream. */
void InfoEntry() :
{}
{
<INFO> <ID> <EQUAL> InfoValue() ("\r" | "\n" | "\r\n")
}