package mars.tools;
import mars.*;
import mars.util.*;
import mars.assembler.*;
import mars.mips.instructions.*;
import mars.mips.hardware.*;
import java.util.*;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.border.*;
import javax.swing.text.html.*;
/*
Copyright (c) 2003-2006, Pete Sanderson and Kenneth Vollmar
Developed by Pete Sanderson (psanderson@otterbein.edu)
and Kenneth Vollmar (kenvollmar@missouristate.edu)
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject
to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
(MIT license, http://www.opensource.org/licenses/mit-license.html)
*/
/**
* Tool to help students learn about IEEE 754 representation of 32 bit
* floating point values. This representation is used by MIPS "float"
* directive and instructions and also the Java (and most other languages)
* "float" data type. As written, it can ALMOST be adapted to 64 bit by
* changing a few constants.
*/
public class FloatRepresentation extends AbstractMarsToolAndApplication {
private static String version = "Version 1.1";
private static String heading = "32-bit IEEE 754 Floating Point Representation";
private static final String title = "Floating Point Representation, ";
private static final String defaultHex = "00000000";
private static final String defaultDecimal = "0.0";
private static final String defaultBinarySign = "0";
private static final String defaultBinaryExponent = "00000000";
private static final String defaultBinaryFraction = "00000000000000000000000";
private static final int maxLengthHex = 8;
private static final int maxLengthBinarySign = 1;
private static final int maxLengthBinaryExponent = 8;
private static final int maxLengthBinaryFraction = 23;
private static final int maxLengthBinaryTotal = maxLengthBinarySign+maxLengthBinaryExponent+maxLengthBinaryFraction;
private static final int maxLengthDecimal = 20;
private static final String denormalizedLabel = " significand (denormalized - no 'hidden bit')";
private static final String normalizedLabel = " significand ('hidden bit' underlined) ";
private static final Font instructionsFont = new Font("Arial",Font.PLAIN,14);
private static final Font hexDisplayFont = new Font("Courier",Font.PLAIN,32);
private static final Font binaryDisplayFont = new Font("Courier",Font.PLAIN,18);
private static final Font decimalDisplayFont = new Font("Courier",Font.PLAIN,18);
private static final Color hexDisplayColor = Color.red;
private static final Color binaryDisplayColor = Color.black;
private static final Color decimalDisplayColor = Color.blue;
private static final String expansionFontTag = "";
private static final String instructionFontTag = "";
private static final int exponentBias = 127; // 32 bit floating point exponent bias
private Register attachedRegister = null;
private Register[] fpRegisters;
private FloatRepresentation thisFloatTool;
// Panels to hold binary displays and decorations (labels, arrows)
private JPanel binarySignDecoratedDisplay,
binaryExponentDecoratedDisplay, binaryFractionDecoratedDisplay;
// Editable fields for the hex, binary and decimal representations.
private JTextField hexDisplay, decimalDisplay,
binarySignDisplay, binaryExponentDisplay, binaryFractionDisplay;
// Non-editable fields to display formula translating binary to decimal.
private JLabel expansionDisplay;
private JLabel significandLabel = new JLabel(denormalizedLabel, JLabel.CENTER);
private BinaryToDecimalFormulaGraphic binaryToDecimalFormulaGraphic;
// Non-editable field to display instructions
private InstructionsPane instructions;
private String defaultInstructions = "Modify any value then press the Enter key to update all values.";
/**
* Simple constructor, likely used to run a stand-alone memory reference visualizer.
* @param title String containing title for title bar
* @param heading String containing text for heading shown in upper part of window.
*/
public FloatRepresentation(String title, String heading) {
super(title,heading);
thisFloatTool = this;
}
/**
* Simple constructor, likely used by the MARS Tools menu mechanism
*/
public FloatRepresentation() {
this(title+version, heading);
}
/**
* Main provided for pure stand-alone use. Recommended stand-alone use is to write a
* driver program that instantiates a FloatRepresentation object then invokes its go() method.
* "stand-alone" means it is not invoked from the MARS Tools menu. "Pure" means there
* is no driver program to invoke the application.
*/
public static void main(String[] args) {
new FloatRepresentation(title+version,heading).go();
}
/**
* Fetch tool name (for display in MARS Tools menu)
* @return String containing tool name
*/
public String getName() {
return "Floating Point Representation";
}
/**
* Override the inherited method, which registers us as an Observer over the static data segment
* (starting address 0x10010000) only. This version will register us as observer over the selected
* floating point register, if any. If no register is selected, it will not do anything.
* If you use the inherited GUI buttons, this method is invoked when you click "Connect" button
* on MarsTool or the "Assemble and Run" button on a Mars-based app.
*/
protected void addAsObserver() {
addAsObserver(attachedRegister);
}
/**
* Delete this app/tool as an Observer of the attached register. This overrides
* the inherited version which deletes only as an Observer of memory.
* This method is called when the default "Disconnect" button on a MarsTool is selected or
* when the MIPS program execution triggered by the default "Assemble and run" on a stand-alone
* Mars app terminates (e.g. when the button is re-enabled).
*/
protected void deleteAsObserver() {
deleteAsObserver(attachedRegister);
}
/**
* Method that constructs the main display area. This will be vertically sandwiched between
* the standard heading area at the top and the control area at the bottom.
* @return the GUI component containing the application/tool-specific part of the user interface
*/
protected JComponent buildMainDisplayArea() {
return buildDisplayArea();
}
/**
* Override inherited update() to update display when "attached" register is modified
* either by MIPS program or by user editing it on the MARS user interface.
* The latter is the reason for overriding the inherited update() method.
* The inherited method will filter out notices triggered by the MARS GUI or the user.
* @param register the attached register
* @param accessNotice information provided by register in RegisterAccessNotice object
*/
public void update(Observable register, Object accessNotice) {
if (((AccessNotice)accessNotice).getAccessType()==AccessNotice.WRITE) {
updateDisplays(new FlavorsOfFloat().buildOneFromInt(attachedRegister.getValue()));
}
}
/**
* Method to reset display values to 0 when the Reset button selected.
* If attached to a MIPS register at the time, the register will be reset as well.
* Overrides inherited method that does nothing.
*/
protected void reset() {
instructions.setText(defaultInstructions);
updateDisplaysAndRegister(new FlavorsOfFloat());
}
//////////////////////////////////////////////////////////////////////////////////////
// Private methods defined to support the above.
protected JComponent buildDisplayArea() {
// Panel to hold all floating point dislay and editing components
Box mainPanel = Box.createVerticalBox();
JPanel leftPanel = new JPanel(new GridLayout(5,1,0,0));
JPanel rightPanel = new JPanel(new GridLayout(5,1,0,0));
Box subMainPanel = Box.createHorizontalBox();
subMainPanel.add(leftPanel);
subMainPanel.add(rightPanel);
mainPanel.add(subMainPanel);
// Editable display for hexadecimal version of the float value
hexDisplay = new JTextField(defaultHex, maxLengthHex+1);
hexDisplay.setFont(hexDisplayFont);
hexDisplay.setForeground(hexDisplayColor);
hexDisplay.setHorizontalAlignment(JTextField.RIGHT);
hexDisplay.setToolTipText(""+maxLengthHex+"-digit hexadecimal (base 16) display");
hexDisplay.setEditable(true);
hexDisplay.revalidate();
hexDisplay.addKeyListener(new HexDisplayKeystrokeListener(8));
JPanel hexPanel = new JPanel();
hexPanel.add(hexDisplay);
//################ Grid Row : Hexadecimal ##################################
leftPanel.add(hexPanel);
HexToBinaryGraphicPanel hexToBinaryGraphic = new HexToBinaryGraphicPanel();
//################ Grid Row : Hex-to-binary graphic ########################
leftPanel.add(hexToBinaryGraphic);
// Editable display for binary version of float value.
// It is split into 3 separately editable components (sign,exponent,fraction)
binarySignDisplay = new JTextField(defaultBinarySign, maxLengthBinarySign+1);
binarySignDisplay.setFont(binaryDisplayFont);
binarySignDisplay.setForeground(binaryDisplayColor);
binarySignDisplay.setHorizontalAlignment(JTextField.RIGHT);
binarySignDisplay.setToolTipText("The sign bit");
binarySignDisplay.setEditable(true);
binarySignDisplay.revalidate();
binaryExponentDisplay = new JTextField(defaultBinaryExponent, maxLengthBinaryExponent+1);
binaryExponentDisplay.setFont(binaryDisplayFont);
binaryExponentDisplay.setForeground(binaryDisplayColor);
binaryExponentDisplay.setHorizontalAlignment(JTextField.RIGHT);
binaryExponentDisplay.setToolTipText(""+maxLengthBinaryExponent+"-bit exponent");
binaryExponentDisplay.setEditable(true);
binaryExponentDisplay.revalidate();
binaryFractionDisplay = new BinaryFractionDisplayTextField(defaultBinaryFraction, maxLengthBinaryFraction+1);
binaryFractionDisplay.setFont(binaryDisplayFont);
binaryFractionDisplay.setForeground(binaryDisplayColor);
binaryFractionDisplay.setHorizontalAlignment(JTextField.RIGHT);
binaryFractionDisplay.setToolTipText(""+maxLengthBinaryFraction+"-bit fraction");
binaryFractionDisplay.setEditable(true);
binaryFractionDisplay.revalidate();
binarySignDisplay.addKeyListener(new BinaryDisplayKeystrokeListener(maxLengthBinarySign));
binaryExponentDisplay.addKeyListener(new BinaryDisplayKeystrokeListener(maxLengthBinaryExponent));
binaryFractionDisplay.addKeyListener(new BinaryDisplayKeystrokeListener(maxLengthBinaryFraction));
JPanel binaryPanel = new JPanel();
binarySignDecoratedDisplay = new JPanel(new BorderLayout());
binaryExponentDecoratedDisplay = new JPanel(new BorderLayout());
binaryFractionDecoratedDisplay = new JPanel(new BorderLayout());
binarySignDecoratedDisplay.add(binarySignDisplay,BorderLayout.CENTER);
binarySignDecoratedDisplay.add(new JLabel("sign",JLabel.CENTER),BorderLayout.SOUTH);
binaryExponentDecoratedDisplay.add(binaryExponentDisplay,BorderLayout.CENTER);
binaryExponentDecoratedDisplay.add(new JLabel("exponent",JLabel.CENTER),BorderLayout.SOUTH);
binaryFractionDecoratedDisplay.add(binaryFractionDisplay,BorderLayout.CENTER);
binaryFractionDecoratedDisplay.add(new JLabel("fraction",JLabel.CENTER),BorderLayout.SOUTH);
binaryPanel.add(binarySignDecoratedDisplay);
binaryPanel.add(binaryExponentDecoratedDisplay);
binaryPanel.add(binaryFractionDecoratedDisplay);
//################ Grid Row : Binary ##################################
leftPanel.add(binaryPanel);
//################ Grid Row : Binary to decimal formula arrows ##########
binaryToDecimalFormulaGraphic = new BinaryToDecimalFormulaGraphic();
binaryToDecimalFormulaGraphic.setBackground(leftPanel.getBackground());
leftPanel.add(binaryToDecimalFormulaGraphic);
// Non-Editable display for expansion of binary representation
expansionDisplay = new JLabel(new FlavorsOfFloat().expansionString);
expansionDisplay.setFont(new Font("Monospaced",Font.PLAIN,12));
expansionDisplay.setFocusable(false); // causes it to be skipped in "tab sequence".
expansionDisplay.setBackground(leftPanel.getBackground());
JPanel expansionDisplayBox = new JPanel(new GridLayout(2,1));
expansionDisplayBox.add(expansionDisplay);
expansionDisplayBox.add(significandLabel); // initialized at top
//################ Grid Row : Formula mapping binary to decimal ########
leftPanel.add(expansionDisplayBox);
// Editable display for decimal version of float value.
decimalDisplay = new JTextField(defaultDecimal, maxLengthDecimal+1);
decimalDisplay.setFont(decimalDisplayFont);
decimalDisplay.setForeground(decimalDisplayColor);
decimalDisplay.setHorizontalAlignment(JTextField.RIGHT);
decimalDisplay.setToolTipText("Decimal floating point value");
decimalDisplay.setMargin(new Insets(0,0,0,0));
decimalDisplay.setEditable(true);
decimalDisplay.revalidate();
decimalDisplay.addKeyListener(new DecimalDisplayKeystokeListenter());
Box decimalDisplayBox = Box.createVerticalBox();
decimalDisplayBox.add(Box.createVerticalStrut(5));
decimalDisplayBox.add(decimalDisplay);
decimalDisplayBox.add(Box.createVerticalStrut(15));
FlowLayout rightPanelLayout = new FlowLayout(FlowLayout.LEFT);
JPanel place1 = new JPanel(rightPanelLayout);
JPanel place2 = new JPanel(rightPanelLayout);
JPanel place3 = new JPanel(rightPanelLayout);
JPanel place4 = new JPanel(rightPanelLayout);
JEditorPane hexExplain = new JEditorPane("text/html",expansionFontTag+"< Hexadecimal representation"+"");
hexExplain.setEditable(false);
hexExplain.setFocusable(false);
hexExplain.setForeground(Color.black);
hexExplain.setBackground(place1.getBackground());
JEditorPane hexToBinExplain = new JEditorPane("text/html",expansionFontTag+"< Each hex digit represents 4 bits"+"");
hexToBinExplain.setEditable(false);
hexToBinExplain.setFocusable(false);
hexToBinExplain.setBackground(place2.getBackground());
JEditorPane binExplain = new JEditorPane("text/html",expansionFontTag+"< Binary representation"+"");
binExplain.setEditable(false);
binExplain.setFocusable(false);
binExplain.setBackground(place3.getBackground());
JEditorPane binToDecExplain = new JEditorPane("text/html",expansionFontTag+"< Binary-to-decimal conversion"+"");
binToDecExplain.setEditable(false);
binToDecExplain.setFocusable(false);
binToDecExplain.setBackground(place4.getBackground());
place1.add(hexExplain);
place2.add(hexToBinExplain);
place3.add(binExplain);
place4.add(binToDecExplain);
//################ 4 Grid Rows : Explanations #########################
rightPanel.add(place1);
rightPanel.add(place2);
rightPanel.add(place3);
rightPanel.add(place4);
//################ Grid Row : Decimal ##################################
rightPanel.add(decimalDisplayBox);
//######## mainPanel is vertical box, instructions get a row #################
JPanel instructionsPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
instructions = new InstructionsPane(instructionsPanel);
instructionsPanel.add(instructions);
instructionsPanel.setBorder(new TitledBorder("Instructions"));
mainPanel.add(instructionsPanel);
// Means of selecting and deselecting an attached floating point register
fpRegisters = Coprocessor1.getRegisters();
String[] registerList = new String[fpRegisters.length+1];
registerList[0] = "None";
for (int i=0; i"+expansionFontTag
+ "-1"+binaryString.substring(0,maxLengthBinarySign)+" * 2"
+ stringExponent + HTMLspaces.substring(0, (5-stringExponent.length())*6)
+ " * "
+ ((biasedExponent==0) ? " ." : "1.")
+ binaryString.substring(maxLengthBinarySign+maxLengthBinaryExponent, maxLengthBinaryTotal)
+ " =