ucisc 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/.travis.yml +6 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +14 -0
- data/Gemfile.lock +52 -0
- data/LICENSE.txt +21 -0
- data/README.md +217 -0
- data/Rakefile +10 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/examples/factorial.ucisc +58 -0
- data/examples/fib.ucisc +74 -0
- data/examples/hello_world.ucisc +96 -0
- data/examples/image.ucisc +543 -0
- data/exe/ucisc +25 -0
- data/lib/micro_cisc.rb +48 -0
- data/lib/micro_cisc/compile/compiler.rb +103 -0
- data/lib/micro_cisc/compile/instruction.rb +310 -0
- data/lib/micro_cisc/compile/label_generator.rb +48 -0
- data/lib/micro_cisc/compile/statement.rb +113 -0
- data/lib/micro_cisc/version.rb +3 -0
- data/lib/micro_cisc/vm/device.rb +140 -0
- data/lib/micro_cisc/vm/empty_device.rb +9 -0
- data/lib/micro_cisc/vm/processor.rb +447 -0
- data/lib/micro_cisc/vm/term_device.rb +35 -0
- data/lib/micro_cisc/vm/video.rb +151 -0
- data/ucisc.gemspec +28 -0
- data/ucisc.vim +54 -0
- metadata +74 -0
@@ -0,0 +1,35 @@
|
|
1
|
+
module MicroCisc
|
2
|
+
module Vm
|
3
|
+
class TermDevice < Device
|
4
|
+
def initialize(device_id)
|
5
|
+
super(device_id, 9, 1)
|
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
|
13
|
+
end
|
14
|
+
|
15
|
+
def handle_control_read(address)
|
16
|
+
case(address)
|
17
|
+
when 7
|
18
|
+
@control_mem[7] = TTY::Screen.width
|
19
|
+
when 8
|
20
|
+
@control_mem[8] = TTY::Screen.height
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def handle_control_update(address, value)
|
25
|
+
if address == 5
|
26
|
+
# value is number of bytes to send
|
27
|
+
words = (value + 1) / 2
|
28
|
+
string = @local_mem[0][0...words].pack("S>*")[0...value]
|
29
|
+
$stdout.write(string)
|
30
|
+
$stdout.flush
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,151 @@
|
|
1
|
+
module MicroCisc
|
2
|
+
module Vm
|
3
|
+
class Video
|
4
|
+
attr_reader :config_page, :start_page, :page_count, :end_page
|
5
|
+
def initialize(proc_count, mem_size, rom, debug = false)
|
6
|
+
@bytes_per_pixel = 2
|
7
|
+
@w = 640
|
8
|
+
@h = 480
|
9
|
+
@refresh = 24
|
10
|
+
@page_count = (@w * @h * @bytes_per_pixel + 511) / 512
|
11
|
+
@enabled = 1
|
12
|
+
|
13
|
+
# Initialize the control section of main memory
|
14
|
+
config_mem = [@enabled, @w, @h, @bytes_per_pixel, @refresh]
|
15
|
+
config_mem = config_mem + Array.new(256 - config_mem.size).map { 0 }
|
16
|
+
@config_page = 16
|
17
|
+
@start_page = 17
|
18
|
+
@end_page = @config_page + @page_count
|
19
|
+
|
20
|
+
@reader, @writer = IO.pipe
|
21
|
+
|
22
|
+
fork do
|
23
|
+
@reader.close
|
24
|
+
system = System.new(proc_count, mem_size, rom, self, debug)
|
25
|
+
system.write_page(@config_page, config_mem)
|
26
|
+
system.run
|
27
|
+
end
|
28
|
+
|
29
|
+
@writer.close
|
30
|
+
# Initialize the video memory space
|
31
|
+
@memory = [config_mem] + Array.new(@page_count).map { Array.new(256).map { 0 } }
|
32
|
+
launch
|
33
|
+
end
|
34
|
+
|
35
|
+
def send_page_update(main_page, data)
|
36
|
+
msg = Message.new
|
37
|
+
msg.write(main_page, main_page - @config_page, data)
|
38
|
+
msg.write_to_stream(@writer)
|
39
|
+
end
|
40
|
+
|
41
|
+
def launch
|
42
|
+
require 'gtk2'
|
43
|
+
|
44
|
+
Gtk.init
|
45
|
+
|
46
|
+
@image_data = Array.new(@w * @h * 3).map { 0 }
|
47
|
+
pixel_buffer = GdkPixbuf::Pixbuf.new(
|
48
|
+
data: @image_data.pack("C*"),
|
49
|
+
colorspace: GdkPixbuf::Colorspace::RGB,
|
50
|
+
has_alpha: false,
|
51
|
+
bits_per_sample: 8,
|
52
|
+
width: 640,
|
53
|
+
height: 480
|
54
|
+
)
|
55
|
+
@image = Gtk::Image.new(pixel_buffer)
|
56
|
+
|
57
|
+
@window = Gtk::Window.new.set_default_size(640, 480)
|
58
|
+
@window.set_title("uCISC Virtual Machine")
|
59
|
+
@window.set_resizable(false)
|
60
|
+
@window.add(@image)
|
61
|
+
@image.show
|
62
|
+
@window.signal_connect("destroy") do
|
63
|
+
Gtk.main_quit
|
64
|
+
end
|
65
|
+
GLib::Timeout.add(15) do
|
66
|
+
do_update
|
67
|
+
true
|
68
|
+
end
|
69
|
+
@window.show
|
70
|
+
|
71
|
+
Gtk.main
|
72
|
+
end
|
73
|
+
|
74
|
+
def do_update
|
75
|
+
@t0 ||= Time.now
|
76
|
+
@tcount ||= 0
|
77
|
+
changed = false
|
78
|
+
|
79
|
+
while(@reader.ready?) do
|
80
|
+
msg = Message.read_from_stream(@reader)
|
81
|
+
if msg.write?
|
82
|
+
changed = true
|
83
|
+
page = msg.local_page
|
84
|
+
data = msg.data
|
85
|
+
data = data[0...256] if data.size > 256
|
86
|
+
@memory[page] = data
|
87
|
+
|
88
|
+
if msg.local_page == 0
|
89
|
+
@config_page = data
|
90
|
+
@enabled, @w, @h, @bytes_per_pixel, @refresh = @config_page[0...4]
|
91
|
+
@window.resize(@w, @h)
|
92
|
+
else
|
93
|
+
update_page(page)
|
94
|
+
end
|
95
|
+
else
|
96
|
+
exit(0)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
if changed
|
101
|
+
pixel_buffer = GdkPixbuf::Pixbuf.new(
|
102
|
+
data: @image_data.pack("C*"),
|
103
|
+
colorspace: GdkPixbuf::Colorspace::RGB,
|
104
|
+
has_alpha: false,
|
105
|
+
bits_per_sample: 8,
|
106
|
+
width: 640,
|
107
|
+
height: 480
|
108
|
+
)
|
109
|
+
new_image = Gtk::Image.new(pixel_buffer)
|
110
|
+
@window.remove(@image)
|
111
|
+
@window.add(new_image)
|
112
|
+
new_image.show
|
113
|
+
@window.show
|
114
|
+
@image = new_image
|
115
|
+
end
|
116
|
+
|
117
|
+
@tcount += 1
|
118
|
+
if @tcount == 60
|
119
|
+
delta = Time.now - @t0
|
120
|
+
#puts "60 frames in #{delta}s (#{60 / delta} fps)"
|
121
|
+
@t0 = Time.now
|
122
|
+
@tcount = 0
|
123
|
+
end
|
124
|
+
rescue Interrupt
|
125
|
+
end
|
126
|
+
|
127
|
+
def update_page(page)
|
128
|
+
word_offset = (page - 1) * 256
|
129
|
+
finish = word_offset + 256
|
130
|
+
row_words = @bytes_per_pixel * @w / 2
|
131
|
+
pixel_x = word_offset % row_words
|
132
|
+
pixel_y = (word_offset / row_words)
|
133
|
+
|
134
|
+
while word_offset < finish
|
135
|
+
word = @memory[page][word_offset % 256]
|
136
|
+
pixel_offset = (pixel_y * @w + pixel_x) * 3
|
137
|
+
@image_data[pixel_offset] = ((word & 0xF800) >> 8) + 7
|
138
|
+
@image_data[pixel_offset + 1] = ((word & 0x07E0) >> 3) + 3
|
139
|
+
@image_data[pixel_offset + 2] = ((word & 0x001F) << 3) + 7
|
140
|
+
|
141
|
+
word_offset += 1
|
142
|
+
pixel_x += 1
|
143
|
+
if pixel_x % @w == 0
|
144
|
+
pixel_x = 0
|
145
|
+
pixel_y += 1
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
data/ucisc.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require_relative 'lib/micro_cisc/version'
|
2
|
+
|
3
|
+
Gem::Specification.new do |spec|
|
4
|
+
spec.name = "ucisc"
|
5
|
+
spec.version = MicroCisc::VERSION
|
6
|
+
spec.authors = ["Robert Butler"]
|
7
|
+
spec.email = ["robert at grokthiscommunity.net"]
|
8
|
+
|
9
|
+
spec.summary = %q{Micro instruction set vm & compiler for hobbyist computing}
|
10
|
+
spec.homepage = "https://github.com/grokthis/ucisc-ruby"
|
11
|
+
spec.license = "MIT"
|
12
|
+
spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
|
13
|
+
|
14
|
+
#spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
|
15
|
+
|
16
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
17
|
+
spec.metadata["source_code_uri"] = "https://github.com/grokthis/ucisc-ruby"
|
18
|
+
#spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."
|
19
|
+
|
20
|
+
# Specify which files should be added to the gem when it is released.
|
21
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
22
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
23
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
24
|
+
end
|
25
|
+
spec.bindir = "exe"
|
26
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
27
|
+
spec.require_paths = ["lib"]
|
28
|
+
end
|
data/ucisc.vim
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
" uCISC syntax file
|
2
|
+
" Language: uCISC
|
3
|
+
" URL: https://github.com/grokthis/ucisc-ruby
|
4
|
+
" License: MIT
|
5
|
+
"
|
6
|
+
" Copy this into your ftplugin directory, and add the following to your vimrc
|
7
|
+
" or to .vim/ftdetect/ucisc.vim:
|
8
|
+
" autocmd BufReadPost,BufNewFile *.ucisc set filetype=ucisc
|
9
|
+
|
10
|
+
let s:save_cpo = &cpo
|
11
|
+
set cpo&vim
|
12
|
+
|
13
|
+
" setlocal iskeyword=@,48-57,?,!,_,$,-
|
14
|
+
setlocal formatoptions-=t " allow long lines
|
15
|
+
setlocal formatoptions+=c " but comments should still wrap
|
16
|
+
|
17
|
+
setlocal iskeyword+=-,?,<,>
|
18
|
+
|
19
|
+
syntax keyword uciscOpcode copy compute
|
20
|
+
highlight link uciscOpcode Function
|
21
|
+
|
22
|
+
syntax match uciscComment /#.*/
|
23
|
+
syntax match uciscComment /\/[^\/]*\//
|
24
|
+
syntax match uciscComment /'[^ ]*/
|
25
|
+
highlight link uciscComment Comment
|
26
|
+
|
27
|
+
syntax match uciscLabel /\([^a-zA-Z_:&@!]*\)\@=[a-zA-Z_:&@!][a-zA-Z0-9_:&@!]*:/
|
28
|
+
highlight link uciscLabel Identifier
|
29
|
+
|
30
|
+
syntax match uciscControl /[(){}]/
|
31
|
+
syntax match uciscControl /\(break\|loop\)/
|
32
|
+
highlight link uciscControl Statement
|
33
|
+
|
34
|
+
syntax match uciscImmediate /\<\((\)\?\(-\)\?\(0x\)\?[0-9a-fA-F]\+\([/.]\|\s\|,\)\@=/
|
35
|
+
highlight link uciscImmediate Number
|
36
|
+
|
37
|
+
syntax match uciscArg /\(\$\|&\)[a-zA-Z0-9_:&@!?*]\+/
|
38
|
+
highlight link uciscArg Type
|
39
|
+
|
40
|
+
syntax keyword uciscOption push pop as
|
41
|
+
syntax match uciscOption /\(.\)\@=\<\(disp\|imm\)\>\(\/\|\s\|,\|)\|$\)\@=/
|
42
|
+
syntax match uciscOption /\(.\)\@=\<\(reg\|mem\|val\)\>\(\/\|\s\|,\|)\|$\)\@=/
|
43
|
+
syntax match uciscOption /\(.\)\@=\<\(op\|inc\|eff\)\>\(\/\|\s\|$\)\@=/
|
44
|
+
highlight link uciscOption Define
|
45
|
+
|
46
|
+
syntax match uciscData /^[ ]*% *\([0-9a-fA-F][0-9a-fA-F][ ]*\)*/
|
47
|
+
highlight link uciscData Number
|
48
|
+
|
49
|
+
set comments-=:#
|
50
|
+
set comments+=n:#
|
51
|
+
syntax match subxCommentedCode "#? .*" | highlight link subxCommentedCode CommentedCode
|
52
|
+
let b:cmt_head = "#? "
|
53
|
+
|
54
|
+
let &cpo = s:save_cpo
|
metadata
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ucisc
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Robert Butler
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-07-05 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description:
|
14
|
+
email:
|
15
|
+
- robert at grokthiscommunity.net
|
16
|
+
executables:
|
17
|
+
- ucisc
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- ".gitignore"
|
22
|
+
- ".travis.yml"
|
23
|
+
- CODE_OF_CONDUCT.md
|
24
|
+
- Gemfile
|
25
|
+
- Gemfile.lock
|
26
|
+
- LICENSE.txt
|
27
|
+
- README.md
|
28
|
+
- Rakefile
|
29
|
+
- bin/console
|
30
|
+
- bin/setup
|
31
|
+
- examples/factorial.ucisc
|
32
|
+
- examples/fib.ucisc
|
33
|
+
- examples/hello_world.ucisc
|
34
|
+
- examples/image.ucisc
|
35
|
+
- exe/ucisc
|
36
|
+
- lib/micro_cisc.rb
|
37
|
+
- lib/micro_cisc/compile/compiler.rb
|
38
|
+
- lib/micro_cisc/compile/instruction.rb
|
39
|
+
- lib/micro_cisc/compile/label_generator.rb
|
40
|
+
- lib/micro_cisc/compile/statement.rb
|
41
|
+
- lib/micro_cisc/version.rb
|
42
|
+
- lib/micro_cisc/vm/device.rb
|
43
|
+
- lib/micro_cisc/vm/empty_device.rb
|
44
|
+
- lib/micro_cisc/vm/processor.rb
|
45
|
+
- lib/micro_cisc/vm/term_device.rb
|
46
|
+
- lib/micro_cisc/vm/video.rb
|
47
|
+
- ucisc.gemspec
|
48
|
+
- ucisc.vim
|
49
|
+
homepage: https://github.com/grokthis/ucisc-ruby
|
50
|
+
licenses:
|
51
|
+
- MIT
|
52
|
+
metadata:
|
53
|
+
homepage_uri: https://github.com/grokthis/ucisc-ruby
|
54
|
+
source_code_uri: https://github.com/grokthis/ucisc-ruby
|
55
|
+
post_install_message:
|
56
|
+
rdoc_options: []
|
57
|
+
require_paths:
|
58
|
+
- lib
|
59
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: 2.3.0
|
64
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
requirements: []
|
70
|
+
rubygems_version: 3.0.8
|
71
|
+
signing_key:
|
72
|
+
specification_version: 4
|
73
|
+
summary: Micro instruction set vm & compiler for hobbyist computing
|
74
|
+
test_files: []
|