remian 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.
- data/.gitignore +5 -0
- data/.gitkeep +0 -0
- data/AUTHORS.md +2 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +18 -0
- data/LICENSE.md +24 -0
- data/README.md +5 -0
- data/bin/.gitkeep +0 -0
- data/bin/remian +44 -0
- data/lib/.gitkeep +0 -0
- data/lib/remian.rb +12 -0
- data/lib/remian/.gitkeep +0 -0
- data/lib/remian/clock.rb +14 -0
- data/lib/remian/control.rb +59 -0
- data/lib/remian/decoder.rb +10 -0
- data/lib/remian/instruction_set.rb +27 -0
- data/lib/remian/instruction_set/add_i.rb +9 -0
- data/lib/remian/instruction_set/and.rb +8 -0
- data/lib/remian/instruction_set/branch.rb +11 -0
- data/lib/remian/instruction_set/cp.rb +7 -0
- data/lib/remian/instruction_set/exit.rb +8 -0
- data/lib/remian/instruction_set/jump.rb +9 -0
- data/lib/remian/instruction_set/mv.rb +8 -0
- data/lib/remian/instruction_set/not.rb +7 -0
- data/lib/remian/instruction_set/or.rb +8 -0
- data/lib/remian/instruction_set/put.rb +7 -0
- data/lib/remian/instruction_set/put_a.rb +8 -0
- data/lib/remian/instruction_set/set.rb +7 -0
- data/lib/remian/instruction_set/zero.rb +8 -0
- data/lib/remian/memory.rb +35 -0
- metadata +109 -0
data/.gitkeep
ADDED
File without changes
|
data/AUTHORS.md
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
data/LICENSE.md
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
This is free and unencumbered software released into the public domain.
|
2
|
+
|
3
|
+
Anyone is free to copy, modify, publish, use, compile, sell, or
|
4
|
+
distribute this software, either in source code form or as a compiled
|
5
|
+
binary, for any purpose, commercial or non-commercial, and by any
|
6
|
+
means.
|
7
|
+
|
8
|
+
In jurisdictions that recognize copyright laws, the author or authors
|
9
|
+
of this software dedicate any and all copyright interest in the
|
10
|
+
software to the public domain. We make this dedication for the benefit
|
11
|
+
of the public at large and to the detriment of our heirs and
|
12
|
+
successors. We intend this dedication to be an overt act of
|
13
|
+
relinquishment in perpetuity of all present and future rights to this
|
14
|
+
software under copyright law.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
19
|
+
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
20
|
+
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
21
|
+
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
22
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
23
|
+
|
24
|
+
For more information, please refer to http://unlicense.org.
|
data/README.md
ADDED
@@ -0,0 +1,5 @@
|
|
1
|
+
# Remian
|
2
|
+
A baby virtual machine built in Ruby. Designed to a Von Neumann architecture and a RISC mindset.
|
3
|
+
|
4
|
+
## Why the name?
|
5
|
+
I decided to build Remian just after waking up, so it seemed apt to name it after a phase of sleeping. I picked [REM](http://en.wikipedia.org/wiki/Rapid_eye_movement_sleep) because `Non-REMian` or `Phase 3ian` would be a terrible name.
|
data/bin/.gitkeep
ADDED
File without changes
|
data/bin/remian
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "thor"
|
4
|
+
require "remian"
|
5
|
+
|
6
|
+
module Remian
|
7
|
+
class Thorian < Thor
|
8
|
+
desc "execute FILEPATH", "Runs given .rem file."
|
9
|
+
|
10
|
+
method_option :clock_speed, default: 30, aliases: "-c", desc: "Machine clock speed in Hz (default 50)."
|
11
|
+
method_option :memory_size, default: 1024, aliases: "-m", desc: "Size of machine memory (default 1024)."
|
12
|
+
|
13
|
+
def execute filepath
|
14
|
+
if File.exist? filepath
|
15
|
+
data = File.read filepath
|
16
|
+
else
|
17
|
+
Remian.say "Provided file #{filepath} does not exist."
|
18
|
+
exit
|
19
|
+
end
|
20
|
+
|
21
|
+
control = Remian::Control.new data, {clock_speed: options[:clock_speed].to_i, memory_size: options[:memory_size].to_i}
|
22
|
+
control.start
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
Remian::Thorian.start
|
27
|
+
end
|
28
|
+
class ThorExample < Thor
|
29
|
+
desc "start", "start server"
|
30
|
+
method_option :environment,:default => "development", :aliases => "-e",
|
31
|
+
:desc => "which environment you want server run."
|
32
|
+
method_option :daemon, :type => :boolean, :default => false, :aliases => "-d",
|
33
|
+
:desc => "running on daemon mode?"
|
34
|
+
def start
|
35
|
+
puts "start #{options.inspect}"
|
36
|
+
end
|
37
|
+
|
38
|
+
desc "stop" ,"stop server"
|
39
|
+
method_option :delay, :default => 0, :aliases => "-w",
|
40
|
+
:desc => "wait server finish it's job"
|
41
|
+
def stop
|
42
|
+
puts "stop"
|
43
|
+
end
|
44
|
+
end
|
data/lib/.gitkeep
ADDED
File without changes
|
data/lib/remian.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require "term/ansicolor"
|
2
|
+
require "./lib/remian/control"
|
3
|
+
|
4
|
+
module Remian
|
5
|
+
def self.say message, colour_hash
|
6
|
+
unless colour_hash.nil? || !Term::ANSIColor.respond_to?(colour_hash)
|
7
|
+
extend Term::ANSIColor
|
8
|
+
message = Term::ANSIColor.method(colour_hash.to_s).call(message)
|
9
|
+
end
|
10
|
+
puts message
|
11
|
+
end
|
12
|
+
end
|
data/lib/remian/.gitkeep
ADDED
File without changes
|
data/lib/remian/clock.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
# load initial instructions + data
|
2
|
+
# run initial instruction
|
3
|
+
# handle instruction register changes
|
4
|
+
# fetch + execute instruction register memory location
|
5
|
+
|
6
|
+
require "remian/clock"
|
7
|
+
require "remian/memory"
|
8
|
+
require "remian/decoder"
|
9
|
+
require "remian/instruction_set"
|
10
|
+
|
11
|
+
module Remian
|
12
|
+
class Control
|
13
|
+
attr_accessor :options
|
14
|
+
attr_accessor :clock
|
15
|
+
attr_accessor :memory
|
16
|
+
attr_accessor :decoder
|
17
|
+
attr_accessor :registers
|
18
|
+
attr_accessor :instruction_set
|
19
|
+
|
20
|
+
def initialize data, options = {}
|
21
|
+
@options = option_defaults.merge options
|
22
|
+
|
23
|
+
@registers = {address: nil}
|
24
|
+
@clock = Clock.new @options[:clock_speed]
|
25
|
+
@decoder = Decoder.new
|
26
|
+
|
27
|
+
@memory = Memory.new @options[:memory_size]
|
28
|
+
@memory.write_data data
|
29
|
+
|
30
|
+
@instruction_set = InstructionSet.new @memory, @registers
|
31
|
+
end
|
32
|
+
|
33
|
+
def start start_address = 1
|
34
|
+
@registers[:address] = start_address
|
35
|
+
|
36
|
+
while @clock.tick_delay
|
37
|
+
cycle
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
protected
|
42
|
+
def option_defaults
|
43
|
+
{clock_speed: 30, memory_size: 1024}
|
44
|
+
end
|
45
|
+
|
46
|
+
def cycle
|
47
|
+
address_contents = @memory.read @registers[:address]
|
48
|
+
@registers[:address] = @registers[:address] + 1
|
49
|
+
|
50
|
+
instruction = @decoder.parse address_contents
|
51
|
+
if not instruction[:opcode].nil? and @instruction_set.respond_to? instruction[:opcode]
|
52
|
+
Remian.say "> #{address_contents}", :green
|
53
|
+
@instruction_set.send(instruction[:opcode], instruction[:data])
|
54
|
+
else
|
55
|
+
Remian.say "Instruction '#{instruction[:opcode]}' is not defined.", :red
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# These solve problems with Ruby boolean types vs 1/0 integer booleans
|
2
|
+
class TrueClass
|
3
|
+
def to_i
|
4
|
+
1
|
5
|
+
end
|
6
|
+
end
|
7
|
+
class FalseClass
|
8
|
+
def to_i
|
9
|
+
0
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
module Remian
|
14
|
+
class InstructionSet
|
15
|
+
attr_accessor :memory
|
16
|
+
attr_accessor :registers
|
17
|
+
|
18
|
+
def initialize memory, registers
|
19
|
+
@memory = memory
|
20
|
+
@registers = registers
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
Dir["#{File.dirname(__FILE__)}/instruction_set/*.rb"].each do |file|
|
26
|
+
require "#{file[0..-4]}"
|
27
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module Remian
|
2
|
+
class InstructionSet
|
3
|
+
def branch addresses
|
4
|
+
if @memory.read(addresses[0].to_i).to_i != 0
|
5
|
+
destination = @memory.read(addresses[1].to_i).to_i
|
6
|
+
Remian.say "Branching to address #{destination}.", :magenta
|
7
|
+
@registers[:address] = destination
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# Addresses start at 1, despite underlying 0-based array implementation
|
2
|
+
# This makes assembly programming easier, since line numbers correspond to addresses.
|
3
|
+
module Remian
|
4
|
+
class Memory
|
5
|
+
attr_accessor :store, :size
|
6
|
+
|
7
|
+
def initialize size
|
8
|
+
@size = size
|
9
|
+
@store = Array.new @size, ""
|
10
|
+
end
|
11
|
+
|
12
|
+
def read address
|
13
|
+
memory_key = convert_address_to_memory_key address
|
14
|
+
@store[memory_key]
|
15
|
+
end
|
16
|
+
|
17
|
+
def write address, value
|
18
|
+
memory_key = convert_address_to_memory_key address
|
19
|
+
if memory_key >= 0 && memory_key < @store.length
|
20
|
+
@store[memory_key] = value
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def write_data data
|
25
|
+
data.split("\n").each_with_index do |instruction, i|
|
26
|
+
write i + 1, instruction
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
protected
|
31
|
+
def convert_address_to_memory_key address
|
32
|
+
address - 1
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
metadata
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: remian
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Michael Mokrysz
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-12-18 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: thor
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 0.16.0
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 0.16.0
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: term-ansicolor
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: 1.0.7
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 1.0.7
|
46
|
+
description: A baby virtual machine built in Ruby.
|
47
|
+
email:
|
48
|
+
- hi@46bit.com
|
49
|
+
executables:
|
50
|
+
- remian
|
51
|
+
extensions: []
|
52
|
+
extra_rdoc_files: []
|
53
|
+
files:
|
54
|
+
- .gitignore
|
55
|
+
- .gitkeep
|
56
|
+
- AUTHORS.md
|
57
|
+
- Gemfile
|
58
|
+
- Gemfile.lock
|
59
|
+
- LICENSE.md
|
60
|
+
- README.md
|
61
|
+
- bin/.gitkeep
|
62
|
+
- bin/remian
|
63
|
+
- lib/.gitkeep
|
64
|
+
- lib/remian.rb
|
65
|
+
- lib/remian/.gitkeep
|
66
|
+
- lib/remian/clock.rb
|
67
|
+
- lib/remian/control.rb
|
68
|
+
- lib/remian/decoder.rb
|
69
|
+
- lib/remian/instruction_set.rb
|
70
|
+
- lib/remian/instruction_set/add_i.rb
|
71
|
+
- lib/remian/instruction_set/and.rb
|
72
|
+
- lib/remian/instruction_set/branch.rb
|
73
|
+
- lib/remian/instruction_set/cp.rb
|
74
|
+
- lib/remian/instruction_set/exit.rb
|
75
|
+
- lib/remian/instruction_set/jump.rb
|
76
|
+
- lib/remian/instruction_set/mv.rb
|
77
|
+
- lib/remian/instruction_set/not.rb
|
78
|
+
- lib/remian/instruction_set/or.rb
|
79
|
+
- lib/remian/instruction_set/put.rb
|
80
|
+
- lib/remian/instruction_set/put_a.rb
|
81
|
+
- lib/remian/instruction_set/set.rb
|
82
|
+
- lib/remian/instruction_set/zero.rb
|
83
|
+
- lib/remian/memory.rb
|
84
|
+
homepage: https://github.com/46Bit/remian
|
85
|
+
licenses: []
|
86
|
+
post_install_message:
|
87
|
+
rdoc_options: []
|
88
|
+
require_paths:
|
89
|
+
- lib
|
90
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
91
|
+
none: false
|
92
|
+
requirements:
|
93
|
+
- - ! '>='
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0'
|
96
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
requirements: []
|
103
|
+
rubyforge_project:
|
104
|
+
rubygems_version: 1.8.24
|
105
|
+
signing_key:
|
106
|
+
specification_version: 3
|
107
|
+
summary: Remian is a small virtual machine, designed to a Von Neumann architecture
|
108
|
+
with a RISC mindset.
|
109
|
+
test_files: []
|