-
Notifications
You must be signed in to change notification settings - Fork 11
/
memdev.rb
82 lines (75 loc) · 1.51 KB
/
memdev.rb
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
module MemDev
class TransactProxy
def initialize(mem, cache_reads)
@mem = mem
@writeset = {}
@readset = {} if cache_reads
end
def read(addr, opt={})
r = (opt[:count] || 1).times.map do |i|
iaddr = addr + i * 4
v = @writeset[iaddr]
v ||= (@readset[iaddr] ||= @mem[iaddr]) if @readset
v
end
if opt[:count]
r
else
r[0]
end
end
alias :[] :read
def write(addr, val, opt={})
if !val.respond.to? :each
val = [val]
end
val.each_with_index do |v, i|
@writeset[addr + i * 4] = v
end
end
alias :[]= :write
def commit!
writes = @writeset.sort_by{|k,v| k}
writes.each do |addr, val|
@mem[addr] = val
end
@writeset = nil
end
end
def read(addr, opt={})
ret = @mem.read(@baseaddr + addr, opt)
unless opt[:noswap]
ret = bswap(ret)
end
ret
end
alias :[] :read
def write(addr, val, opt = {})
unless opt[:noswap]
val = bswap(val)
end
@mem.write(@baseaddr + addr, val)
end
alias :[]= :write
def bswap(val)
if @devendian != @mem.endian
if val.respond_to? :each
d = val
else
d = [val]
end
d = d.pack('V*').unpack('N*')
if !val.respond_to? :each
d = d.first
end
d
else
val
end
end
def transact(cache_reads=false)
proxy = TransactProxy.new(self, cache_reads)
yield proxy
proxy.commit!
end
end