0da1c5dcca
First commit of the 4.5 version (latest version available)
271 lines
7.7 KiB
Java
271 lines
7.7 KiB
Java
/*
|
|
Copyright (c) 2008, Felipe Lessa
|
|
|
|
Developed by Felipe Lessa (felipe.lessa@gmail.com)
|
|
|
|
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)
|
|
*/
|
|
package mars.tools;
|
|
|
|
import java.awt.GridBagConstraints;
|
|
import java.awt.GridBagLayout;
|
|
import java.awt.Insets;
|
|
import java.util.Observable;
|
|
|
|
import javax.swing.JComponent;
|
|
import javax.swing.JLabel;
|
|
import javax.swing.JPanel;
|
|
import javax.swing.JProgressBar;
|
|
import javax.swing.JTextField;
|
|
|
|
import mars.ProgramStatement;
|
|
import mars.mips.hardware.AccessNotice;
|
|
import mars.mips.hardware.AddressErrorException;
|
|
import mars.mips.hardware.Memory;
|
|
import mars.mips.hardware.MemoryAccessNotice;
|
|
import mars.mips.instructions.BasicInstruction;
|
|
import mars.mips.instructions.BasicInstructionFormat;
|
|
|
|
/**
|
|
*
|
|
* Instruction counter tool. Can be used to know how many instructions
|
|
* were executed to complete a given program.
|
|
*
|
|
* Code slightly based on MemoryReferenceVisualization.
|
|
*
|
|
* @author Felipe Lessa <felipe.lessa@gmail.com>
|
|
*
|
|
*/
|
|
//@SuppressWarnings("serial")
|
|
public class InstructionCounter extends AbstractMarsToolAndApplication {
|
|
private static String name = "Instruction Counter";
|
|
private static String version = "Version 1.0 (Felipe Lessa)";
|
|
private static String heading = "Counting the number of instructions executed";
|
|
|
|
/**
|
|
* Number of instructions executed until now.
|
|
*/
|
|
protected int counter = 0;
|
|
private JTextField counterField;
|
|
|
|
/**
|
|
* Number of instructions of type R.
|
|
*/
|
|
protected int counterR = 0;
|
|
private JTextField counterRField;
|
|
private JProgressBar progressbarR;
|
|
|
|
/**
|
|
* Number of instructions of type I.
|
|
*/
|
|
protected int counterI = 0;
|
|
private JTextField counterIField;
|
|
private JProgressBar progressbarI;
|
|
|
|
/**
|
|
* Number of instructions of type J.
|
|
*/
|
|
protected int counterJ = 0;
|
|
private JTextField counterJField;
|
|
private JProgressBar progressbarJ;
|
|
|
|
|
|
/**
|
|
* The last address we saw. We ignore it because the only way for a
|
|
* program to execute twice the same instruction is to enter an infinite
|
|
* loop, which is not insteresting in the POV of counting instructions.
|
|
*/
|
|
protected int lastAddress = -1;
|
|
|
|
/**
|
|
* 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 InstructionCounter(String title, String heading) {
|
|
super(title,heading);
|
|
}
|
|
|
|
/**
|
|
* Simple construction, likely used by the MARS Tools menu mechanism.
|
|
*/
|
|
public InstructionCounter() {
|
|
super(name + ", " + version, heading);
|
|
}
|
|
|
|
// @Override
|
|
public String getName() {
|
|
return name;
|
|
}
|
|
|
|
// @Override
|
|
protected JComponent buildMainDisplayArea() {
|
|
// Create everything
|
|
JPanel panel = new JPanel(new GridBagLayout());
|
|
|
|
counterField = new JTextField("0", 10);
|
|
counterField.setEditable(false);
|
|
|
|
counterRField = new JTextField("0", 10);
|
|
counterRField.setEditable(false);
|
|
progressbarR = new JProgressBar(JProgressBar.HORIZONTAL);
|
|
progressbarR.setStringPainted(true);
|
|
|
|
counterIField = new JTextField("0", 10);
|
|
counterIField.setEditable(false);
|
|
progressbarI = new JProgressBar(JProgressBar.HORIZONTAL);
|
|
progressbarI.setStringPainted(true);
|
|
|
|
counterJField = new JTextField("0", 10);
|
|
counterJField.setEditable(false);
|
|
progressbarJ = new JProgressBar(JProgressBar.HORIZONTAL);
|
|
progressbarJ.setStringPainted(true);
|
|
|
|
// Add them to the panel
|
|
|
|
// Fields
|
|
GridBagConstraints c = new GridBagConstraints();
|
|
c.anchor = GridBagConstraints.LINE_START;
|
|
c.gridheight = c.gridwidth = 1;
|
|
c.gridx = 3;
|
|
c.gridy = 1;
|
|
c.insets = new Insets(0, 0, 17, 0);
|
|
panel.add(counterField, c);
|
|
|
|
c.insets = new Insets(0, 0, 0, 0);
|
|
c.gridy++;
|
|
panel.add(counterRField, c);
|
|
|
|
c.gridy++;
|
|
panel.add(counterIField, c);
|
|
|
|
c.gridy++;
|
|
panel.add(counterJField, c);
|
|
|
|
// Labels
|
|
c.anchor = GridBagConstraints.LINE_END;
|
|
c.gridx = 1;
|
|
c.gridwidth = 2;
|
|
c.gridy = 1;
|
|
c.insets = new Insets(0, 0, 17, 0);
|
|
panel.add(new JLabel("Instructions so far: "), c);
|
|
|
|
c.insets = new Insets(0, 0, 0, 0);
|
|
c.gridx = 2;
|
|
c.gridwidth = 1;
|
|
c.gridy++;
|
|
panel.add(new JLabel("R-type: "), c);
|
|
|
|
c.gridy++;
|
|
panel.add(new JLabel("I-type: "), c);
|
|
|
|
c.gridy++;
|
|
panel.add(new JLabel("J-type: "), c);
|
|
|
|
// Progress bars
|
|
c.insets = new Insets(3, 3, 3, 3);
|
|
c.gridx = 4;
|
|
c.gridy = 2;
|
|
panel.add(progressbarR, c);
|
|
|
|
c.gridy++;
|
|
panel.add(progressbarI, c);
|
|
|
|
c.gridy++;
|
|
panel.add(progressbarJ, c);
|
|
|
|
return panel;
|
|
}
|
|
|
|
// @Override
|
|
protected void addAsObserver() {
|
|
addAsObserver(Memory.textBaseAddress, Memory.textLimitAddress);
|
|
}
|
|
|
|
// @Override
|
|
protected void processMIPSUpdate(Observable resource, AccessNotice notice) {
|
|
if (!notice.accessIsFromMIPS()) return;
|
|
if (notice.getAccessType() != AccessNotice.READ) return;
|
|
MemoryAccessNotice m = (MemoryAccessNotice) notice;
|
|
int a = m.getAddress();
|
|
if (a == lastAddress) return;
|
|
lastAddress = a;
|
|
counter++;
|
|
try {
|
|
ProgramStatement stmt = Memory.getInstance().getStatement(a);
|
|
BasicInstruction instr = (BasicInstruction) stmt.getInstruction();
|
|
BasicInstructionFormat format = instr.getInstructionFormat();
|
|
if (format == BasicInstructionFormat.R_FORMAT)
|
|
counterR++;
|
|
else if (format == BasicInstructionFormat.I_FORMAT
|
|
|| format == BasicInstructionFormat.I_BRANCH_FORMAT)
|
|
counterI++;
|
|
else if (format == BasicInstructionFormat.J_FORMAT)
|
|
counterJ++;
|
|
} catch (AddressErrorException e) {
|
|
// TODO Auto-generated catch block
|
|
e.printStackTrace();
|
|
}
|
|
updateDisplay();
|
|
}
|
|
|
|
// @Override
|
|
protected void initializePreGUI() {
|
|
counter = counterR = counterI = counterJ = 0;
|
|
lastAddress = -1;
|
|
}
|
|
|
|
// @Override
|
|
protected void reset() {
|
|
counter = counterR = counterI = counterJ = 0;
|
|
lastAddress = -1;
|
|
updateDisplay();
|
|
}
|
|
|
|
// @Override
|
|
protected void updateDisplay() {
|
|
counterField.setText(String.valueOf(counter));
|
|
|
|
counterRField.setText(String.valueOf(counterR));
|
|
progressbarR.setMaximum(counter);
|
|
progressbarR.setValue(counterR);
|
|
|
|
counterIField.setText(String.valueOf(counterI));
|
|
progressbarI.setMaximum(counter);
|
|
progressbarI.setValue(counterI);
|
|
|
|
counterJField.setText(String.valueOf(counterJ));
|
|
progressbarJ.setMaximum(counter);
|
|
progressbarJ.setValue(counterJ);
|
|
|
|
if (counter == 0) {
|
|
progressbarR.setString("0%");
|
|
progressbarI.setString("0%");
|
|
progressbarJ.setString("0%");
|
|
} else {
|
|
progressbarR.setString((counterR * 100)/counter + "%");
|
|
progressbarI.setString((counterI * 100)/counter + "%");
|
|
progressbarJ.setString((counterJ * 100)/counter + "%");
|
|
}
|
|
}
|
|
}
|