cache—主存—辅存三级调度模拟

近日,在体系结构的课程中,老师留了一个上机作业,为cache—主存—辅存三级调度模拟,要求如下:

实现三级存储体系的模拟调度程序

描述:CPU在cache访问数据块,若命中给出对应的cache实地址,若不命中在主存中查找,如果找到调入到cache中,若是cache已满使用LRU算法进行替换,采用写回法保持cache与主存的一致性。若是没有命中在辅存中查找,找到之后调入到主存,并更新cache。

实验要求:

(1)主存的容量可以更改

(2)分配给程序的页面数可以更改

(3)Cache采用组相连映像,cache大小、组数、组内块数均可以更改

(4)地址流可以采用输入的方式给出

(5)辅存部分可以不用实现

(6)要求有图形化的用户界面,上述参数均可以直接输入。

(7)显示执行程序时数据块以及页面的替换过程

(8)编程语言:选取自己熟悉的高级语言

百度了很久,没有找到Cache组相联映像的LRU替换算法,以下只是自己的一点想法与思路,若有不足,欢迎指正。

程序运行界面如下:

  

 点击确定后:

  

第0组Cache块中各个块的使用情况为:
T1时刻 1
T2时刻 1
T3时刻 1 4
T4时刻 4 1
T5时刻 4 1
T6时刻 4 1
T7时刻 1 0
T8时刻 0 1
T9时刻 0 1
T10时刻 1 5
T11时刻 5 4
T12时刻 5 4
T13时刻 5 4
T14时刻 5 4
T15时刻 5 4

第1组Cache块中各个块的使用情况为:
T2时刻 2
T3时刻 2
T4时刻 2
T5时刻 2 3
T6时刻 3 7
T7时刻 3 7
T8时刻 3 7
T9时刻 7 2
T10时刻 7 2
T11时刻 7 2
T12时刻 2 6
T13时刻 2 6
T14时刻 6 7
T15时刻 7 2

下面是Cache类的代码,主要实现Cache的LRU替换算法,使用LinkedHashMap本身自带的特性实现的LRU算法

import java.util.LinkedHashMap;
import java.util.Map;

/**
 * 模拟Catch块中的LRU替换算法
 * 此处使用java中LinkedHashMap,利用其自身特性,对removeEldestEntry()方法进行重写
 * @author SUIXUE
 *
 */
public class Cache {
    
    public  int cacheSize = 2;
    
    public Cache(){
        
    }
    
    public Cache(int cacheSize){
        this.cacheSize = cacheSize;
    }
    
    //此处的写法避免了新建类,也无需继承
    Map<Integer, Integer> map = new LinkedHashMap<Integer, Integer>((int) Math.ceil(cacheSize / 0.75f) + 1, 0.75f, true) {
        /**
         * 
         */
        private static final long serialVersionUID = 1L;

        @Override
        protected boolean removeEldestEntry(Map.Entry<Integer, Integer> eldest) {
        return size() > cacheSize;
        }
    };
    
    /**
     * 重写toString()方法
     */
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        for (Map.Entry<Integer, Integer> entry : this.map.entrySet()) {
            sb.append(String.format("%s   ", entry.getKey()));
        }
        return sb.toString();
    }
    
    /**
     * 此处的主要目的是在Cache中采用组相联映像时,在输出结果时同时显示当前时间
     * @param addr
     * @return
     */
    public String display(int[] addr){
        StringBuilder sb = new StringBuilder();
        int index =15-addr.length+1;
        for(int i = 0; i < addr.length;i++){
            this.map.put(addr[i], 0);
            sb.append("T").append(index++).append("时刻   ").append(this.toString()+"\n");
        }
        return sb.toString();
    }
}

