Java Cache模拟器(图形界面) -电脑资料

时间:2018-03-02 02:21:15
染雾
分享
WORD下载 PDF下载 投诉

一、设计思路

1.综述

我沿用了助教给的Java模版,完成了基本要求:设置Cache总大小和块大小、设置映射机制、设置替换策略、设置写策略,也完成了所有较高要求:能把Cache分为数据Cache和指令Cache、能设置预取策略、能设置写不命中调块策略并且有UI界面,

Java Cache模拟器(图形界面)

在设计上我充分利用了面向对象的设计思路,把各个逻辑部件都封装成内部类,模拟各种行为的方法也封装在内部类的方法中。比较重要的内部类有Instruction类(模拟数据流个条指令)、CacheBlock(模拟各个Cache块特性)、Cache(封装所有Cache块,模拟Cache读写等)。

UI来配置Cache,要点在于将JCombox的选项映射到实际值。我设计的思路沿用模版,加载了din类型流文件后把指令全部读取到内存。这时候我把所有的Cache设置全部保存一遍固定下来并初始化Cache,在运行过程中修改各项JCombox的选项并不会改变当前Cache的设置,仅在下一次加载din流文件时重新载入配置。

下面详细介绍重要方法和各个内部类的设计思想(按照程序逻辑顺序)。

2.内部类CacheBlock

CacheBlock类模拟Cache的块,是一个纯模型类,每一个CacheBlock有一个tag标识(定义同书上Cache地址的块地址的tag)、dirty脏位(表示该块是否被修改过且没有写回Memory)、count计数(用于LRU计算访问次数,这里读写CacheBlock都会增加count)、time(组内Cache块入Cache时间,是一个从0-MAX_LONG的long长整型变量)。

CacheBlock需要一个tag初始化,初始化块count为0、time为-1(由Cache为每组设置的计时器在外部分配入组time)且该块是干净的。

3.Cache初始化,从UI选项到配置的映射

Cache初始化在点击加载din流文件的按键时完成(尽管很奇怪,但是我读din文件时就需要初始化每条Instruction,而初始化Instruction类需要知道当前Cache的配置,所以Cache配置需要先完成,将在后面的分条中介绍。我之前设计的是CachePrepare->ReadFile->CacheInit,后来把CachePrepare和CacheInit合并了)。

初始化Cache之前先置零所有统计量,根据mcacheType决定的类型算出Cache总大小(多少B)以及块大小(多少B)。然后以Cache总大小和块大小来实例化Cache类,接下来的初始化工作在下一小节介绍。

4.内部类Cache

Cache这种以组index作索引,组内块数固定的编址模式,很容易让我们想到用二维数组来模拟。因此最重要的字段是private CacheBlock cache[][],第一维坐标表示组,第二维坐标表示组内块编号。

除此之外,Cache类有一系列记录其属性的字段:cacheSize总大小、blockSize块大小、blockNum总block个数、blockOffset块内地址所占32位2进制地址位数、blockNumInAGroup一个组内块数量、groupNum组总数以及groupOffset组index寻址所占

32位2进制地址位数。这些属性计算公式如下:

blockNum = cacheSize / blockSize;

blockOffset = log2(blockSize);

blockNumInAGroup = pow(2, mwayIndex);

groupNum = blockNum / blockNumInAGroup;

groupOffset = log2(groupNum);

有了这些属性(groupOffset和blockOffset)即可把32位地址分割为三项:tag+index+inblockAddr,后面Instruction类介绍时会再次提到。

最后Cache还为每个组设置了一个入组时间计数器groupFIFOTime[],目的是为了分配实现先进先出队列时选择最早入队的块的time属性。每加载一个新的块入组,groupFIFOTime[index]加一。

Cache类有一系列模拟Cache行为的方法,如read读取Cache、write写入Cache、prefetch预取块、replaceCacheBlock替换块、loadToCache把块从内存加载到Cache等。下面分别介绍这几种方法具体实现:

(1)read

