/******************************************************************************* * openDLX - A DLX/MIPS processor simulator. * Copyright (C) 2013 The openDLX project, University of Augsburg, Germany * Project URL: <https://sourceforge.net/projects/opendlx> * Development branch: <https://github.com/smetzlaff/openDLX> * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program 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. * * You should have received a copy of the GNU General Public License * along with this program, see <LICENSE>. If not, see * <http://www.gnu.org/licenses/>. ******************************************************************************/ package openDLX.gui.dialog; import java.awt.BorderLayout; import java.awt.Frame; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JDialog; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JTextField; import openDLX.BranchPredictionModule; import openDLX.datatypes.ArchCfg; import openDLX.datatypes.BranchPredictorState; import openDLX.datatypes.BranchPredictorType; import openDLX.gui.MainFrame; import openDLX.gui.Preference; @SuppressWarnings("serial") public class OptionDialog extends JDialog implements ActionListener { // two control buttons, press confirm to save selected options private JButton confirm; private JButton cancel; // checkBoxes private JCheckBox forwardingCheckBox; private JCheckBox mipsCompatibilityCheckBox; /* * JComboBox may be represented by Vectors or Arrays of Objects (Object []) * we have chosen "String[]" to be the representation (in fact - String) for * the data within AsmFileLoader-class , but Vector is appropriate as well. */ private JComboBox<String> bpTypeComboBox; private JComboBox<String> bpInitialStateComboBox; private JTextField btbSizeTextField; //input text fields private JTextField maxCyclesTextField; public OptionDialog(Frame owner) { //calls modal constructor, set to "false" to make dialog non-modal super(owner, true); setLayout(new BorderLayout()); setTitle("options"); //control buttons confirm = new JButton("OK"); confirm.addActionListener(this); cancel = new JButton("Cancel"); cancel.addActionListener(this); //the panel containing all the control buttons JPanel buttonPanel = new JPanel(); buttonPanel.add(confirm); buttonPanel.add(cancel); add(buttonPanel, BorderLayout.SOUTH); /*instantiate all the components that you'd like to use as input, * as well as any labels describing them, HERE: */ /*create a checkboxes * * checkboxes don't need a label -> the name is part of the constructor *-> its a single element, hence it doesn't need a JPanel */ forwardingCheckBox = new JCheckBox("Use Forwarding"); forwardingCheckBox.setSelected(Preference.pref.getBoolean(Preference.forwardingPreferenceKey, true)); // load current value mipsCompatibilityCheckBox = new JCheckBox("MIPS compatibility mode (requires forwarding)"); mipsCompatibilityCheckBox.setSelected(Preference.pref.getBoolean(Preference.mipsCompatibilityPreferenceKey, true)); // load current value // disable MIPS compatibility if no forwading is active if (!forwardingCheckBox.isSelected()) { mipsCompatibilityCheckBox.setSelected(false); } /*create a JComboBoxes * * JComboBox need a Object[] or Vector as data representation Furthermore the JComboBox gets a JLabel, describing it, * -> put both components into a JPanel*/ // bpType: JLabel bpTypeComboBoxDescriptionLabel = new JLabel("Branch Predictor: "); bpTypeComboBox = new JComboBox<String>(ArchCfg.possibleBpTypeComboBoxValues); bpTypeComboBox.setSelectedItem(BranchPredictionModule.getBranchPredictorTypeFromString( Preference.pref.get(Preference.bpTypePreferenceKey, BranchPredictorType.UNKNOWN.toString())).toGuiString()); // load current value //surrounding panel JPanel bpTypeListPanel = new JPanel(); //add the label bpTypeListPanel.add(bpTypeComboBoxDescriptionLabel); //add the box itself bpTypeListPanel.add(bpTypeComboBox); // bpInitialState: JLabel bpInitialStateComboBoxDescriptionLabel = new JLabel("Initial Predictor State: "); bpInitialStateComboBox = new JComboBox<String>(ArchCfg.possibleBpInitialStateComboBoxValues); bpInitialStateComboBox.setSelectedItem(BranchPredictionModule.getBranchPredictorInitialStateFromString( Preference.pref.get(Preference.bpInitialStatePreferenceKey, BranchPredictorState.UNKNOWN.toString())).toGuiString()); // load current value //surrounding panel JPanel bpInitialStateListPanel = new JPanel(); //add the label bpInitialStateListPanel.add(bpInitialStateComboBoxDescriptionLabel); //add the box itself bpInitialStateListPanel.add(bpInitialStateComboBox); /*create a JTextFields * the field and a JLabel description */ // Max Cycles JLabel maxCyclesTextFieldDescription = new JLabel("Maximum Cycles: "); // the number in constructor means the number of lines in textfield maxCyclesTextField = new JTextField(10); //load current text from ArchCfg maxCyclesTextField.setText((new Integer(ArchCfg.max_cycles)).toString()); //surrounding panel, containing both JLabel and JTextField JPanel maxCyclesTextFieldPanel = new JPanel(); //add the label maxCyclesTextFieldPanel.add(maxCyclesTextFieldDescription); //add the field itself maxCyclesTextFieldPanel.add(maxCyclesTextField); // BTB Size JLabel btbSizeTextFieldDescription = new JLabel("BTB Size: "); // the number in constructor means the number of lines in textfield btbSizeTextField = new JTextField(5); //load current text from ArchCfg btbSizeTextField.setText((new Integer(ArchCfg.branch_predictor_table_size)).toString()); //surrounding panel, containing both JLabel and JTextField JPanel btbSizeTextFieldPanel = new JPanel(); //add the label btbSizeTextFieldPanel.add(btbSizeTextFieldDescription); //add the field itself btbSizeTextFieldPanel.add(btbSizeTextField); //this panel contains all input components = top level panel JPanel optionPanel = new JPanel(); optionPanel.setLayout(new GridLayout(0, 1)); //dont forget adding the components to the panel !!! optionPanel.add(forwardingCheckBox); optionPanel.add(mipsCompatibilityCheckBox); optionPanel.add(bpTypeListPanel); optionPanel.add(bpInitialStateListPanel); optionPanel.add(btbSizeTextFieldPanel); optionPanel.add(maxCyclesTextFieldPanel); //adds the top-level-panel to the Dialog frame add(optionPanel, BorderLayout.CENTER); //dialog appears in the middle of the MainFrame setLocationRelativeTo(owner); pack(); setResizable(false); setVisible(true); } @Override public void actionPerformed(ActionEvent e) { //just close the dialog if (e.getSource().equals(cancel)) { setVisible(false); dispose(); } /* get all the values, assign them to data within ArchCfg * and save them as preference for future use */ if (e.getSource().equals(confirm)) { Preference.pref.putBoolean(Preference.forwardingPreferenceKey, forwardingCheckBox.isSelected()); Preference.pref.putBoolean(Preference.mipsCompatibilityPreferenceKey, mipsCompatibilityCheckBox.isSelected()); if (forwardingCheckBox.isSelected()) { ArchCfg.use_forwarding = true; if(mipsCompatibilityCheckBox.isSelected()) { ArchCfg.use_load_stall_bubble = true; } else { ArchCfg.use_load_stall_bubble = false; } } else { ArchCfg.use_forwarding = false; ArchCfg.use_load_stall_bubble = false; if(mipsCompatibilityCheckBox.isSelected()) { // reset the MIPS compatibility mipsCompatibilityCheckBox.setSelected(false); Preference.pref.putBoolean(Preference.mipsCompatibilityPreferenceKey, false); JOptionPane.showMessageDialog(MainFrame.getInstance(), "Reset \"MIPS compatibility mode\", since it requires activated forwarding.", "Info", JOptionPane.INFORMATION_MESSAGE); } } // propagate forwarding to menu propagateFWToMenu(forwardingCheckBox.isSelected()); // TODO also add a field for disabling the branch prediction // TODO do some checks for the setting of the BP initial state and sizes ArchCfg.branch_predictor_type = BranchPredictionModule.getBranchPredictorTypeFromGuiString(bpTypeComboBox.getSelectedItem().toString()); Preference.pref.put(Preference.bpTypePreferenceKey, ArchCfg.branch_predictor_type.toString()); ArchCfg.branch_predictor_initial_state = BranchPredictionModule. getBranchPredictorInitialStateFromGuiString( bpInitialStateComboBox.getSelectedItem().toString()); Preference.pref.put(Preference.bpInitialStatePreferenceKey, ArchCfg.branch_predictor_initial_state.toString()); ArchCfg.branch_predictor_table_size = Integer.parseInt(btbSizeTextField.getText()); Preference.pref.put(Preference.btbSizePreferenceKey, btbSizeTextField.getText()); // correct user input switch(ArchCfg.branch_predictor_type) { case UNKNOWN: case S_ALWAYS_TAKEN: case S_ALWAYS_NOT_TAKEN: case S_BACKWARD_TAKEN: // unknown and static predictors have no initial state and no branch predictor table size ArchCfg.branch_predictor_initial_state = BranchPredictorState.UNKNOWN; Preference.pref.put(Preference.bpInitialStatePreferenceKey, BranchPredictorState.UNKNOWN.toString()); ArchCfg.branch_predictor_table_size = 1; Preference.pref.put(Preference.btbSizePreferenceKey, new Integer(ArchCfg.branch_predictor_table_size).toString()); break; case D_1BIT: switch(ArchCfg.branch_predictor_initial_state) { case PREDICT_STRONGLY_NOT_TAKEN: case PREDICT_WEAKLY_NOT_TAKEN: // correct 2bit states to 1 bit state ArchCfg.branch_predictor_initial_state = BranchPredictorState.PREDICT_NOT_TAKEN; Preference.pref.put(Preference.bpInitialStatePreferenceKey, ArchCfg.branch_predictor_initial_state.toString()); break; case PREDICT_STRONGLY_TAKEN: case PREDICT_WEAKLY_TAKEN: // correct 2bit states to 1 bit state ArchCfg.branch_predictor_initial_state = BranchPredictorState.PREDICT_TAKEN; Preference.pref.put(Preference.bpInitialStatePreferenceKey, ArchCfg.branch_predictor_initial_state.toString()); break; case UNKNOWN: default: ArchCfg.branch_predictor_initial_state = BranchPredictorState.PREDICT_NOT_TAKEN; Preference.pref.put(Preference.bpInitialStatePreferenceKey, ArchCfg.branch_predictor_initial_state.toString()); // TODO Throw exception break; } break; case D_2BIT_SATURATION: case D_2BIT_HYSTERESIS: switch(ArchCfg.branch_predictor_initial_state) { case PREDICT_NOT_TAKEN: // correct 1bit states to 2 bit state ArchCfg.branch_predictor_initial_state = BranchPredictorState.PREDICT_WEAKLY_NOT_TAKEN; Preference.pref.put(Preference.bpInitialStatePreferenceKey, ArchCfg.branch_predictor_initial_state.toString()); break; case PREDICT_TAKEN: // correct 1bit states to 2 bit state ArchCfg.branch_predictor_initial_state = BranchPredictorState.PREDICT_WEAKLY_TAKEN; Preference.pref.put(Preference.bpInitialStatePreferenceKey, ArchCfg.branch_predictor_initial_state.toString()); break; case UNKNOWN: default: ArchCfg.branch_predictor_initial_state = BranchPredictorState.PREDICT_WEAKLY_NOT_TAKEN; Preference.pref.put(Preference.bpInitialStatePreferenceKey, ArchCfg.branch_predictor_initial_state.toString()); // TODO Throw exception break; } break; } // the btb has to be a power of two if (ArchCfg.branch_predictor_table_size == 0) { ArchCfg.branch_predictor_table_size = 1; Preference.pref.put(Preference.btbSizePreferenceKey, (new Integer(ArchCfg.branch_predictor_table_size)).toString()); // TODO Throw exception } ArchCfg.max_cycles = Integer.parseInt(maxCyclesTextField.getText()); Preference.pref.put(Preference.maxCyclesPreferenceKey, maxCyclesTextField.getText()); setVisible(false); dispose(); } } private void propagateFWToMenu(boolean forwarding_enabled) { MainFrame.getInstance().getForwardingMenuItem().setSelected(forwarding_enabled); } }