ucisc 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,3 @@
1
1
  module MicroCisc
2
- VERSION = "0.1.3"
2
+ VERSION = "0.1.4"
3
3
  end
@@ -0,0 +1,115 @@
1
+ require 'gtk2'
2
+
3
+ module MicroCisc
4
+ module Vm
5
+ class ColorLcdDisplay < Device
6
+ COLOR_MODE_12BIT = 1
7
+ COLOR_MODE_16BIT = 2
8
+ COLOR_MODES = [COLOR_MODE_16BIT, COLOR_MODE_12BIT].freeze
9
+
10
+ def initialize(device_id, mem_blocks, width, height, bit_mode)
11
+ super(device_id, Device::TYPE_BLOCK_MEMORY, mem_blocks)
12
+ @w = width
13
+ @h = height
14
+ @bit_mode = COLOR_MODES.include?(bit_mode) ? bit_mode : COLOR_MODES.first
15
+ @image_data = Array.new(@w * @h * 3).map { 0 }
16
+ @scale =
17
+ if @w <= 320
18
+ 4
19
+ elsif @w <= 640
20
+ 2
21
+ else
22
+ 1
23
+ end
24
+ @control_mem[6] = @w
25
+ @control_mem[7] = @h
26
+ @privileged_read = @privileged_read | 0x0C0
27
+
28
+ Gtk.init
29
+
30
+ @window = Gtk::Window.new.set_default_size(@w * @scale, @h * @scale)
31
+ @window.set_title("uCISC Virtual Machine")
32
+ @window.set_resizable(false)
33
+
34
+ update_screen
35
+
36
+ @window.signal_connect("destroy") do
37
+ Gtk.main_quit
38
+ end
39
+ GLib::Timeout.add(5) do
40
+ do_update
41
+ true
42
+ end
43
+ @window.show
44
+
45
+ @window_thread = Thread.new do
46
+ Gtk.main
47
+ end
48
+ end
49
+
50
+ def join
51
+ @window_thread.join
52
+ end
53
+
54
+ def update_screen
55
+ pixel_buffer = GdkPixbuf::Pixbuf.new(
56
+ data: @image_data.pack("C*"),
57
+ colorspace: GdkPixbuf::Colorspace::RGB,
58
+ has_alpha: false,
59
+ bits_per_sample: 8,
60
+ width: @w,
61
+ height: @h
62
+ )
63
+ pixel_buffer = pixel_buffer.scale_simple(@w * @scale, @h * @scale, 0)
64
+ new_image = Gtk::Image.new(pixel_buffer)
65
+ @window.remove(@image) if @image
66
+ @window.add(new_image)
67
+ new_image.show
68
+ @window.show
69
+ @image = new_image
70
+ end
71
+
72
+ def do_update
73
+ @t0 ||= Time.now
74
+ @tcount ||= 0
75
+
76
+ update_image_data
77
+ update_screen
78
+
79
+ @tcount += 1
80
+ if @tcount == 60
81
+ delta = Time.now - @t0
82
+ #puts "60 frames in #{delta}s (#{60 / delta} fps)"
83
+ @t0 = Time.now
84
+ @tcount = 0
85
+ end
86
+ rescue Interrupt
87
+ end
88
+
89
+ def update_image_data
90
+ (0...@w).each do |x|
91
+ (0...@h).each do |y|
92
+ word_offset = y * @w + x
93
+ pixel_offset = word_offset * 3
94
+ word = read_mem(@id, word_offset, true)
95
+ if (@bit_mode == COLOR_MODE_16BIT)
96
+ r = (word & 0x0F00) >> 8
97
+ @image_data[pixel_offset] = r + (r >> 5)
98
+ g = (word & 0x07E0) >> 3
99
+ @image_data[pixel_offset + 1] = g + (g >> 5)
100
+ b = (word & 0x001F) << 3
101
+ @image_data[pixel_offset + 2] = b + (b >> 5)
102
+ elsif (@bit_mode == COLOR_MODE_12BIT)
103
+ r = (word & 0x0F00) >> 4
104
+ @image_data[pixel_offset] = r + (r >> 4)
105
+ g = word & 0x00F0
106
+ @image_data[pixel_offset + 1] = g + (g >> 4)
107
+ b = (word & 0x000F) << 4
108
+ @image_data[pixel_offset + 2] = b + (b >> 4)
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
114
+ end
115
+ end
@@ -4,21 +4,30 @@ module MicroCisc
4
4
  #
5
5
  # From the docs, the control word layout is as follows:
6
6
  #
