炎寒

恒,厚,勤,学,俭 做一个厚道的普通人。

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

经过三次重写,和合计30多个小时的开发,终于把这个简单的逻辑做完了。(自己太笨)

因为刚刚接触C,写的代码实现方式肯定有不对的地方,逻辑上可能也有疏漏,如果有看官发现问题还望及时给予指正,谢谢。

 

一、整体概括:

1.1目标:

维护一个单独的缓存空间,该空间是低一级存储的缓存。缓存的大小比低级存储的大小要小很多,通过一个逻辑将底层存储的数据抽到缓存中的一个位置。

1.2 实现思路:

  通过阅读《深入理解计算机系统》一书,了解低级存储与缓存之间关联规则是基于存储地址的,通过一个地址映射的规则,将低级存储的地址映射到缓存的制定位置。

  1.2.1 存储:

    存储是由一个个位构成的,每个位都有一个对应的地址,地址的大小取决于计算机的字长。

  1.2.2 低级存储:

    在这次的设计中低级存储只是一个抽象概念,实际上就是内存中的一块空间,只不过我通过映射值将低级存储的地址改为从F000开始的地址。

  1.2.3 缓存:

    缓存是比低级存储小得多的集合,因为存储越大寻址的时间越长,所以需要一个小的缓存来存储处理器近期使用到的数据。

    这次设计中的缓存也只是一个抽象概念,也是内存的一块空间,也是通过映射值将缓存的地址改为A000开始的地址。

  如何将低级存储的地址映射到缓存——缓存模型:

    缓存模型主要分——组、行、缓存单元

    1.2.3.1 组

      在逻辑上没有体现,知识对地址进行切割并划分了一个范围,是在映射逻辑上有关,在实际内存中不会存储。

    1.2.3.2 行

      也是一个逻辑体现,主要是为了更好的提升缓存的寻址效率而设置的思想。

    1.2.3.3 缓存单元:

      实际存储数据的对象,其中包含了标识、是否加载、以及字节块。

        标识:标识是地址的一部分根据规则截取出来的,通过地址另一部分找到对应的组以后就会对其中的行进行遍历,根据标识找到对应的行。

        是否加载:用来标识该缓存是否已经加载数据。

        字节块:用来存储缓存数据。(大小可设置)

      1.2.3.4 总结

      通过上述的几个对象,我们将缓存组织成了一个三层的结构,第一层是组、第二层是行、第三层是存储单元。一个缓存可以有S个组,可以有E个行,每行只能有一个缓存单元。

  1.2.4 全相连高速缓存、组相连高速缓存、直接映射高速缓存

    全相连高速缓存就是缓存中只有一个组,有E个行的方式实现。

    组相连高速缓存就是一个缓存中有S个组,E个行的实现方式。

    直接映射高速缓存就是一个缓存中有S个组,1个行和1个缓存单元的实现方式。

   1.2.5 缓存各项指标的设置:

    组数、行数、缓存数据块的大小的设置直接影响缓存的效率但也要根据实际情况,大小对不同的情况有不同的策略。

 

二、具体实现:

  2.1 公共常量:

    计算机字长:MemAddrLength

  2.2 几个核心对象:

    2.2.1 硬件控制器:HWController

      属性:

        存储空间大小

      1)写方法(Write):传入一个虚拟硬件地址(自己映射的,从F000开始)和一个长度。映射后写入数据到内存。

      2)读方法(Read):传入一个虚拟硬件地址和一个长度。映射后从内存读出数据,并写到一个新的内存空间并返回该指针。

    2.2.2 缓存控制器:CacheController

      1)缓存单元查询器(CacheFinder):

      2)读方法(Read):传入一个硬件虚拟地址和长度,在缓存中查找对应的单元,如果找不到从硬件中读取数据写到缓存,并将数据写到内存新的空间中、返回该指针。

      3)写方法(Write):传入一个硬件虚拟地址和长度,将数据写入到硬件中再写到缓存里(实际上缓存会有多种策略、直写/不直写等等)。

      4)取下一个(Next):将传入缓存单元指针移动到相邻的下一个缓存单元,如果超出缓存范围则返回0x00。

  2.3 执行结果概述

  返回四大部分:

  1)总体介绍部分,会将地址空间、缓存的S、E、B、t几个主要参数值显示出来。

  

  2)内存查看部分,会将初始化后虚拟硬件存储和缓存存储的值都写出来。

3)缓存大小显示

4)缓存读值测试

下面的集合是所有缓存单元的参数和右侧缓存单元字节块中的数据。

