-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmemory.py
executable file
·122 lines (113 loc) · 3.93 KB
/
memory.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
from ctypes import *
import logging
import sys
import math
class Memory:
def __init__(self,memsize=4096,binfile=None):
self.RAM=[0]*memsize
self.mem_size=memsize
if binfile!=None:
self.init_mem(binfile)
def read(self,address):
addr=address&((int(2**math.log2(self.mem_size*4))-1))
logging.debug(str(hex(address))+" "+str(hex(addr))+" "+str(hex(int(2**math.log2(self.mem_size*4)))))
addr=addr>>2
if(addr<self.mem_size):
return self.RAM[addr]
else:
logging.critical("MEMORY : Bus address out of range @ read : "+str(hex(addr&(2**32-1))) +" "+ str(hex(self.mem_size)))
sys.exit(1)
def init_mem(self,binfile):
file=open(binfile,"rb")
addr=0
while word:=file.read(4):
val=0
val|=word[0]
val|=word[1]<<8
val|=word[2]<<16
val|=word[3]<<24
self.RAM[addr]=val
addr+=1
def write(self,address,data,size):
addr=address&((int(2**math.log2(self.mem_size*4))-1))
logging.debug(str(hex(address))+" "+str(hex(addr))+" "+str(hex(int(2**math.log2(self.mem_size*4)))))
addr=addr>>2
if(addr<self.mem_size):
orig=self.RAM[addr]
logging.debug("Before write @ "+str(hex(address&(2**32-1)))+" => "+str(hex(orig&(2**32-1))))
if(size&1):
orig&=~(0x000000ff)
orig|=data&0x000000ff
if(size&2):
orig&=~(0x0000ff00)
orig|=data&0x0000ff00
if(size&4):
orig&=~(0x00ff0000)
orig|=data&0x00ff0000
if(size&8):
orig&=~(0xff000000)
orig|=data&0xff000000
self.RAM[addr]=orig
logging.debug("After write @ "+str(hex(address&(2**32-1)))+" => "+str(hex(self.RAM[addr]&(2**32-1))))
else:
logging.critical("MEMORY : Bus address out of range @ write : "+str(hex(addr&(2**32-1)))+" "+ str(hex(self.mem_size)))
sys.exit(1)
def dumpmem(self,address,len=0):
addr=address&((int(2**math.log2(self.mem_size*4))-1))
addr=address>>2
for i in range(addr-int(len/2),addr+int(len/2)+1):
if i>=0 and i<self.mem_size:
print("MEM[{}]={}".format(hex(i<<2),hex(self.RAM[i])))
#to run unit tests do pytest ./memory.py
def test_bram():
import random
bram=Memory(binfile="test.bin")
assert bram.RAM[0x00>>2] == 0x0040006f
assert bram.RAM[0xe8>>2] == 0x00000537
assert bram.RAM[0xc0>>2] == 0xfedff06f
#word read / writes
for i in range(0,100):
addr=random.randrange(0,4096)
val=random.randrange(0,0xffffffff)
bram.write(addr,val,15)
assert bram.read(addr) == val
val=0xaaaaaaaa
bram.write(addr,val,15)
assert bram.read(addr) == val
val=0x55555555
bram.write(addr,val,15)
assert bram.read(addr) == val
#byte read writes
for i in range(0,100):
addr=random.randrange(0,4096)
val=0xffffffff
bram.write(addr,val,15)
assert bram.read(addr) == val
size=random.choice([1,2,4,8])
val=0xaaaaaaaa
bram.write(addr,val,size)
val=bram.read(addr)
if(size==1):
assert val==0xffffffaa
elif(size==2):
assert val==0xffffaaff
elif(size==4):
assert val==0xffaaffff
else:
assert val==0xaaffffff
#half word read writes
for i in range(0,100):
addr=random.randrange(0,4096)
val=0xffffffff
bram.write(addr,val,15)
assert bram.read(addr) == val
size=random.choice([3,12])
val=0xaaaaaaaa
bram.write(addr,val,size)
val=bram.read(addr)
if(size==3):
assert val==0xffffaaaa
else:
assert val==0xaaaaffff
if __name__ == "__main__":
test_bram()