7
- # * 0x0 - Device ID, read only. Unique system wide.
8
- # * 0x1 - Bank address (MSB) | Device type (LSB)
9
- # * 0x2 - Bus access device ID
10
- # * 0x3 - Interrupt code (MSB) | Device status (LSB)
11
- # * 0x4 - Local register with interrupt handler address (read/write)
12
- # * 0x5 to 0xF - Device type specific
7
+ # * 0x0 - Device ID - read only. Unique system wide.
8
+ # * 0x1 - Local bank block (MSB) | Device type (LSB) - read only
9
+ # * 0x2 - Init device ID - read only if set, writable if 0 or by init device
10
+ # * 0x3 - Accessed device block address (LSB) - writable by init device
11
+ # * 0x4 - <Reserved> (MSB) | Device status (LSB)
12
+ # * 0x5 - Local register with interrupt handler address (read/write)
13
+ # * 0x6 to 0xF - Device type specific (see below)
13
14
  class Device
15
+ TYPE_INVALID = 0
16
+ TYPE_PROCESSOR = 1
17
+ TYPE_BLOCK_MEMORY = 2
18
+ TYPE_BLOCK_IO = 3
19
+ TYPE_SERIAL = 4
20
+ TYPE_HID = 5
21
+ TYPE_TERMINAL = 6
22
+
14
23
  attr_reader :id
15
24
 
16
25
  def initialize(id, type, local_blocks, rom_blocks = [])
17
26
  @id = id
18
- @external_read = 0x001F
19
- @privileged_read = 0x001F
20
- @privileged_write = 0x0010
21
- @internal_write = 0x000C
27
+ @external_read = 0x003F
28
+ @privileged_read = 0x003F
29
+ @privileged_write = 0x002C
30
+ @internal_write = 0x0010
22
31
 
23
32
  @local_blocks = local_blocks
24
33
  rom_blocks.each { |block| block.freeze }
@@ -31,6 +40,7 @@ module MicroCisc
31
40
  @control_mem = Array.new(16).map { 0 }
32
41
  @control_mem[0] = id
33
42
  @control_mem[1] = type & 0xFF
43
+ @control_mem[2] = 0
34
44
 
35
45
  @devices = [self]
36
46
  end
@@ -44,17 +54,16 @@ module MicroCisc
44
54
  @devices.each_with_index { |device, index| device.bank_index = index }
45
55
  end
46
56
 
47
- def source_halted(source_device_id)
48
- @control_mem[2] = 0 if source_device_id == @control_mem[2]
49
- end
50
-
51
57
  def write_control(source_device_id, address, value)
52
58
  address = address & 0xF
53
59
  return if address == 0
54
60
  if source_device_id == @id
55
61
  return if (1 << (address - 1)) & @internal_write == 0
56
62
  @control_mem[address] = value
57
- elsif source_device_id == @control_mem[2]
63
+ elsif @control_mem[2] == 0 || source_device_id == @control_mem[2]
64
+ # Special case where a processor can "claim" the device
65
+ @control_mem[2] = source_device_id
66
+
58
67
  return if (1 << (address - 1)) & @privileged_write == 0
59
68
  @control_mem[address] = value
60
69
  handle_control_update(address, value)
@@ -62,8 +71,10 @@ module MicroCisc
62
71
  end
63
72
 
64
73
  def read_control(source_device_id, address)
65
- return @control_mem[0] if address == 0
66
- if source_device_id == @id || source_device_id == @control_mem[2]
74
+ if address == 0
75
+ handle_control_read(address)
76
+ @control_mem[0]
77
+ elsif source_device_id == @id || source_device_id == @control_mem[2]
67
78
  return 0 if (1 << (address - 1)) & @privileged_read == 0
68
79
  handle_control_read(address)
69
80
  @control_mem[address]
@@ -106,11 +117,11 @@ module MicroCisc
106
117
  @local_mem[page][address & 0xFF] = value
107
118
  end
108
119
  elsif !banked && source_device_id == @id
109
- page = (address & 0xFF00) >> 8
110
- @local_mem[page][address & 0xFF] = value
120
+ block = (address & 0xFF00) >> 8
121
+ @local_mem[block][address & 0xFF] = value
111
122
  elsif source_device_id == @control_mem[2]
112
- page = (@control_mem[3] & 0xFF00) >> 8
113
- @local_mem[page][address & 0xFF] = value
123
+ block = @control_mem[3]
124
+ @local_mem[block][address & 0xFF] = value if @local_mem[block]
114
125
  end
115
126
  end
116
127
 
@@ -55,6 +55,7 @@ module MicroCisc
55
55
  @run = false
56
56
  @pc_modified = false
57
57
  @count = 0
58
+ @clocks_per_second = 200_000
58
59
  end
59
60
 
60
61
  def handle_control_update(address, value)
@@ -134,13 +135,13 @@ module MicroCisc
134
135
  def source_value(source, immediate)