上面的集合是根据指令从缓存中读取出来的数据内容。

通过这两个集合可以验证读取数据是否正确。

 

 剩下没解决的问题:

在写缓存的时候,如果该组所有缓存单元都已经初始化了,就需要通过一个科学的方式选择一个块覆盖或驱逐,目前是用随机数,不太合理。

抽象不够,没有悟透和语言不熟导致很多复用问题比较多,有问题望指出。后续有时间我会继续完善。

说不定有BUG,如果有客观指正。

 

 

三、代码

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <math.h>
  4 #include <unistd.h>
  5 
  6 /*
  7  * 基本设定初始化
  8  */
  9 const unsigned int _memSize = 1024; //内存大小(字节)
 10 const unsigned int _memAddrLength = 16;//地址长度
 11 const unsigned int _cacheSize = 256;//缓存大小
 12 
 13 /*
 14  * 硬件控制器
 15  */
 16 typedef struct HWController{
 17     unsigned long _memStartAddr; //start addr 0XF0
 18     unsigned char* _memAddr;
 19     unsigned long _memOffset;
 20 
 21     unsigned char* (*Read)(unsigned long memOffset, unsigned long addr, unsigned long length);
 22     unsigned char (*Write)(unsigned long memOffset, unsigned long addr, unsigned char *data, unsigned long length);
 23 };
 24 
 25 /*
 26  * 缓存控制器:
 27  *      1)缓存单元集合指针 CacheUnitArrayPtr
 28  *      2)缓存查询函数 CacheFinder
 29  *      3)缓存读函数 Read
 30  *      4)缓存写函数 Write
 31  */
 32 typedef struct CacheController {
 33     unsigned int _s;
 34     unsigned long _sMask;
 35     unsigned int _S;
 36     unsigned int _E;
 37     unsigned int _b;
 38     unsigned long _bMask;
 39     unsigned int _B;
 40     unsigned int _t;
 41     unsigned long _tMask;
 42     unsigned int _C;
 43 
 44     unsigned long _unitCount;
 45     unsigned long _unitSize;
 46 
 47     unsigned long _cacheSize;
 48     unsigned long _cacheStartAddr;
 49     unsigned char* _cacheMemAddr;
 50     unsigned long _cacheOffset;
 51     struct CacheUnit* CacheUnitArrayPtr;
 52 
 53     struct CacheUnit* (*Next)(struct CacheController *ctrl,struct CacheUnit *unit);
 54     struct CacheUnit* (*CacheFinder)(struct CacheController *ctrl,unsigned long Addr);
 55     unsigned char* (*Read)(struct CacheController *ctrl,struct HWController *hwctrl,unsigned long addr, unsigned long length);
 56     unsigned char (*Write)(struct CacheController *ctrl,struct HWController *hwctrl,unsigned long addr, unsigned char *data, unsigned long length);
 57 };
 58 
 59 /*
 60  * 缓存单元
 61  *      1)数据块集合指针 BlockArrayPtr;
 62  *      2)t标志位 tCode;
 63  *      3)热标识位 hot;
 64  */
 65 typedef struct CacheUnit {
 66     unsigned char* BlockArrayPtr;
 67     unsigned long tCode;
 68     unsigned char Hot;
 69 };
 70 
 71 //HWController
 72 unsigned char _hwWrite(unsigned long memOffset, unsigned long addr, unsigned char *data, unsigned long length){
 73     unsigned char* ptr = (unsigned char*)(memOffset + addr);
 74     while(length--){
 75         *ptr = *data;
 76         ptr++;
 77         data++;
 78     }
 79     return 1;
 80 }
 81 unsigned char* _hwRead(unsigned long memOffset, unsigned long addr, unsigned long length){
 82     unsigned char *ptr = (unsigned char*)(memOffset + addr);
 83     unsigned char *retPtr = malloc(length);
 84     unsigned char *loopPtr = retPtr;
 85     while(length--){
 86         *loopPtr = *ptr;
 87         ptr++;
 88         loopPtr++;
 89     }
 90 
 91     return retPtr;
 92 }
 93 struct HWController* GetHWCtroller(){
 94     struct HWController *ctrl = malloc(sizeof(struct HWController));
 95     void *rPtr = malloc(_memSize);//get ptr point to Memory Space.
 96     (*ctrl)._memStartAddr = 0xF000;
 97     (*ctrl)._memOffset = (unsigned long) (rPtr - (*ctrl)._memStartAddr);
 98     (*ctrl)._memAddr = rPtr;
 99     (*ctrl).Write = _hwWrite;
100     (*ctrl).Read = _hwRead;
101 
102     unsigned char *ptr = rPtr;
103     int i = 0;
104     while( i < _memSize ){
105         *ptr = i + 1000;
106         ptr++;
107         i++;
108     }
109 
110     printf("==>Memory:\r\n startAddr:%X,offset:%X",(unsigned int)(*ctrl)._memStartAddr,(unsigned int)((*ctrl)._memOffset ));
111 
112     return ctrl;
113 }
114 
115 //CacheController
116 struct CacheUnit* _next(struct CacheController *ctrl,struct CacheUnit *unit){
117    unit = (struct CacheUnit *)((unsigned long)unit + ctrl->_unitSize);
118    return unit >= (ctrl->_cacheSize + ctrl->_cacheMemAddr) ? 0x00 : unit;
119 }
120 struct CacheUnit* _cacheFinder(struct CacheController *ctrl,unsigned long addr){
121     unsigned long _tBit = (addr&(*ctrl)._tMask)>>((*ctrl)._b+(*ctrl)._s);
122     unsigned long _sBit = (addr&(*ctrl)._sMask)>>((*ctrl)._b);
123     unsigned long _bBit = (addr&(*ctrl)._bMask);
124 
125 //    printf("\r\n\r\n====>Find Addr:%X \r\n tMask:%X,tVal:%X \t sMask:%X,sVal:%X \t bMask:%X,bVal:%X",addr,(*ctrl)._tMask,_tBit,(*ctrl)._sMask,_sBit,(*ctrl)._bMask,_bBit);
126 
127     struct CacheUnit* _unit = (struct CacheUnit*)((*ctrl)._cacheStartAddr + ctrl->_cacheOffset + _sBit * ((*ctrl)._E * ctrl->_unitSize));
128     int e = (*ctrl)._E;
129     while ( e-- )
130     {
131         if((*_unit).tCode == _tBit){
132             return _unit;
133         }
134         _unit = (struct CacheUnit *)(((unsigned long)_unit)+ ctrl->_unitSize);
135     }
136     return 0;
137 }
138 unsigned char* _cacheRead(struct CacheController *ctrl,struct HWController *hwctrl,unsigned long addr, unsigned long length){
139     struct CacheUnit *unit = ctrl->CacheFinder(ctrl,addr);
140     //todo: 找时间把Loader抽象出来或者其他方式优化复用。
141     if(!unit || !(*unit).Hot){
142         unsigned char *read = hwctrl->Read(hwctrl->_memOffset,addr,length);
143         ctrl->Write(ctrl,hwctrl,addr,read,length);
144         unit = ctrl->CacheFinder(ctrl,addr);
145         if(!unit || !(*unit).Hot){
146             printf("\r\nERROR::can not load cache by %X !!!! \r\n" ,(unsigned int)addr);
147             exit(0);
148         }
149     }
150     unsigned char *memPtr = malloc(length);
151     unsigned char *memLoopPtr = memPtr;
152     unsigned char *blockPtr = (*unit).BlockArrayPtr + (ctrl->_bMask & addr);
153     unsigned long i = 0;
154     while(i < length){
155         *memLoopPtr = *blockPtr;
156         memLoopPtr++;
157         blockPtr++;
158         if(blockPtr >= (*unit).BlockArrayPtr + (*ctrl)._B){
159             unit = ctrl->CacheFinder(ctrl,addr + i + 1);
160             if(!unit || !(*unit).Hot){
161                     printf("\r\nERROR::can not load cache by %X !!!! \r\n" ,(unsigned int)(addr + i));
162                     exit(0);
163             }
164             blockPtr = unit->BlockArrayPtr;
165         }
166         i++;
167     }
168     return memPtr;
169 }
170 unsigned char _cacheWrite(struct CacheController *ctrl,struct HWController *hwctrl,unsigned long addr, unsigned char *data, unsigned long length){
171     //写入底层内存先。
172     hwctrl->Write(hwctrl->_memOffset,addr,data,length);
173     //写入缓存
174     unsigned char *ptr = data;
175     unsigned long i = 0;
176 
177     while(i<length){
178         struct CacheUnit *unit = ctrl->CacheFinder(ctrl,addr + i);
179         if(!unit||!unit->Hot)
180         {
181             unsigned long startAddr = (unsigned long)(ctrl->_cacheMemAddr + (((ctrl->_sMask & (addr + i)) >> ((*ctrl)._b)) * ctrl->_E) * ctrl->_unitSize) ;
182             unsigned long endAddr = (unsigned long)(ctrl->_cacheMemAddr + (((ctrl->_sMask & (addr + i)) >> ((*ctrl)._b)) * ctrl->_E)) + ctrl->_E * ctrl->_unitSize;
183             unit = (struct CacheUnit *)startAddr;
184             int hit = 0;
185             while(unit){
186                 if(!unit->Hot)
187                 {
188                     hit=1;
189                     break;
190                 }
191                 unit = ctrl->Next(ctrl,unit);
192                 if((unsigned long)unit >= endAddr){
193                     break;
194                 }
195             }
196             if(!hit)
197             {
198                 printf("\r\rnhit!!!\r\n");
199                int rm = rand() % ( ctrl->_E );
200                unit = startAddr + rm * ctrl->_unitSize;
201             }
202             unit->tCode = ((addr + i) & ctrl->_tMask) >> ((*ctrl)._b+(*ctrl)._s);
203             unit->Hot = 1;
204         }
205         unsigned char *blockPtr = unit->BlockArrayPtr + ((addr+i)&ctrl->_bMask);
206         *blockPtr = *ptr;
207         ptr++;
208         i++;
209     }
210 }
211 struct CacheController* GetCacheController(unsigned int _memAddrLength, unsigned int cacheSize, unsigned int blockSize,unsigned int E){
212     struct CacheController *cache = malloc(sizeof(struct CacheController));
213     (*cache)._b = (unsigned int)log2(blockSize);
214     (*cache)._B = blockSize;
215     (*cache)._bMask = (unsigned long) pow(2,(*cache)._b) - 1;
216 
217     (*cache)._E = E;
218 
219     (*cache)._S = cacheSize / (*cache)._B / (*cache)._E;
220     (*cache)._s = (unsigned int)log2((*cache)._S);
221     (*cache)._sMask = (unsigned long) pow(2,((*cache)._b + (*cache)._s)) - (*cache)._bMask - 1;
222 
223     (*cache)._C = (*cache)._B * (*cache)._E * (*cache)._S;
224 
225     (*cache)._t = _memAddrLength - (*cache)._s - (*cache)._b;
226     (*cache)._tMask = (unsigned long) pow(2,_memAddrLength) - (*cache)._bMask - (*cache)._sMask - 1;
227 
228     (*cache)._unitCount = (*cache)._E * (*cache)._S;
229     (*cache)._unitSize = sizeof(struct CacheUnit) + (*cache)._B;
230 
231     (*cache)._cacheSize = (*cache)._unitSize * (*cache)._unitCount;
232     //apply mem
233     (*cache)._cacheMemAddr = malloc((*cache)._cacheSize);
234     (*cache)._cacheStartAddr = 0xA000;
235     (*cache)._cacheOffset = (unsigned long)((*cache)._cacheMemAddr - cache->_cacheStartAddr);
236 
237     unsigned long counter = (*cache)._unitCount;
238     struct CacheUnit *unit = (struct CacheUnit*)(*cache)._cacheMemAddr;
239 
240     while(counter){
241         (*unit).Hot = 0x00;
242         (*unit).tCode = counter;
243         (*unit).BlockArrayPtr = (unsigned char *)(((unsigned long)unit) + sizeof(struct CacheUnit));
244         int x;
245         for(x = 0;x < cache->_B ; x++){
246             *(unit->BlockArrayPtr + x) = (unsigned char)x;
247         }
248         unit = (struct CacheUnit*)((*unit).BlockArrayPtr + (*cache)._B);
249         counter--;
250     }
251     (*cache).Next = _next;
252     (*cache).CacheFinder = _cacheFinder;
253     (*cache).Read = _cacheRead;
254     (*cache).Write = _cacheWrite;
255 
256     printf("\r\n==>CacheSize:\r\n MemAddrLength = %d. C = %d, \r\nS = %d, E = %d, B = %d; \r\n s = %d, b = %d, t = %d",_memAddrLength,(*cache)._C,(*cache)._S,(*cache)._E,(*cache)._B,(*cache)._s,(*cache)._b,(*cache)._t);
257     printf("\r\ncacheAddr:%X,cacheStartAddr:%X, cacheOffset:%X, cacheSize:%d",(unsigned int)(*cache)._cacheMemAddr,(unsigned int)(*cache)._cacheStartAddr,(unsigned int)(*cache)._cacheOffset,(unsigned int) (*cache)._cacheSize);
258     printf("\r\nbMask:%x,sMask:%x,tMask:%x",(unsigned int)(*cache)._bMask,(unsigned int)(*cache)._sMask,(unsigned int)(*cache)._tMask);
259 
260     return cache;
261 }
262 
263 //utility
264 void PrintMem(char* title, unsigned long addr, unsigned long length,int split){
265     printf("\r\n\r\n=====> title::%s::  Printing Mem %X,Length:%d  <=======\r\n",title,(unsigned int)addr,(unsigned int)length);
266     unsigned char *ptr = (unsigned char *)addr;
267 
268     int i = 0;
269     while(i < length){
270         if( i % 16 == 0){
271             printf("\r\n%d\t%X\t",i,(unsigned int)ptr);
272         }
273         else if( i > 0 && i % 4 == 0){
274             printf("\t");
275         }
276         printf("\t%X",*ptr);
277         ptr++;
278         i++;
279     }
280 }
281 void PrintCache(char* title, struct CacheController* ctrl){
282     printf("\r\n\r\n=====> title::%s::  Printing Mem %X,Length:%d  <=======\r\n",title,(unsigned int)(ctrl->_cacheStartAddr + ctrl->_cacheOffset),(unsigned int)ctrl->_unitCount);
283 
284     struct CacheUnit *unit = ( struct CacheUnit *)(ctrl->_cacheStartAddr + ctrl->_cacheOffset);
285     unsigned char *blockPtr = unit->BlockArrayPtr;
286     int i = 0;
287     int j = 0;
288     while(i < ctrl->_unitCount){
289         printf("\r\n--Unit%d[[tCode:%d,BlockPtr:%X,Hot:%d]] Blocks:\t",i+1,(unsigned int)unit->tCode,(unsigned int)unit->BlockArrayPtr,(unsigned int)unit->Hot);
290         j = 0;
291         while(j < ctrl->_B){
292             printf("\t%X",(unsigned int)*blockPtr);
293             blockPtr++;
294             j++;
295         }
296         unit = (struct CacheUnit *)(((unsigned long)unit) + sizeof(struct CacheUnit) + ctrl->_B);
297         blockPtr = unit->BlockArrayPtr;
298         i++;
299     }
300 }
301 int main() {
302     printf("Hello, World!\n");
303     struct HWController hwCtrl = *GetHWCtroller();
304     struct CacheController cacheCtrl = *GetCacheController(_memAddrLength,_cacheSize,32,2);
305 
306 //HW Unit Test
307     //    PrintMem("",(unsigned long)hwCtrl._memAddr,16,0);
308     //    unsigned char temp = 0xAA;
309     //    unsigned char *data = &temp;
310     //    hwCtrl.Write(hwCtrl._memOffset,0XF002,data,1);
311     //    PrintMem(" HWMEM 0~16 ",(unsigned long)hwCtrl._memAddr,16,0);
312     //    unsigned char *retData = hwCtrl.Read(hwCtrl._memOffset,0XF002,1);
313     //    PrintMem(" HWMEM 0XF002 ",(unsigned long)retData,1,0);
314     //    unsigned char *retData = hwCtrl.Read(hwCtrl._memOffset,0XF002,1);
315     PrintMem(" HWMEM ALL ",(unsigned long)hwCtrl._memAddr,_memSize,0);
316 
317 
318     //Cache Unit Test
319     PrintMem(" CACHE ALL ",(unsigned long)cacheCtrl._cacheMemAddr,cacheCtrl._cacheSize,0);
320 
321 
322     //struct test
323     struct CacheUnit cu = {
324             0x00,
325             0x00,
326             0x00
327     };
328     printf("\r\n ============>> CacheUnitTypeSize %d \r\n",sizeof(struct CacheUnit));
329     printf("\r\n ============>> CacheUnitSize %d \r\n",sizeof(cu));
330     printf("\r\n ============>> CacheUnitSize.Hot %d \r\n",sizeof(cu.Hot));
331     printf("\r\n ============>> CacheUnitSize.tCode %d \r\n",sizeof(cu.tCode));
332     printf("\r\n ============>> CacheUnitSize ptr %d \r\n",sizeof(cu.BlockArrayPtr));
333 
334     //ReadCacheTest
335     PrintMem("",cacheCtrl.Read(&cacheCtrl,&hwCtrl,0XF038,16),16,0);
336     PrintCache("",&cacheCtrl);
337     return 0;
338 }

 

posted on 2018-08-19 21:58  炎寒  阅读(956)  评论(0编辑  收藏  举报