public boolean read(int tag, int index, int inblockAddr) {			for (int i = 0; i < blockNumInAGroup; i++) {				if (cache[index][i].tag == tag) {//hit					cache[index][i].count++;										/*						Now pretend to send data to CPU					*/					return true;				}			}			return false;		}

读方法传入一个地址的tag、index和inblockAddr,其中inblockAddr并不会用到,这里是为了模拟真实取块内某字节数据所需要提供的inblockAddr。

有了index就直接在该index索引的组内枚举blockNumInAGroup个块,对比每个块的tag。注意:这次实验没有说性能上的优化,那么我这里用O(n)的遍历,如果我们考虑到快速定位tag块可以用HashMap实现(但硬件上应该不会设计这么复杂的数据结构)。

read方法找到该块则返回true,没找到则返回false。其他Cache行为逻辑在单步执行那个方法中完成。

(2)write

public boolean write(int tag, int index, int inblockAddr) {			for (int i = 0; i < blockNumInAGroup; i++) {				if (cache[index][i].tag == tag) {//hit										cache[index][i].count++;					cache[index][i].dirty = true;					/*						Now pretend to write data to Cache					*/					if (mwriteIndex == 0) {//write back						//doing nothing					} else if (mwriteIndex == 1) {//write through						memoryWriteTime++;						/*							pretending to write dirty cache to memory after write to cache						*/						cache[index][i].dirty = false;					}					return true;				}			}			return false;		}

write时在Cache中找目标块也是遍历比较tag,若找到目标则改块访问次数++,dirty置位。模拟写入后(所有模拟动作部分我都用注释标注),判断Cache写回方法,若写回法则此时什么也不做(等待该脏块被替换出去时才写回Memory);若是写之直达法则模拟写Memory并擦除脏位。和read一样找到目标块返回true,否则返回false,其他逻辑交给外部处理。

(3)prefetch

public void prefetch(int nextBlockAddr) {					int nextTag = nextBlockAddr / pow(2, groupOffset + blockOffset);			int nextIndex = nextBlockAddr / pow(2, blockOffset) % pow(2, groupOffset);			replaceCacheBlock(nextTag, nextIndex);		}

预取我只做了指令预取(外部逻辑调用),即某条指令所在块Miss时预取下一个指令块。牢记Cache地址=tag: index: inblockAddr,用两个offset位数配合整除和取余运算获取这两部分的tag和index然后调用replaceCacheBlock选择合适的替换算法选择替换块并加载该下一个指令块。

(4)replaceCacheBlock

public void replaceCacheBlock(int tag, int index) {			if (mreplaceIndex == 0) {//LRU				int lruBlock = 0;				for (int i = 1; i < blockNumInAGroup; i++) {					if (cache[index][lruBlock].count > cache[index][i].count) {						lruBlock = i;					}				}				loadToCache(tag, index, lruBlock);			} else if (mreplaceIndex == 1) {//FIFO				int fifoBlock = 0;				for (int i = 1; i < blockNumInAGroup; i++) {					if (cache[index][fifoBlock].time > cache[index][i].time) {						fifoBlock = i;					}				}				loadToCache(tag, index, fifoBlock);			} else if (mreplaceIndex == 2) {//random				int ranBlock = random(0, blockNumInAGroup);				loadToCache(tag, index, ranBlock);			}		}

根据不同的替换策略选取不同的被替换块,LRU则遍历组内最近最少被使用的块用loadToCache方法替换出去(这里使用优先队列是不是性能更好?),FIFO则根据记录组内入Cache时间的time属性选取最先入组的块替换出去,随机则比较简单直接产生一个组内编号的随机数替换。

(5)loadToCache

private void loadToCache(int tag, int index, int groupAddr) {			if (mwriteIndex == 0 && cache[index][groupAddr].dirty) {				//write back before being replaced;				memoryWriteTime++;			}			cache[index][groupAddr].tag = tag;			cache[index][groupAddr].count = 1;			cache[index][groupAddr].dirty = false;			cache[index][groupAddr].time = groupFIFOTime[index];			groupFIFOTime[index]++;		}

替换一个块,首先需要判断是不是用写回法,若是则一定在该Cache块替换出去之前写回内存,然后再设置块的tag位、count置1访问一次、非脏,且用groupFIFOTime分配入组时间。

5.内部类Instruction

Instruction类实例化需要传入din数据流文件中一条数据流指令的opt操作码和地址addr。构造函数内部实现了一个数据选择器和译码器,首先用HexAddr2BinAddr()方法将10进制地址转换为32位2进制地址(32位01字符串)。然后根据Cache设置中计算出的groupOffset和blockOffset分割该字符串,得到tag、index、inblockAddr和blockAddr(tag:index)。注意,这里分割使用的Offset需要考虑Cache类型,统一Cache还是独立Cache/数据Cache还是指令Cache。

HexAddr2BinAddr()就是无脑的switch case转换即可,之前注意补0补齐32位地址即可。

6.内部类DinFileFilter

DinFileFilter是个辅助类,辅助JFileChooser选出我们要的din类型的文件,继承FileFilter类重写accept方法即可。

7.执行(单步、步进到底)和统计量

单步执行需要定义一个ip指针,指向当前执行数据流指令的index。ip等于0时清空一次Cache、重置所有统计量并把UI显示统计量的部分清空刷新。instructions数组中存储在读取din文件就实例化的Instruction实例,在单步执行时我们可以直接利用分割好的地址。取得当前指令后要做的首要事情就是判断Cache类型,统一Cache的指令和数据是存在一个Cache中,分离Cache中他们是分开存储的。下面以分离Cache为例简要分析:

(1)读数据

if (opt == 0) {// read data				isHit = dCache.read(tag, index, inblockAddr);				if (isHit) {					readDataHitTime++;				} else {					readDataMissTime++;					/*						Now pretend to find the block in memory					*/					dCache.replaceCacheBlock(tag, index);					/*						Now pretend to load the data in block into CPU					*/				}			}

读数据访问dCache,read方法返回是否命中,更新响应统计量计数。若不命中则模拟从Memory调块 -> 调用replaceCacheBlock方法替换旧块并装入新块 -> 最后模拟把这个block中的目标数据返回给CPU。

(2)写数据

<span></span>else if (opt == 1) {// write data				isHit = dCache.write(tag, index, inblockAddr);				if (isHit) {					writeDataHitTime++;				} else {					writeDataMissTime++;					/*						Now pretend to find the block in memory					*/					if (mallocIndex == 0) {//write alloc						/*							load the target block into Cache						*/						dCache.replaceCacheBlock(tag, index);						/*							pretend to write into the loaded Cache block						*/						dCache.write(tag, index, inblockAddr);					} else if (mallocIndex == 1) {//no write alloc						/*							do not load the written-missed block into Cache							just pretend to write to memory						*/						memoryWriteTime++;					}				}

写数据同样是针对dCache,write返回命中与否并据此更新统计量。若写不命中,模拟在Memory中找到该块,根据写不命中策略决定是否把不命中块加载到Cache中:若使用按写分配策略则调该Miss块入Cache,同样用replaceCacheBlock方法并模拟write(注意这里要再调一次write,且不记录模拟统计值);若不按写分配则直接模拟写修改MEM。

(3)读指令

} else if (opt == 2) {// read instruction 				isHit = iCache.read(tag, index, inblockAddr);				if (isHit) {					readInstHitTime++;				} else {					readInstMissTime++;					/*						Now pretend to find the block in memory					*/					iCache.replaceCacheBlock(tag, index);					/*						Now pretend to load the data in block into CPU					*/					if (mprefetchIndex == 0) {// do not prefetch						//doing nothing					} else if (mprefetchIndex == 1){// prefetch if instruction missed!						iCache.prefetch(instructions[ip].blockAddr + 1);					}				}			}

读指令调用iCache指令Cache的read方法,其他跟dCache读数据一样,除了需要判断一下用不用预取,若需要则传入下一个指令块地址预取该块。

二、分析结论

略,以后补充

三、说明

实验中我和助教给的c++程序比较了几组Cache设置,跑出来结果是一样的。但有的时候偶尔统计不一样,即使所有设置都一样。排除随机因素如随机替换,我给出一点可能不太正确的解释:比如LRU如果组内有某多个块的count值相同,那么我写的程序和助教给的程序选择的替换块可能不同,因此最后结果可能有细微差别(差别不大,1-2条Miss或Hit统计差别)。

我暂时认为我的程序没有问题,但也不能保证...若有Bug请提出,谢谢啦!

四、完整代码

import java.awt.BorderLayout;import java.awt.Dimension;import java.awt.Color;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.awt.event.ItemEvent;import java.awt.event.ItemListener;import java.io.File;import javax.swing.*;import javax.swing.border.EtchedBorder;import java.lang.*;import java.util.*;public class MyCacheSim extends JFrame. implements ActionListener {	private static final long serialVersionUID = 1L;/*	ui property*/	private JPanel panelTop, panelLeft, panelRight, panelBottom;	private JButton execStepBtn, execAllBtn, fileBotton;	private JComboBox<string>csBox, bsBox, wayBox, replaceBox, prefetchBox, writeBox, allocBox;	private JComboBox<string>icsBox, dcsBox;	private JFileChooser fileChooser;		private JLabel labelTop,labelLeft,rightLabel,bottomLabel,fileLabel,fileAddrBtn, stepLabel1, stepLabel2, csLabel, bsLabel, wayLabel, replaceLabel, prefetchLabel, writeLabel, allocLabel;	private JLabel icsLabel, dcsLabel;	private JLabel resultTagLabel[][];	private JLabel resultDataLabel[][];	private JLabel accessTypeTagLabel, addressTagLabel, blockNumberTagLabel, tagTagLabel, indexTagLabel, inblockAddressTagLabel, hitTagLabel;	private JLabel accessTypeDataLabel, addressDataLabel, blockNumberDataLabel, tagDataLabel, indexDataLabel, inblockAddressDataLabel, hitDataLabel;	private JRadioButton unifiedCacheButton, separateCacheButton;/*	options section*/	private final String cachesize[] = { "2KB", "8KB", "32KB", "128KB", "512KB", "2MB" };	private final String scachesize[] = { "1KB", "4KB", "16KB", "64KB", "256KB", "1MB" };	private final  String blocksize[] = { "16B", "32B", "64B", "128B", "256B" };	private final  String way[] = { "直接映象", "2路", "4路", "8路", "16路", "32路" };	private final  String replace[] = { "LRU", "FIFO", "RAND" };	private final  String pref[] = { "不预取", "不命中预取" };	private final  String write[] = { "写回法", "写直达法" };	private final  String alloc[] = { "按写分配", "不按写分配" };	//private final  String typename[] = { "读数据", "写数据", "读指令" };	//private String hitname[] = {"不命中", "命中" };	private final  String resultTags[][] = {		{"访问总次数:", "不命中次数:", "不命中率:"}, 		{"读指令次数:", "不命中次数:", "不命中率:"},		{"读数据次数:", "不命中次数:", "不命中率:"},		{"写数据次数:", "不命中次数:", "不命中率:"}	};/*	loading file*/	private File file;/*	user options record*/	private int csIndex, bsIndex, wayIndex, replaceIndex, prefetchIndex, writeIndex, allocIndex;	private int mcsIndex, mbsIndex, mwayIndex, mreplaceIndex, mprefetchIndex, mwriteIndex, mallocIndex;	private int icsIndex, dcsIndex, micsIndex, mdcsIndex;	private int cacheType = 0, mcacheType = 0;/*	instruction class*/	private class Instruction {		int opt;		int tag;		int index;		int blockAddr;		int inblockAddr;		String addr;		public Instruction(int opt, String addr) {			this.opt = opt;			this.addr = addr;			String baddr = this.HexAddr2BinAddr();			//System.out.println(baddr);			if (mcacheType == 0 && uCache != null) {				this.tag = Integer.parseInt(baddr.substring(0, 32 - uCache.blockOffset - uCache.groupOffset), 2);				this.index = Integer.parseInt(baddr.substring(32 - uCache.blockOffset - uCache.groupOffset, 32 - uCache.blockOffset), 2);				this.blockAddr = Integer.parseInt(baddr.substring(0, 32 - uCache.blockOffset), 2);				this.inblockAddr = Integer.parseInt(baddr.substring(32 - uCache.blockOffset), 2);			}			if (mcacheType == 1 && iCache != null && dCache != null) {				if (opt == 0 || pt == 1) {					this.tag = Integer.parseInt(baddr.substring(0, 32 - dCache.blockOffset - dCache.groupOffset), 2);					this.index = Integer.parseInt(baddr.substring(32 - dCache.blockOffset - dCache.groupOffset, 32 - dCache.blockOffset), 2);					this.blockAddr = Integer.parseInt(baddr.substring(0, 32 - dCache.blockOffset), 2);					this.inblockAddr = Integer.parseInt(baddr.substring(32 - dCache.blockOffset), 2);				} else if (opt == 2) {					this.tag = Integer.parseInt(baddr.substring(0, 32 - iCache.blockOffset - iCache.groupOffset), 2);					this.index = Integer.parseInt(baddr.substring(32 - iCache.blockOffset - iCache.groupOffset, 32 - iCache.blockOffset), 2);					this.blockAddr = Integer.parseInt(baddr.substring(0, 32 - iCache.blockOffset), 2);					this.inblockAddr = Integer.parseInt(baddr.substring(32 - iCache.blockOffset), 2);				}			}		}		public String description() {			return "opt = " + opt + ", tag = " + tag + ", index = " + index + ", inblockAddr = " + inblockAddr; 		}		private String HexAddr2BinAddr() {			StringBuffer sb = new StringBuffer();			int zero = 8 - this.addr.length();			for (int i = 0; i < zero; i++) {				sb.append("0000");			}			for (int i = 0; i < this.addr.length(); i++) {				switch(this.addr.charAt(i)) {					case '0':						sb.append("0000");						break;					case '1':						sb.append("0001");						break;					case '2':						sb.append("0010");						break;					case '3':						sb.append("0011");						break;					case '4':						sb.append("0100");						break;					case '5':						sb.append("0101");						break;					case '6':						sb.append("0110");						break;					case '7':						sb.append("0111");						break;					case '8':						sb.append("1000");						break;					case '9':						sb.append("1001");						break;					case 'a':						sb.append("1010");						break;					case 'b':						sb.append("1011");						break;					case 'c':						sb.append("1100");						break;					case 'd':						sb.append("1101");						break;					case 'e':						sb.append("1110");						break;					case 'f':						sb.append("1111");						break;					default:						System.out.println("Data Error!");				}			}			return sb.toString();		}	}/*	instruction property*/	private Instruction instructions[];	private final int INSTRUCTION_MAX_SIZE = 100000;	private int isize;	private int ip;	private class CacheBlock {		int tag;		boolean dirty;		int count;		long time;		public CacheBlock(int tag) {			this.tag = tag;			dirty = false;			count = 0;			time = -1L;		}	}/*	cache class*/	private class Cache { 	/*		cache property	*/		private CacheBlock cache[][];		private int 	cacheSize; 		private int 	blockSize; 		private int 	blockNum;		private int 	blockOffset;		private int 	blockNumInAGroup;		private int 	groupNum;		private int 	groupOffset;		private long groupFIFOTime[];		public Cache(int csize, int bsize) {			cacheSize = csize;			blockSize = bsize;			blockNum = cacheSize / blockSize;			blockOffset = log2(blockSize);			blockNumInAGroup = pow(2, mwayIndex);			groupNum = blockNum / blockNumInAGroup;			groupOffset = log2(groupNum);			cache = new CacheBlock[groupNum][blockNumInAGroup];			for (int i = 0; i < groupNum; i++) {				for (int j = 0; j < blockNumInAGroup; j++) {					cache[i][j] = new CacheBlock(-1);				}			}			groupFIFOTime = new long[groupNum];		}		public boolean read(int tag, int index, int inblockAddr) {			for (int i = 0; i < blockNumInAGroup; i++) {				if (cache[index][i].tag == tag) {//hit					cache[index][i].count++;										/*						Now pretend to send data to CPU					*/					return true;				}			}			return false;		}		public boolean write(int tag, int index, int inblockAddr) {			for (int i = 0; i < blockNumInAGroup; i++) {				if (cache[index][i].tag == tag) {//hit										cache[index][i].count++;					cache[index][i].dirty = true;					/*						Now pretend to write data to Cache					*/					if (mwriteIndex == 0) {//write back						//doing nothing					} else if (mwriteIndex == 1) {//write through						memoryWriteTime++;						/*							pretending to write dirty cache to memory after write to cache						*/						cache[index][i].dirty = false;					}					return true;				}			}			return false;		}		public void prefetch(int nextBlockAddr) {					int nextTag = nextBlockAddr / pow(2, groupOffset + blockOffset);			int nextIndex = nextBlockAddr / pow(2, blockOffset) % pow(2, groupOffset);			replaceCacheBlock(nextTag, nextIndex);		}		public void replaceCacheBlock(int tag, int index) {			if (mreplaceIndex == 0) {//LRU				int lruBlock = 0;				for (int i = 1; i < blockNumInAGroup; i++) {					if (cache[index][lruBlock].count > cache[index][i].count) {						lruBlock = i;					}				}				loadToCache(tag, index, lruBlock);			} else if (mreplaceIndex == 1) {//FIFO				int fifoBlock = 0;				for (int i = 1; i < blockNumInAGroup; i++) {					if (cache[index][fifoBlock].time > cache[index][i].time) {						fifoBlock = i;					}				}				loadToCache(tag, index, fifoBlock);			} else if (mreplaceIndex == 2) {//random				int ranBlock = random(0, blockNumInAGroup);				loadToCache(tag, index, ranBlock);			}		}		private void loadToCache(int tag, int index, int groupAddr) {			if (mwriteIndex == 0 && cache[index][groupAddr].dirty) {				//write back before being replaced;				memoryWriteTime++;			}			cache[index][groupAddr].tag = tag;			cache[index][groupAddr].count = 1;			cache[index][groupAddr].dirty = false;			cache[index][groupAddr].time = groupFIFOTime[index];			groupFIFOTime[index]++;		}		public void description() {			System.out.println("cacheSize = " + cacheSize);			System.out.println("blockSize = " + blockSize);			System.out.println("blockNum = " + blockNum);			System.out.println("blockOffset = " + blockOffset);			System.out.println("blockNumInAGroup = " + blockNumInAGroup);			System.out.println("groupNum = " + groupNum);			System.out.println("groupOffset = " + groupOffset);		}	}	Cache uCache, iCache, dCache;/* *	statistic property */	private int readDataMissTime, readInstMissTime, readInstHitTime, readDataHitTime;	private int writeDataHitTime, writeDataMissTime;	private int memoryWriteTime;/* *	JFileChooser Filter Class */	private class DinFileFilter extends  javax.swing.filechooser.FileFilter{		public boolean accept(File f) {			if (f.isDirectory()) return true;			String name = f.getName();			return name.endsWith(".din") || name.endsWith(".DIN");		}		public String getDescription() {			return ".din";		}	}/* *	cache simulator class */	public MyCacheSim(){		super("Cache Simulator");		fileChooser = new JFileChooser();		fileChooser.setFileFilter(new DinFileFilter());		draw();	}	public void actionPerformed(ActionEvent e) {		if (e.getSource() == execAllBtn) {			simExecAll();		}		if (e.getSource() == execStepBtn) {			simExecStep(true);		}		if (e.getSource() == fileBotton){			int fileOver = fileChooser.showOpenDialog(null);			if (fileOver == 0) {				   	String path = fileChooser.getSelectedFile().getAbsolutePath();				   	fileAddrBtn.setText(path);				   	file = new File(path);				   	/*						fix the setting					*/					mcacheType = cacheType;					mcsIndex = csIndex;					micsIndex = icsIndex;					mdcsIndex = dcsIndex;					mbsIndex = bsIndex;					mwayIndex = wayIndex;					mreplaceIndex = replaceIndex;					mprefetchIndex = prefetchIndex;					mwriteIndex = writeIndex;					mallocIndex = allocIndex;				   	initCache();				   	readFile();					reloadUI();			}		}	}	/*	 * 初始化 Cache 模拟器	 */	private void initCache() {		/*			reset statistic properties		*/		readDataMissTime = 0;		readInstMissTime = 0;		readDataHitTime = 0;		readInstHitTime = 0;		writeDataHitTime = 0;		writeDataMissTime = 0;		memoryWriteTime = 0;		/*			Cache initialization		*/		if (mcacheType == 0) {			uCache = new Cache(2 * 1024 * pow(4, mcsIndex), 16 * pow(2, mbsIndex));			iCache = null;			dCache = null;			System.out.println("Unified Cache:");			uCache.description();	 	} else if (mcacheType == 1) {	 		uCache = null;	 		iCache = new Cache(1 * 1024 * pow(4, micsIndex), 16 * pow(2, mbsIndex));			dCache = new Cache(1 * 1024 * pow(4, mdcsIndex), 16 * pow(2, mbsIndex));			System.out.println("Instruction Cache:");			iCache.description();			System.out.println("Data Cache:");			dCache.description();	 	}	}		/*	 * 将指令和数据流从文件中读入	 */	private void readFile() {		try {			Scanner s = new Scanner(file);			instructions = new Instruction[INSTRUCTION_MAX_SIZE];			isize = 0;			ip = 0;			while(s.hasNextLine()) {				String line = s.nextLine();				String[] items = line.split(" ");				instructions[isize] = new Instruction(Integer.parseInt(items[0].trim()), items[1].trim());				isize++;			}		} catch(Exception e) {			e.printStackTrace();		}	}	private void reloadUI() {		for (int i = 0; i < 4; i++) {			for (int j = 0; j < 2; j++) {				resultDataLabel[i][j].setText("0");			}			resultDataLabel[i][2].setText("0.00%");		}		accessTypeDataLabel.setText("--");		addressDataLabel.setText("--");		blockNumberDataLabel.setText("--");		tagDataLabel.setText("--");		indexDataLabel.setText("--");		inblockAddressDataLabel.setText("--");		hitDataLabel.setText("--");	}		/*	 * 模拟单步执行	 */	private void simExecStep(boolean oneStepExec) {		ip %= isize;		if (ip == 0) {			initCache();			reloadUI();		}		int pt = instructions[ip].opt;		int index = instructions[ip].index;		int tag = instructions[ip].tag;		int inblockAddr = instructions[ip].inblockAddr;				//System.out.printf("opt = %d, tag = %d, index = %d, inblockAddr = %d\n", opt, tag, index, inblockAddr);		System.out.println(instructions[ip].description());		boolean isHit = false;		if (mcacheType == 0) {/*		unified cache*/				if (opt == 0) {// read data				isHit = uCache.read(tag, index, inblockAddr);				if (isHit) {					readDataHitTime++;				} else {					readDataMissTime++;					/*						Now pretend to find the block in memory					*/					uCache.replaceCacheBlock(tag, index);					/*						Now pretend to load the data in block into CPU					*/				}			} else if (opt == 1) {// write data				isHit = uCache.write(tag, index, inblockAddr);				if (isHit) {					writeDataHitTime++;				} else {					writeDataMissTime++;					/*						Now pretend to find the block in memory					*/					if (mallocIndex == 0) {//write alloc						/*							load the target block into Cache						*/						uCache.replaceCacheBlock(tag, index);						/*							pretend to write into the loaded Cache block						*/						uCache.write(tag, index, inblockAddr);					} else if (mallocIndex == 1) {//no write alloc						/*							do not load the written-missed block into Cache							just pretend to write to memory						*/						memoryWriteTime++;					}				}			} else if (opt == 2) {// read instruction 				isHit = uCache.read(tag, index, inblockAddr);				if (isHit) {					readInstHitTime++;				} else {					readInstMissTime++;					/*						Now pretend to find the block in memory					*/					uCache.replaceCacheBlock(tag, index);					/*						Now pretend to load the data in block into CPU					*/					if (mprefetchIndex == 0) {// do not prefetch						//doing nothing					} else if (mprefetchIndex == 1){// prefetch if instruction missed!						uCache.prefetch(instructions[ip].blockAddr + 1);					}				}			}		} else if (mcacheTyp

e == 1) {/* seperated cache*/ if (opt == 0) {// read data isHit = dCache.read(tag, index, inblockAddr); if (isHit) { readDataHitTime++; } else { readDataMissTime++; /* Now pretend to find the block in memory */ dCache.replaceCacheBlock(tag, index); /* Now pretend to load the data in block into CPU */ } } else if (opt == 1) {// write data isHit = dCache.write(tag, index, inblockAddr); if (isHit) { writeDataHitTime++; } else { writeDataMissTime++; /* Now pretend to find the block in memory */ if (mallocIndex == 0) {//write alloc /* load the target block into Cache */ dCache.replaceCacheBlock(tag, index); /* pretend to write into the loaded Cache block */ dCache.write(tag, index, inblockAddr); } else if (mallocIndex == 1) {//no write alloc /* do not load the written-missed block into Cache just pretend to write to memory */ memoryWriteTime++; } } } else if (opt == 2) {// read instruction isHit = iCache.read(tag, index, inblockAddr); if (isHit) { readInstHitTime++; } else { readInstMissTime++; /* Now pretend to find the block in memory */ iCache.replaceCacheBlock(tag, index); /* Now pretend to load the data in block into CPU */ if (mprefetchIndex == 0) {// do not prefetch //doing nothing } else if (mprefetchIndex == 1){// prefetch if instruction missed! iCache.prefetch(instructions[ip].blockAddr + 1); } } } } if (oneStepExec || ip == isize - 1) { statisticUIUpdate(instructions[ip], isHit); } ip++; } private void statisticUIUpdate(Instruction inst, boolean isHit) { int totalMissTime = readInstMissTime + readDataMissTime + writeDataMissTime; int totalVisitTime = totalMissTime + readInstHitTime + readDataHitTime + writeDataHitTime; resultDataLabel[0][0].setText(totalVisitTime + ""); resultDataLabel[0][1].setText(totalMissTime + ""); if (totalVisitTime > 0) { double missRate = ((double)totalMissTime / (double)totalVisitTime) * 100; resultDataLabel[0][2].setText(String.format("%.2f", missRate) + "%"); } resultDataLabel[1][0].setText((readInstHitTime + readInstMissTime) + ""); resultDataLabel[1][1].setText(readInstMissTime + ""); if (readInstMissTime + readInstHitTime > 0) { double missRate = ((double)readInstMissTime/(double)(readInstMissTime + readInstHitTime)) * 100; resultDataLabel[1][2].setText(String.format("%.2f", missRate) + "%"); } resultDataLabel[2][0].setText((readDataHitTime + readDataMissTime) + ""); resultDataLabel[2][1].setText(readDataMissTime + ""); if (readDataMissTime + readDataHitTime > 0) { double missRate = ((double)readDataMissTime/(double)(readDataMissTime + readDataHitTime)) * 100; resultDataLabel[2][2].setText(String.format("%.2f", missRate) + "%"); } resultDataLabel[3][0].setText((writeDataHitTime + writeDataMissTime) + ""); resultDataLabel[3][1].setText(writeDataMissTime + ""); if (writeDataMissTime + writeDataHitTime > 0) { double missRate = ((double)writeDataMissTime/(double)(writeDataMissTime + writeDataHitTime)) * 100; resultDataLabel[3][2].setText(String.format("%.2f", missRate) + "%"); } if (inst.opt == 0) { accessTypeDataLabel.setText("读指令"); } else if (inst.opt == 1) { accessTypeDataLabel.setText("读数据"); } else if (inst.opt == 2) { accessTypeDataLabel.setText("写数据"); } else { accessTypeDataLabel.setText("非法指令"); } addressDataLabel.setText(inst.addr); blockNumberDataLabel.setText(inst.blockAddr + ""); tagDataLabel.setText(inst.tag + ""); indexDataLabel.setText(inst.index + ""); inblockAddressDataLabel.setText(inst.inblockAddr + ""); if (isHit) { hitDataLabel.setText("命中"); } else { hitDataLabel.setText("未命中"); } } /* * 模拟执行到底 */ private void simExecAll() { while (ip < isize) { simExecStep(false); } } /* 辅助函数 */ private int pow(int x, int p) { return (int)Math.pow(x, p); } private int log2(int x) { return (int)(Math.log(x) / Math.log(2)); } private int random(int x, int y) { return (int)Math.random() * (y - x) + x; } /* 绘制界面 */ private void unifiedCacheEnabled(boolean enabled) { unifiedCacheButton.setSelected(enabled); csLabel.setEnabled(enabled); csBox.setEnabled(enabled); } private void separateCacheEnabled(boolean enabled) { separateCacheButton.setSelected(enabled); icsLabel.setEnabled(enabled); dcsLabel.setEnabled(enabled); icsBox.setEnabled(enabled); dcsBox.setEnabled(enabled); } private void draw() { setLayout(new BorderLayout(5,5)); panelTop = new JPanel(); panelLeft = new JPanel(); panelRight = new JPanel(); panelBottom = new JPanel(); panelTop.setPreferredSize(new Dimension(800, 50)); panelLeft.setPreferredSize(new Dimension(300, 450)); panelRight.setPreferredSize(new Dimension(500, 450)); panelBottom.setPreferredSize(new Dimension(800, 100)); panelTop.setBorder(new EtchedBorder(EtchedBorder.RAISED)); panelLeft.setBorder(new EtchedBorder(EtchedBorder.RAISED)); panelRight.setBorder(new EtchedBorder(EtchedBorder.RAISED)); panelBottom.setBorder(new EtchedBorder(EtchedBorder.RAISED)); labelTop = new JLabel("Cache Simulator by JCGuo"); labelTop.setAlignmentX(CENTER_ALIGNMENT); JLabel promptLabel = new JLabel(" (Notice! 如果修改了左侧Cache设置请重新加载流文件再运行!)"); promptLabel.setForeground(Color.red); panelTop.add(labelTop); panelTop.add(promptLabel); labelLeft = new JLabel("Cache 参数设置"); labelLeft.setPreferredSize(new Dimension(300, 40)); csLabel = new JLabel("总大小"); csLabel.setPreferredSize(new Dimension(80, 30)); csBox = new JComboBox<string>(cachesize); csBox.setPreferredSize(new Dimension(90, 30)); csBox.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { csIndex = csBox.getSelectedIndex(); } }); //cache 种类 unifiedCacheButton = new JRadioButton("统一Cache:", true); unifiedCacheButton.setPreferredSize(new Dimension(100, 30)); unifiedCacheButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { separateCacheEnabled(false); unifiedCacheEnabled(true); cacheType = 0; } }); separateCacheButton = new JRadioButton("分离Cache:"); separateCacheButton.setPreferredSize(new Dimension(100, 30)); separateCacheButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { separateCacheEnabled(true); unifiedCacheEnabled(false); cacheType = 1; } }); icsLabel = new JLabel("指令Cache"); icsLabel.setPreferredSize(new Dimension(80, 30)); dcsLabel = new JLabel("数据Cache"); dcsLabel.setPreferredSize(new Dimension(80, 30)); JLabel emptyLabel = new JLabel(""); emptyLabel.setPreferredSize(new Dimension(100, 30)); icsBox = new JComboBox<string>(scachesize); icsBox.setPreferredSize(new Dimension(90, 30)); icsBox.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { icsIndex = icsBox.getSelectedIndex(); } }); dcsBox = new JComboBox<string>(scachesize); dcsBox.setPreferredSize(new Dimension(90, 30)); dcsBox.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { dcsIndex = dcsBox.getSelectedIndex(); } }); separateCacheEnabled(false); unifiedCacheEnabled(true); //cache 块大小设置 bsLabel = new JLabel("块大小"); bsLabel.setPreferredSize(new Dimension(120, 30)); bsBox = new JComboBox<string>(blocksize); bsBox.setPreferredSize(new Dimension(160, 30)); bsBox.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { bsIndex = bsBox.getSelectedIndex(); } }); //相连度设置 wayLabel = new JLabel("相联度"); wayLabel.setPreferredSize(new Dimension(120, 30)); wayBox = new JComboBox<string>(way); wayBox.setPreferredSize(new Dimension(160, 30)); wayBox.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { wayIndex = wayBox.getSelectedIndex(); } }); //替换策略设置 replaceLabel = new JLabel("替换策略"); replaceLabel.setPreferredSize(new Dimension(120, 30)); replaceBox = new JComboBox<string>(replace); replaceBox.setPreferredSize(new Dimension(160, 30)); replaceBox.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { replaceIndex = replaceBox.getSelectedIndex(); } }); //欲取策略设置 prefetchLabel = new JLabel("预取策略"); prefetchLabel.setPreferredSize(new Dimension(120, 30)); prefetchBox = new JComboBox<string>(pref); prefetchBox.setPreferredSize(new Dimension(160, 30)); prefetchBox.addItemListener(new ItemListener(){ public void itemStateChanged(ItemEvent e){ prefetchIndex = prefetchBox.getSelectedIndex(); } }); //写策略设置 writeLabel = new JLabel("写策略"); writeLabel.setPreferredSize(new Dimension(120, 30)); writeBox = new JComboBox<string>(write); writeBox.setPreferredSize(new Dimension(160, 30)); writeBox.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { writeIndex = writeBox.getSelectedIndex(); } }); //调块策略 allocLabel = new JLabel("写不命中调块策略"); allocLabel.setPreferredSize(new Dimension(120, 30)); allocBox = new JComboBox<string>(alloc); allocBox.setPreferredSize(new Dimension(160, 30)); allocBox.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { allocIndex = allocBox.getSelectedIndex(); } }); //选择指令流文件 fileLabel = new JLabel("选择指令流文件"); fileLabel.setPreferredSize(new Dimension(120, 30)); fileAddrBtn = new JLabel(); fileAddrBtn.setPreferredSize(new Dimension(210,30)); fileAddrBtn.setBorder(new EtchedBorder(EtchedBorder.RAISED)); fileBotton = new JButton("浏览"); fileBotton.setPreferredSize(new Dimension(70,30)); fileBotton.addActionListener(this); panelLeft.add(labelLeft); panelLeft.add(unifiedCacheButton); panelLeft.add(csLabel); panelLeft.add(csBox); panelLeft.add(separateCacheButton); panelLeft.add(icsLabel); panelLeft.add(icsBox); panelLeft.add(emptyLabel); panelLeft.add(dcsLabel); panelLeft.add(dcsBox); panelLeft.add(bsLabel); panelLeft.add(bsBox); panelLeft.add(wayLabel); panelLeft.add(wayBox); panelLeft.add(replaceLabel); panelLeft.add(replaceBox); panelLeft.add(prefetchLabel); panelLeft.add(prefetchBox); panelLeft.add(writeLabel); panelLeft.add(writeBox); panelLeft.add(allocLabel); panelLeft.add(allocBox); panelLeft.add(fileLabel); panelLeft.add(fileAddrBtn); panelLeft.add(fileBotton); //*****************************右侧面板绘制*****************************************// //模拟结果展示区域 rightLabel = new JLabel("模拟结果"); rightLabel.setPreferredSize(new Dimension(500, 40)); panelRight.add(rightLabel); resultTagLabel = new JLabel[4][3]; resultDataLabel = new JLabel[4][3]; for (int i = 0; i < 4; i++) { for (int j = 0; j < 3; j++) { resultTagLabel[i][j] = new JLabel(resultTags[i][j]); resultTagLabel[i][j].setPreferredSize(new Dimension(70, 40)); if (j != 2) { resultDataLabel[i][j] = new JLabel("0"); } else { resultDataLabel[i][j] = new JLabel("0.00%"); } resultDataLabel[i][j].setPreferredSize(new Dimension(83, 40)); panelRight.add(resultTagLabel[i][j]); panelRight.add(resultDataLabel[i][j]); } if (i == 0) { JLabel label = new JLabel("其中:"); label.setPreferredSize(new Dimension(500, 40)); panelRight.add(label); } } /* stepLabel1 = new JLabel(); stepLabel1.setVisible(false); stepLabel1.setPreferredSize(new Dimension(500, 40)); stepLabel2 = new JLabel(); stepLabel2.setVisible(false); stepLabel2.setPreferredSize(new Dimension(500, 40)); panelRight.add(stepLabel1); panelRight.add(stepLabel2); */ accessTypeTagLabel = new JLabel("访问类型:"); addressTagLabel = new JLabel("地址:"); blockNumberTagLabel = new JLabel("块号:"); tagTagLabel = new JLabel("标记Tag:"); indexTagLabel = new JLabel("组索引:"); inblockAddressTagLabel = new JLabel("块内地址:"); hitTagLabel = new JLabel("命中情况:"); accessTypeDataLabel = new JLabel("--"); addressDataLabel = new JLabel("--"); blockNumberDataLabel = new JLabel("--"); tagDataLabel = new JLabel("--"); indexDataLabel = new JLabel("--"); inblockAddressDataLabel = new JLabel("--"); hitDataLabel = new JLabel("--"); accessTypeTagLabel.setPreferredSize(new Dimension(80, 40)); accessTypeDataLabel.setPreferredSize(new Dimension(80, 40)); addressTagLabel.setPreferredSize(new Dimension(80, 40)); addressDataLabel.setPreferredSize(new Dimension(200, 40)); panelRight.add(accessTypeTagLabel); panelRight.add(accessTypeDataLabel); panelRight.add(addressTagLabel); panelRight.add(addressDataLabel); blockNumberTagLabel.setPreferredSize(new Dimension(80, 40)); blockNumberDataLabel.setPreferredSize(new Dimension(200, 40)); hitTagLabel.setPreferredSize(new Dimension(80, 40)); hitDataLabel.setPreferredSize(new Dimension(80, 40)); panelRight.add(blockNumberTagLabel); panelRight.add(blockNumberDataLabel); panelRight.add(hitTagLabel); panelRight.add(hitDataLabel); tagTagLabel.setPreferredSize(new Dimension(60, 40)); tagDataLabel.setPreferredSize(new Dimension(70, 40)); indexTagLabel.setPreferredSize(new Dimension(60, 40)); indexDataLabel.setPreferredSize(new Dimension(70, 40)); inblockAddressTagLabel.setPreferredSize(new Dimension(60, 40)); inblockAddressDataLabel.setPreferredSize(new Dimension(100, 40)); panelRight.add(tagTagLabel); panelRight.add(tagDataLabel); panelRight.add(indexTagLabel); panelRight.add(indexDataLabel); panelRight.add(inblockAddressTagLabel); panelRight.add(inblockAddressDataLabel); //*****************************底部面板绘制*****************************************// bottomLabel = new JLabel("执行控制"); bottomLabel.setPreferredSize(new Dimension(800, 30)); execStepBtn = new JButton("步进"); execStepBtn.setLocation(100, 30); execStepBtn.addActionListener(this); execAllBtn = new JButton("执行到底"); execAllBtn.setLocation(300, 30); execAllBtn.addActionListener(this); panelBottom.add(bottomLabel); panelBottom.add(execStepBtn); panelBottom.add(execAllBtn); add("North", panelTop); add("West", panelLeft); add("Center", panelRight); add("South", panelBottom); setSize(820, 620); setVisible(true); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } public static void main(String[] args) { new MyCacheSim(); }}</string></string></string></string></string></string></string></string></string></string></string>

Java Cache模拟器(图形界面) -电脑资料

手机扫码分享

Top