135
136
  case source
136
137
  when 0
137
- @pc + immediate
138
+ (@pc + immediate) & 0xFFFF
138
139
  when 1,2,3
139
- read_mem(@id, @registers[source] + immediate)
140
+ read_mem(@id, (@registers[source] + immediate) & 0xFFFF)
140
141
  when 4
141
142
  immediate
142
143
  else
143
- @registers[source - 4] + immediate
144
+ (@registers[source - 4] + immediate) & 0xFFFF
144
145
  end
145
146
  end
146
147
 
@@ -149,7 +150,7 @@ module MicroCisc
149
150
  when 0
150
151
  @pc
151
152
  when 1,2,3
152
- read_mem(@id, @registers[destination] + immediate)
153
+ read_mem(@id, (@registers[destination] + immediate) & 0xFFFF)
153
154
  when 4
154
155
  @control
155
156
  else
@@ -177,7 +178,14 @@ module MicroCisc
177
178
  store_result(result, source, destination, immediates, push, 0)
178
179
 
179
180
  # Detect halt instruction
180
- return 1 if immediates.first == 0 && source == 0 && destination == 0
181
+ if immediates.first == 0 && source == 0 && destination == 0
182
+ if alu == 0
183
+ return 1
184
+ else
185
+ @pc += 1
186
+ return 2
187
+ end
188
+ end
181
189
  0
182
190
  end
183
191
 
@@ -347,9 +355,12 @@ module MicroCisc
347
355
  @pc += 1
348
356
  end
349
357
  @count += 1
350
- # if count & 0xFF == 0
351
- # read_from_processor
352
- # end
358
+
359
+ allowed_count = (Time.now - @t0) * @clocks_per_second
360
+ while @count >= allowed_count
361
+ sleep(1.0 / @clocks_per_second)
362
+ allowed_count = (Time.now - @t0) * @clocks_per_second
363
+ end
353
364
  end
354
365
  end
355
366
 
@@ -440,7 +451,7 @@ module MicroCisc
440
451
  ins = is_copy ? 'copy' : 'compute'
441
452
 
442
453
 
443
- "Stack: #{stack_string}\n#{ins} #{alu}#{src} #{imm0} #{dest} #{imm1}#{eff} #{push}# value: #{value} (0x#{'%04x' % value}), result: #{result} (0x#{'%04x' % result}), #{'not ' if !store}stored"
454
+ "Stack: #{stack_string}\n#{ins} #{alu}#{src} #{imm0} #{dest} #{imm1}#{eff} #{push}# value: #{value} (0x#{'%04x' % (value & 0xFFFF)}), result: #{result} (0x#{'%04x' % (result & 0xFFFF)}), #{'not ' if !store}stored"
444
455
  end
445
456
  end
446
457
  end
@@ -2,14 +2,10 @@ module MicroCisc
2
2
  module Vm
3
3
  class TermDevice < Device
4
4
  def initialize(device_id)
5
- super(device_id, 9, 1)
5
+ super(device_id, Device::TYPE_TERMINAL, 1)
6
6
  # Init device specific read/write controls
7
- @privileged_read = @privileged_read | 0xE0
8
- @privileged_write = @privileged_write | 0x20
9
- end
10
-
11
- def host_device=(device_id)
12
- @control_mem[2] = device_id
7
+ @privileged_read = @privileged_read | 0x1C0
8
+ @privileged_write = @privileged_write | 0x40
13
9
  end
14
10
 
15
11
  def handle_control_read(address)
@@ -22,7 +18,7 @@ module MicroCisc
22
18
  end
23
19
 
24
20
  def handle_control_update(address, value)
25
- if address == 5
21
+ if address == 6
26
22
  # value is number of bytes to send
27
23
  words = (value + 1) / 2
28
24
  string = @local_mem[0][0...words].pack("S>*")[0...value]
@@ -29,6 +29,8 @@ Gem::Specification.new do |spec|
29
29
  spec.add_runtime_dependency "byebug"
30
30
  spec.add_runtime_dependency "tty-screen"
31
31
  spec.add_runtime_dependency "gtk2"
32
+ spec.add_runtime_dependency "chunky_png"
33
+ spec.add_runtime_dependency "bundler"
32
34
 
33
35
  spec.add_development_dependency "rake"
34
36
  spec.add_development_dependency "minitest"
data/ucisc.vim CHANGED
@@ -14,19 +14,22 @@ set cpo&vim
14
14
  setlocal formatoptions-=t " allow long lines
15
15
  setlocal formatoptions+=c " but comments should still wrap
16
16
 
17
- setlocal iskeyword+=-,?,<,>
17
+ " setlocal iskeyword+=-,?,<,>
18
18
 
