Class: MicroCisc::Vm::Device
- Inherits:
-
Object
- Object
- MicroCisc::Vm::Device
show all
- Defined in:
- lib/micro_cisc/vm/device.rb
Overview
This is a generic device base class providing memory and control access
From the docs, the control word layout is as follows:
- 0x0 - Device ID - read only. Unique system wide.
- 0x1 - Local bank block (MSB) | Device type (LSB) - read only
- 0x2 - Init device ID - read only if set, writable if 0 or by init device
- 0x3 - Accessed device block address (LSB) - writable by init device
- 0x4 - (MSB) | Device status (LSB)
- 0x5 - Local register with interrupt handler address (read/write)
- 0x6 to 0xF - Device type specific (see below)
Constant Summary
collapse
- TYPE_INVALID =
0
- TYPE_PROCESSOR =
1
- TYPE_BLOCK_MEMORY =
2
- TYPE_BLOCK_IO =
3
- TYPE_SERIAL =
4
- TYPE_HID =
5
- TYPE_TERMINAL =
6
Instance Attribute Summary collapse
Instance Method Summary
collapse
-
#bank_index=(index) ⇒ Object
-
#banked?(address) ⇒ Boolean
-
#devices=(devices) ⇒ Object
-
#handle_control_read(address) ⇒ Object
-
#handle_control_update(address, value) ⇒ Object
-
#initialize(id, type, local_blocks, rom_blocks = []) ⇒ Device
constructor
A new instance of Device.
-
#read_control(source_device_id, address) ⇒ Object
-
#read_mem(source_device_id, address, force_local = false) ⇒ Object
-
#write_control(source_device_id, address, value) ⇒ Object
-
#write_mem(source_device_id, address, value) ⇒ Object
Constructor Details
#initialize(id, type, local_blocks, rom_blocks = []) ⇒ Device
Returns a new instance of Device.
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
# File 'lib/micro_cisc/vm/device.rb', line 25
def initialize(id, type, local_blocks, rom_blocks = [])
@id = id
@external_read = 0x003F
@privileged_read = 0x003F
@privileged_write = 0x002C
@internal_write = 0x0010
@local_blocks = local_blocks
rom_blocks.each { |block| block.freeze }
ram_blocks = Array.new(local_blocks - rom_blocks.size).map do
Array.new(256).map { 0 }
end
@local_mem = rom_blocks + ram_blocks
@control = 0
@control_mem = Array.new(16).map { 0 }
@control_mem[0] = id
@control_mem[1] = type & 0xFF
@control_mem[2] = 0
@devices = [self]
end
|
Instance Attribute Details
#id ⇒ Object
Returns the value of attribute id.
23
24
25
|
# File 'lib/micro_cisc/vm/device.rb', line 23
def id
@id
end
|
Instance Method Details
#bank_index=(index) ⇒ Object
48
49
50
|
# File 'lib/micro_cisc/vm/device.rb', line 48
def bank_index=(index)
@control_mem[1] = ((index & 0xFF) << 8) | (@control_mem[1] & 0xFF)
end
|
#banked?(address) ⇒ Boolean
96
97
98
99
100
101
102
103
104
|
# File 'lib/micro_cisc/vm/device.rb', line 96
def banked?(address)
banked = ((address & 0xF000) >> 12)
if banked == 0
banked = 1
else
banked = 1 << banked
end
(banked & @control) != 0
end
|
#devices=(devices) ⇒ Object
52
53
54
55
|
# File 'lib/micro_cisc/vm/device.rb', line 52
def devices=(devices)
@devices = [self] + devices
@devices.each_with_index { |device, index| device.bank_index = index }
end
|
#handle_control_read(address) ⇒ Object
88
89
90
|
# File 'lib/micro_cisc/vm/device.rb', line 88
def handle_control_read(address)
end
|
#handle_control_update(address, value) ⇒ Object
92
93
94
|
# File 'lib/micro_cisc/vm/device.rb', line 92
def handle_control_update(address, value)
end
|
#read_control(source_device_id, address) ⇒ Object
73
74
75
76
77
78
79
80
81
82
83
84
85
86
|
# File 'lib/micro_cisc/vm/device.rb', line 73
def read_control(source_device_id, address)
if address == 0
handle_control_read(address)
@control_mem[0]
elsif source_device_id == @id || source_device_id == @control_mem[2]
return 0 if (1 << (address - 1)) & @privileged_read == 0
handle_control_read(address)
@control_mem[address]
else
return 0 if (1 << (address - 1)) & @external_read == 0
handle_control_read(address)
@control_mem[address]
end
end
|
#read_mem(source_device_id, address, force_local = false) ⇒ Object
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
|
# File 'lib/micro_cisc/vm/device.rb', line 128
def read_mem(source_device_id, address, force_local = false)
banked = banked?(address) && !force_local
device = (address >> 4)
if banked && source_device_id == @id && device < @devices.size
@devices[device].read_control(source_device_id, address & 0xF)
elsif banked && source_device_id == @id && device >= 256
device = (address >> 8)
if device < @devices.size
@devices[device].read_mem(source_device_id, address & 0xFF)
else
page = (address & 0xFF00) >> 8
@local_mem[page][address & 0xFF]
end
elsif !banked && source_device_id == @id
page = (address & 0xFF00) >> 8
@local_mem[page][address & 0xFF]
elsif source_device_id == @control_mem[2]
page = @control_mem[3] & 0xFF00
@local_mem[page][address * 0xFF]
end
end
|
#write_control(source_device_id, address, value) ⇒ Object
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
|
# File 'lib/micro_cisc/vm/device.rb', line 57
def write_control(source_device_id, address, value)
address = address & 0xF
return if address == 0
if source_device_id == @id
return if (1 << (address - 1)) & @internal_write == 0
@control_mem[address] = value
elsif @control_mem[2] == 0 || source_device_id == @control_mem[2]
@control_mem[2] = source_device_id
return if (1 << (address - 1)) & @privileged_write == 0
@control_mem[address] = value
handle_control_update(address, value)
end
end
|
#write_mem(source_device_id, address, value) ⇒ Object
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
# File 'lib/micro_cisc/vm/device.rb', line 106
def write_mem(source_device_id, address, value)
banked = banked?(address)
device = (address >> 4)
if banked && source_device_id == @id && device < @devices.size
@devices[device].write_control(source_device_id, address & 0xF, value)
elsif banked && source_device_id == @id && device >= 256
device = (address >> 8)
if device < @devices.size
@devices[device].write_mem(source_device_id, address & 0xFF, value)
else
page = (address & 0xFF00) >> 8
@local_mem[page][address & 0xFF] = value
end
elsif !banked && source_device_id == @id
block = (address & 0xFF00) >> 8
@local_mem[block][address & 0xFF] = value
elsif source_device_id == @control_mem[2]
block = @control_mem[3]
@local_mem[block][address & 0xFF] = value if @local_mem[block]
end
end
|