下面是主界面的代码

  1 import java.awt.BorderLayout;
  2 import java.awt.GridLayout;
  3 import java.awt.event.ActionEvent;
  4 import java.awt.event.ActionListener;
  5 import java.util.ArrayList;
  6 
  7 import javax.swing.BorderFactory;
  8 import javax.swing.JButton;
  9 import javax.swing.JFrame;
 10 import javax.swing.JLabel;
 11 import javax.swing.JOptionPane;
 12 import javax.swing.JPanel;
 13 import javax.swing.JScrollPane;
 14 import javax.swing.JTextArea;
 15 import javax.swing.JTextField;
 16 
 17 /**
 18  * MainFrame类: 继承JFrame,同时实现接口ActionListener
 19  * 
 20  * @author SUIXUE
 21  * 
 22  */
 23 public class MainFrame extends JFrame implements ActionListener {
 24 
 25     /**
 26      * 
 27      */
 28     private static final long serialVersionUID = 1L;
 29 
 30     private int memory = 0;
 31     private int page = 0;
 32     private int memoryQuNum = 0;
 33 
 34     public int cacheSizeNum = 16;
 35     public int cacheGroupNum = 2;
 36     public int cacheBlockNumber = 2;
 37 
 38     private int cacheNum = cacheGroupNum * cacheBlockNumber;
 39     private int memoryBlockNum = 0;
 40     public int[] addr = new int[] {1,2,4,1,3,7,0,1,2,5,4,6,4,7,2};//默认的地址流,可以在界面文本框中更改
 41 
 42     public Cache[] cache;// 将cache的每组看做一个cache块
 43     public ArrayList<Integer>[] cacheAddrs;// 每组都有对应的地址流
 44 
 45     /**
 46      * 初始化Cache分组(本方法是将每个分组看做一个单独独立的Cache块)
 47      */
 48     public void initCache() {
 49         for (int i = 0; i < cache.length; i++) {
 50             cache[i] = new Cache(cacheBlockNumber);
 51         }
 52     }
 53 
 54     /**
 55      * 初始化地址流
 56      * 将用户输入的地址流,通过分析,分别对应进入不同的Cache分组中
 57      */
 58     public void initAddrs() {
 59         for (int i = 0; i < cacheAddrs.length; i++) {
 60             cacheAddrs[i] = new ArrayList<>();
 61         }
 62         for (int i = 0; i < addr.length; i++) {
 63             int temp = addr[i] % this.cacheNum;// 7%4 = 3
 64             int groupNum = temp / this.cacheBlockNumber;// 3/2 = 1
 65             
 66             ArrayList<Integer> arrayList = cacheAddrs[groupNum];
 67             arrayList.add(addr[i]);// 向各组添加地址流
 68             
 69             //当当前地址不对其他组进行影响时,其他组中的Cache地址流其实等同于该时刻仍是它上一次的地址
 70             if(i != 0){
 71                 for(int j = 0; j < cacheGroupNum;j++){
 72                     if(j != groupNum && cacheAddrs[j].size()>0){
 73                         cacheAddrs[j].add(cacheAddrs[j].get(cacheAddrs[j].size()-1));
 74                     }
 75                 }
 76             }
 77         }
 78     }
 79 
 80     private JPanel mainPanel;
 81 
 82     /**
 83      * 左侧面板
 84      */
 85     private JPanel originalPanel;
 86 
 87     // 主存大小
 88     private JPanel memoryPanel;
 89     private JLabel memorySizeLabel;
 90     private JTextField memorySize;
 91 
 92     // 页面数
 93     private JPanel pagePanel;
 94     private JLabel pageNumLabel;
 95     private JTextField pageNum;
 96 
 97     // cache
 98     private JPanel cachePanel;
 99 
100     // cache大小
101     private JPanel cacheSizePanel;
102     private JLabel cacheSizeLabel;
103     private JTextField cacheSize;
104 
105     // 组数
106     private JPanel cacheGroupSizePanel;
107     private JLabel cacheGroupSizeLabel;
108     private JTextField cacheGroupSize;
109 
110     // 组内块数
111     private JPanel cacheBlockNumPanel;
112     private JLabel cacheBlockNumLabel;
113     private JTextField cacheBlockNum;
114 
115     // 按钮
116     private JPanel button;
117     private JPanel addrPanel;
118     private JTextField addrText;
119     private JLabel addrLabel;
120     private JButton affirm;
121 
122     /**
123      * 右侧面板
124      */
125     private JScrollPane scrollPanel;
126     private JPanel resultPanel;
127 
128     private JLabel display;
129 
130     // 右侧转换结果显示框
131     private JTextArea resultArea;
132 
133     /**
134      * 构造函数
135      */
136     public MainFrame() {
137         initComponent();
138     }
139 
140     // 初始各组件
141     private void initComponent() {
142 
143         // 设置布局
144         mainPanel = new JPanel();
145         mainPanel.setLayout(new GridLayout(1, 2));
146 
147         // --------左侧面板---------------
148         originalPanel = new JPanel();
149         originalPanel.setLayout(new BorderLayout());
150 
151         // -------主存面板----------------
152         memoryPanel = new JPanel();
153         memorySizeLabel = new JLabel("主存容量");
154         memorySize = new JTextField(10);
155         memorySize.setHorizontalAlignment(JTextField.RIGHT);
156         memorySize.setText("32");
157         JLabel unitLabel = new JLabel("KB");
158         memoryPanel.add(memorySizeLabel, BorderLayout.WEST);
159         memoryPanel.add(memorySize, BorderLayout.CENTER);
160         memoryPanel.add(unitLabel, BorderLayout.EAST);
161 
162         // ---------页面大小面板----------------
163         pagePanel = new JPanel();
164         pageNumLabel = new JLabel("页面大小");
165         pageNum = new JTextField(10);
166         pageNum.setHorizontalAlignment(JTextField.RIGHT);
167         pageNum.setText("3");
168         JLabel unitLabel1 = new JLabel("页");
169         pagePanel.add(pageNumLabel, BorderLayout.WEST);
170         pagePanel.add(pageNum, BorderLayout.CENTER);
171         pagePanel.add(unitLabel1, BorderLayout.EAST);
172 
173         JPanel tempPanel = new JPanel();
174         tempPanel.setLayout(new GridLayout(2, 1));
175         tempPanel.add(memoryPanel);
176         tempPanel.add(pagePanel);
177 
178         // -----------cache面板---------------
179         cachePanel = new JPanel();
180         cachePanel.setLayout(new GridLayout(3, 1));
181         cachePanel.setBorder(BorderFactory.createTitledBorder("cache"));
182 
183         cacheSizeLabel = new JLabel("cahce大小");
184         cacheSize = new JTextField(10);
185         cacheSize.setHorizontalAlignment(JTextField.RIGHT);
186         cacheSize.setText("16");
187         JLabel unitLabel2 = new JLabel("KB");
188         cacheSizePanel = new JPanel();
189         cacheSizePanel.add(cacheSizeLabel, BorderLayout.WEST);
190         cacheSizePanel.add(cacheSize, BorderLayout.CENTER);
191         cacheSizePanel.add(unitLabel2, BorderLayout.EAST);
192 
193         cacheGroupSizeLabel = new JLabel("cahce组数");
194         cacheGroupSize = new JTextField(10);
195         cacheGroupSize.setHorizontalAlignment(JTextField.RIGHT);
196         cacheGroupSize.setText("2");
197         JLabel unitLabel3 = new JLabel("组");
198         cacheGroupSizePanel = new JPanel();
199         cacheGroupSizePanel.add(cacheGroupSizeLabel, BorderLayout.WEST);
200         cacheGroupSizePanel.add(cacheGroupSize, BorderLayout.CENTER);
201         cacheGroupSizePanel.add(unitLabel3, BorderLayout.EAST);
202 
203         cacheBlockNumLabel = new JLabel("组内块数   ");
204         cacheBlockNum = new JTextField(10);
205         cacheBlockNum.setHorizontalAlignment(JTextField.RIGHT);
206         cacheBlockNum.setText("2");
207         JLabel unitLabel4 = new JLabel("块");
208         cacheBlockNumPanel = new JPanel();
209         cacheBlockNumPanel.add(cacheBlockNumLabel, BorderLayout.WEST);
210         cacheBlockNumPanel.add(cacheBlockNum, BorderLayout.CENTER);
211         cacheBlockNumPanel.add(unitLabel4, BorderLayout.EAST);
212 
213         cachePanel.add(cacheSizePanel);
214         cachePanel.add(cacheGroupSizePanel);
215         cachePanel.add(cacheBlockNumPanel);
216 
217         button = new JPanel();
218         button.setLayout(new GridLayout(2,1));
219         
220         addrLabel = new JLabel("块地址流   ");
221         addrText = new JTextField(20);
222         addrText.setHorizontalAlignment(JTextField.RIGHT);
223         addrText.setText("1 2 4 1 3 7 0 1 2 5 4 6 4 7 2");
224         addrPanel = new JPanel();
225         addrPanel.add(addrLabel,BorderLayout.WEST);
226         addrPanel.add(addrText,BorderLayout.CENTER);
227         
228         JPanel affirmPanel = new JPanel();
229         affirm = new JButton("确定");
230         affirmPanel.add(affirm,BorderLayout.CENTER);
231         
232         button.add(addrPanel);
233         button.add(affirmPanel);
234         affirm.addActionListener(this);
235 
236         originalPanel.add(tempPanel, BorderLayout.NORTH);
237         originalPanel.add(cachePanel, BorderLayout.CENTER);
238         originalPanel.add(button, BorderLayout.SOUTH);
239 
240         // --------右侧面板---------------
241         resultPanel = new JPanel();
242         resultPanel.setLayout(new BorderLayout());
243 
244         display = new JLabel("Cache中各个块的使用情况");
245 
246         resultArea = new JTextArea();
247         resultArea.setEditable(false);
248         resultArea.setBorder(BorderFactory.createTitledBorder("RESULT"));
249 
250         scrollPanel = new JScrollPane(resultArea);
251 
252         resultPanel.add(display, BorderLayout.NORTH);
253         resultPanel.add(scrollPanel, BorderLayout.CENTER);
254 
255         // -------------------------------------------------------
256         mainPanel.add(originalPanel);
257         mainPanel.add(resultPanel);
258         mainPanel.setBorder(BorderFactory.createTitledBorder("三级调度模拟"));
259 
260         this.add(mainPanel);
261         this.setTitle("小可爱的三级调度模拟");
262         this.setSize(750, 350);
263         this.setDefaultCloseOperation(EXIT_ON_CLOSE);
264         this.setResizable(false);
265         this.setLocationRelativeTo(null);
266         this.setVisible(true);
267 
268     }
269 
270     @Override
271     public void actionPerformed(ActionEvent e) {
272 
273         try {
274             this.memory = Integer.valueOf(memorySize.getText());
275             this.page = Integer.valueOf(pageNum.getText());
276             this.cacheSizeNum = Integer.valueOf(cacheSize.getText());
277             this.cacheGroupNum = Integer.valueOf(cacheGroupSize.getText());
278             this.cacheBlockNumber = Integer.valueOf(cacheBlockNum.getText());
279             this.cacheNum = cacheGroupNum * cacheBlockNumber;
280             this.memoryQuNum = this.memory / this.cacheSizeNum;
281             this.memoryBlockNum = this.memoryQuNum * this.cacheNum;
282             
283             cache = new Cache[cacheGroupNum];
284             cacheAddrs = new ArrayList[cacheGroupNum];
285             
286             String addrString = this.addrText.getText();
287             String[] addrItems = addrString.split(" ");
288             
289             for(int i=0;i<addrItems.length;i++){
290                 this.addr[i]=Integer.parseInt(addrItems[i]);
291             }
292 
293             this.initCache();
294             this.initAddrs();
295 
296             StringBuilder sb = new StringBuilder();
297             for (int i = 0; i < this.cache.length; i++) {
298                 sb.append("第").append(i).append("组Cache块中各个块的使用情况为:\n");
299                 int[] addrTemp = new int[cacheAddrs[i].size()];
300                 for (int j = 0; j < this.cacheAddrs[i].size(); j++) {
301                     addrTemp[j] = ((Integer) this.cacheAddrs[i].get(j))
302                             .intValue();
303                 }
304                 sb.append(this.cache[i].display(addrTemp)).append("\n");
305             }
306             resultArea.setText(sb.toString());
307         } catch (Exception ex) {
308             JOptionPane.showMessageDialog(null, "所有输入均为正整数!\n地址流输入只能用一个空格隔开", "Sorry",
309                     JOptionPane.INFORMATION_MESSAGE);
310             memorySize.setText("32");
311             pageNum.setText("3");
312             cacheSize.setText("16");
313             cacheGroupSize.setText("2");
314             cacheBlockNum.setText("2");
315             addrText.setText("1 2 4 1 3 7 0 1 2 5 4 6 4 7 2");
316         }
317 
318     }
319 
320     /**
321      * main 方法
322      * 
323      * @param args
324      */
325     public static void main(String[] args) {
326         new MainFrame();
327     }
328 }
MainFrame

在解决Cache的组相联映像中,我主要采用的方法是将地址流随Cache分组而进行分组,只有特定的主存块才能进入到特定的Cache组中。针对每一组的Cache进行基本的Cache的LRU替换算法(Cache类中)

原文地址:https://www.cnblogs.com/suixue/p/5589538.html