19
- syntax keyword uciscOpcode copy compute
20
- highlight link uciscOpcode Function
19
+ " syntax keyword uciscOpcode copy compute
20
+ " highlight link uciscOpcode Function
21
21
 
22
22
  syntax match uciscComment /#.*/
23
23
  syntax match uciscComment /\/[^\/]*\//
24
24
  syntax match uciscComment /'[^ ]*/
25
25
  highlight link uciscComment Comment
26
26
 
27
- syntax match uciscLabel /\([^a-zA-Z_:&@!]*\)\@=[a-zA-Z_:&@!][a-zA-Z0-9_:&@!]*:/
27
+ syntax match uciscLabel /&[a-zA-Z0-9_:&@!?]\+/
28
28
  highlight link uciscLabel Identifier
29
29
 
30
+ syntax match uciscFunction /\([^a-zA-Z_:&@!]*\)\@=[a-zA-Z_:&@!][a-zA-Z0-9_:&@!\.]*:/
31
+ highlight link uciscFunction Function
32
+
30
33
  syntax match uciscControl /[(){}]/
31
34
  syntax match uciscControl /\(break\|loop\)/
32
35
  highlight link uciscControl Statement
@@ -34,14 +37,17 @@ highlight link uciscControl Statement
34
37
  syntax match uciscImmediate /\<\((\)\?\(-\)\?\(0x\)\?[0-9a-fA-F]\+\([/.]\|\s\|,\)\@=/
35
38
  highlight link uciscImmediate Number
36
39
 
37
- syntax match uciscArg /\(\$\|&\)[a-zA-Z0-9_:&@!?*]\+/
38
- highlight link uciscArg Type
40
+ syntax match uciscArg /\$[a-zA-Z0-9_:&@!?]\+/
41
+ highlight link uciscArg Define
42
+
43
+ syntax match uciscAssign /=/
44
+ syntax keyword uciscAssign push pop as
45
+ highlight link uciscAssign Function
39
46
 
40
- syntax keyword uciscOption push pop as
41
47
  syntax match uciscOption /\(.\)\@=\<\(disp\|imm\)\>\(\/\|\s\|,\|)\|$\)\@=/
42
48
  syntax match uciscOption /\(.\)\@=\<\(reg\|mem\|val\)\>\(\/\|\s\|,\|)\|$\)\@=/
43
49
  syntax match uciscOption /\(.\)\@=\<\(op\|inc\|eff\)\>\(\/\|\s\|$\)\@=/
44
- highlight link uciscOption Define
50
+ highlight link uciscOption Comment
45
51
 
46
52
  syntax match uciscData /^[ ]*% *\([0-9a-fA-F][0-9a-fA-F][ ]*\)*/
47
53
  highlight link uciscData Number
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ucisc
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Butler
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-07-09 00:00:00.000000000 Z
11
+ date: 2020-07-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: byebug
@@ -52,6 +52,34 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: chunky_png
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: bundler
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
55
83
  - !ruby/object:Gem::Dependency
56
84
  name: rake
57
85
  requirement: !ruby/object:Gem::Requirement
@@ -84,6 +112,7 @@ description:
84
112
  email:
85
113
  - robert at grokthiscommunity.net
86
114
  executables:
115
+ - png_to_hex
87
116
  - ucisc
88
117
  extensions: []
89
118
  extra_rdoc_files: []
@@ -98,10 +127,13 @@ files:
98
127
  - Rakefile
99
128
  - bin/console
100
129
  - bin/setup
130
+ - core/stdlib.ucisc
131
+ - examples/everest_12bit.ucisc
101
132
  - examples/factorial.ucisc
102
133
  - examples/fib.ucisc
103
134
  - examples/hello_world.ucisc
104
- - examples/image.ucisc
135
+ - examples/paint_image.ucisc
136
+ - exe/png_to_hex
105
137
  - exe/ucisc
106
138
  - lib/micro_cisc.rb
107
139
  - lib/micro_cisc/compile/compiler.rb
@@ -109,11 +141,11 @@ files:
109
141
  - lib/micro_cisc/compile/label_generator.rb
110
142
  - lib/micro_cisc/compile/statement.rb
111
143
  - lib/micro_cisc/version.rb
144
+ - lib/micro_cisc/vm/color_lcd_display.rb
112
145
  - lib/micro_cisc/vm/device.rb
113
146
  - lib/micro_cisc/vm/empty_device.rb
114
147
  - lib/micro_cisc/vm/processor.rb
115
148
  - lib/micro_cisc/vm/term_device.rb
116
- - lib/micro_cisc/vm/video.rb
117
149
  - ucisc.gemspec
118
150
  - ucisc.vim
119
151
  homepage: https://github.com/grokthis/ucisc-ruby