rips 0.0.8 → 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 +4 -4
- data/README.md +52 -3
- data/bin/rips +3 -1
- data/examples/calc.rips +55 -0
- data/{example.rips → examples/example.rips} +0 -0
- data/lib/rips.rb +54 -25
- data/lib/rips/assembler.rb +98 -113
- data/lib/rips/error.rb +3 -2
- data/lib/rips/formats/format.rb +0 -4
- data/lib/rips/instructions/instruction.rb +18 -9
- data/lib/rips/utils.rb +4 -18
- data/lib/rips/utils/array.rb +12 -0
- data/lib/rips/utils/integer.rb +15 -0
- data/lib/rips/utils/string_assembler.rb +62 -0
- data/lib/rips/utils/string_variable.rb +41 -0
- data/lib/rips/variables/address.rb +4 -9
- data/lib/rips/variables/inmediate.rb +3 -8
- data/lib/rips/variables/port.rb +3 -9
- data/lib/rips/variables/register.rb +3 -8
- data/lib/rips/variables/variable.rb +4 -26
- data/lib/rips/version.rb +1 -1
- data/rips.gemspec +1 -1
- metadata +9 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3fff3963bd941c448681cc84b7866aef618c72d9
|
4
|
+
data.tar.gz: 1f77e7972c43bcc523a10f749b4cfc7c3bc04d67
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d0bb9c555874d3bdfac873b7cec8add0b1f05007684f5406158420cb76e2ca84352b3d2f2c258faadfc466b62a09d18c31173b65c75a9970fe427b182b1040b2
|
7
|
+
data.tar.gz: febd89dee2a4629452838ade172abde29357d6c1f14bad915cdcc9dcaccd15ea92452ff617f3c2d11ffef5ab8aaf37a655454ea21b77a5063310bab2183f525e
|
data/README.md
CHANGED
@@ -1,14 +1,63 @@
|
|
1
1
|
# Rips
|
2
|
+
[](http://badge.fury.io/rb/rips)
|
3
|
+
[](https://gemnasium.com/Madh93/rips)
|
2
4
|
|
3
|
-
Simple assembler written in Ruby for a simple 16-bit CPU written in Verilog.
|
5
|
+
Simple assembler written in Ruby for a simple 16-bit CPU written in Verilog. Based in MIPS syntax with next features:
|
6
|
+
|
7
|
+
- 18 basic instructions
|
8
|
+
- 16 registers ($0-$15)
|
9
|
+
- 4 I/O ports (@0-@3)
|
10
|
+
- Support labels
|
11
|
+
- Support comments
|
12
|
+
|
13
|
+
## Requirements
|
14
|
+
|
15
|
+
Ruby >=1.9.3
|
4
16
|
|
5
17
|
## Installation
|
6
18
|
|
7
19
|
$ gem install rips
|
20
|
+
|
21
|
+
or download from [RubyGems](https://rubygems.org/gems/rips).
|
22
|
+
|
23
|
+
**Optional:** [Rips syntax highlightning package for sublime text 2/3](https://github.com/Madh93/rips-syntax/)
|
8
24
|
|
9
25
|
## Usage
|
10
26
|
|
11
|
-
$ rips instructions.rips
|
27
|
+
$ rips [OPTIONS] instructions.rips
|
28
|
+
|
29
|
+
Examples:
|
30
|
+
|
31
|
+
$ rips --debug instructions.rips
|
32
|
+
$ rips -d instructions.rips -o instructions
|
33
|
+
|
34
|
+
## Options
|
35
|
+
|
36
|
+
-d, --debug Show trace in console
|
37
|
+
-o FILE Output file with binary instructions (by default: progfile.dat)
|
38
|
+
|
39
|
+
## Instruction Set
|
40
|
+
|
41
|
+
| Name | MNENOMIC | FORMAT | OPERATION | OPCODE |
|
42
|
+
|--------------------|----------|--------|----------------|--------|
|
43
|
+
| Move | move | C | move $1, $0 | 0000 |
|
44
|
+
| Not | not | C | not $1, $0 | 0001 |
|
45
|
+
| Add | add | D | add $2, $0, $1 | 0010 |
|
46
|
+
| Subtract | sub | D | sub $2, $0, $1 | 0011 |
|
47
|
+
| And | and | D | and $2, $0, $1 | 0100 |
|
48
|
+
| Or | or | D | or $2, $0, $1 | 0101 |
|
49
|
+
| Sign negation | neg | C | neg $1, $0 | 0110 |
|
50
|
+
| Jump | j | B | j label | 1001 |
|
51
|
+
| Load Inmediate | li | C | li $0, 10 | 1010 |
|
52
|
+
| Load from I/O | lesr | C | lesr $0, @0 | 1011 |
|
53
|
+
| Store I/O from Reg | sesr | C | sesr @0, $0 | 1101 |
|
54
|
+
| Store I/O from Mem | sesm | C | sesm @0, 10 | 1110 |
|
55
|
+
| Relative Jump | ji | B | ji 10 | 011000 |
|
56
|
+
| Jump and Link | jal | B | jal label | 101000 |
|
57
|
+
| Jump Register | jr | A | jr | 111000 |
|
58
|
+
| Branch z!=0 | bnez | B | bnez label | 001111 |
|
59
|
+
| Branch z==0 | beqz | B | beqz label | 011111 |
|
60
|
+
| No Operation | nop | A | nop | 111111 |
|
12
61
|
|
13
62
|
## Contributing
|
14
63
|
|
@@ -16,4 +65,4 @@ Simple assembler written in Ruby for a simple 16-bit CPU written in Verilog.
|
|
16
65
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
17
66
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
18
67
|
4. Push to the branch (`git push origin my-new-feature`)
|
19
|
-
5. Create a new Pull Request
|
68
|
+
5. Create a new Pull Request
|
data/bin/rips
CHANGED
data/examples/calc.rips
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
#### Simple calculator ###
|
2
|
+
|
3
|
+
# Assign opcodes to add, sub and mul
|
4
|
+
define:
|
5
|
+
li $5, 8 # add (1000)
|
6
|
+
li $6, 4 # sub (0100)
|
7
|
+
li $7, 2 # mul(0010)
|
8
|
+
|
9
|
+
main:
|
10
|
+
|
11
|
+
# Load from I/O to registers
|
12
|
+
lesr $1, @0
|
13
|
+
lesr $2, @1
|
14
|
+
lesr $3, @2
|
15
|
+
|
16
|
+
# Check input is add, sub or mul
|
17
|
+
sub $4, $3, $5
|
18
|
+
beqz op_add
|
19
|
+
|
20
|
+
sub $4, $3, $6
|
21
|
+
beqz op_sub
|
22
|
+
|
23
|
+
sub $4, $3, $7
|
24
|
+
beqz op_mul
|
25
|
+
|
26
|
+
j main # Infinite loop
|
27
|
+
|
28
|
+
op_add:
|
29
|
+
|
30
|
+
add $4, $1, $2
|
31
|
+
j store
|
32
|
+
|
33
|
+
op_sub:
|
34
|
+
|
35
|
+
sub $4, $1, $2
|
36
|
+
j store
|
37
|
+
|
38
|
+
op_mul:
|
39
|
+
|
40
|
+
li $8, 1 # Count
|
41
|
+
move $4, $0
|
42
|
+
add $1, $1, $0 # IF $1==0 -> finish loop
|
43
|
+
beqz store
|
44
|
+
|
45
|
+
loop:
|
46
|
+
|
47
|
+
add $4, $4, $2 # Repeat $1 times
|
48
|
+
sub $1, $1, $8
|
49
|
+
bnez loop
|
50
|
+
|
51
|
+
store:
|
52
|
+
|
53
|
+
# Store in I/O from register
|
54
|
+
sesr @0, $4
|
55
|
+
j main
|
File without changes
|
data/lib/rips.rb
CHANGED
@@ -3,34 +3,63 @@ require "rips/assembler"
|
|
3
3
|
require "rips/error"
|
4
4
|
|
5
5
|
module Rips
|
6
|
+
class RipsLauncher
|
6
7
|
|
7
|
-
|
8
|
+
# @argv: input's arguments
|
9
|
+
# @debug: switch to show trace in console
|
10
|
+
# @source: source file with Rips instructions
|
11
|
+
# @output: output file with binary instructions
|
12
|
+
def initialize
|
13
|
+
@argv = ARGV
|
14
|
+
@debug = debug_mode?
|
15
|
+
@source = source_file
|
16
|
+
@output = output_file
|
8
17
|
|
9
|
-
|
10
|
-
|
11
|
-
debug = true
|
12
|
-
ARGV.delete("-d")
|
13
|
-
elsif ARGV.include?("--debug")
|
14
|
-
debug = true
|
15
|
-
ARGV.delete("--debug")
|
16
|
-
end
|
17
|
-
|
18
|
-
Error::message(1) if ARGV.empty?
|
19
|
-
|
20
|
-
# Check for a valid file
|
21
|
-
if !File.exist? ARGV[0]
|
22
|
-
Error::message(2)
|
23
|
-
elsif !File.readable? ARGV[0]
|
24
|
-
Error::message(3)
|
25
|
-
end
|
18
|
+
run
|
19
|
+
end
|
26
20
|
|
27
|
-
|
21
|
+
private
|
28
22
|
|
29
|
-
|
30
|
-
|
31
|
-
|
23
|
+
# Check debug mode
|
24
|
+
def debug_mode?
|
25
|
+
@argv.include?("-d") || @argv.include?("--debug")
|
32
26
|
end
|
33
|
-
end
|
34
27
|
|
35
|
-
|
36
|
-
|
28
|
+
# Check if it's a valid input file
|
29
|
+
def source_file
|
30
|
+
source = @argv.find{|x| /\.rips$/ =~ x }
|
31
|
+
Error::message(1) if source.nil?
|
32
|
+
Error::message(2) if !File.exist?(source)
|
33
|
+
Error::message(3) if !File.readable?(source)
|
34
|
+
return source
|
35
|
+
end
|
36
|
+
|
37
|
+
# Check cmdline options (now only output)
|
38
|
+
def output_file
|
39
|
+
if @argv.include?("-o")
|
40
|
+
out = @argv[(@argv.index("-o"))+1]
|
41
|
+
Error::message(9) if out.nil? || out == @source || out == "-d" || out == "--debug"
|
42
|
+
return out
|
43
|
+
else
|
44
|
+
return "progfile.dat"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Read input file
|
49
|
+
def read
|
50
|
+
File.open(@source, "r") do |f|
|
51
|
+
f.each_line do |line|
|
52
|
+
@rips << line
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# Launch Rips assembler
|
58
|
+
def run
|
59
|
+
@rips = Assembler.new(@debug)
|
60
|
+
read
|
61
|
+
@rips.run(@output)
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
end
|
data/lib/rips/assembler.rb
CHANGED
@@ -1,5 +1,13 @@
|
|
1
1
|
require "rips/instructions"
|
2
2
|
|
3
|
+
class String
|
4
|
+
include Rips::Utils::StringAssemblerExtension
|
5
|
+
end
|
6
|
+
|
7
|
+
class Array
|
8
|
+
include Rips::Utils::ArrayExtension
|
9
|
+
end
|
10
|
+
|
3
11
|
module Rips
|
4
12
|
class Assembler
|
5
13
|
|
@@ -22,120 +30,62 @@ module Rips
|
|
22
30
|
@line = 1
|
23
31
|
end
|
24
32
|
|
25
|
-
|
26
|
-
def find_labels
|
27
|
-
|
28
|
-
@input.each_with_index do |line, i|
|
29
|
-
if !line.empty?
|
30
|
-
label = line.scan(/\w+:/)
|
31
|
-
if (label.size == 1)
|
32
|
-
|
33
|
-
if !@labels.include?(label[0].to_s.split(":").first)
|
34
|
-
@labels[label[0].to_s.split(":").first] = [*@instructions.each_with_index].bsearch{|x, _| x >= i}.last
|
35
|
-
else
|
36
|
-
Error::message(7, i+1, label[0].to_s.split(":").first)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
33
|
+
private
|
42
34
|
|
43
35
|
# Store number line for each instruction
|
44
36
|
def find_instructions
|
45
|
-
|
46
37
|
@input.each_with_index do |line,i|
|
47
|
-
if
|
38
|
+
if line.instruction?
|
48
39
|
@instructions << i+1
|
49
40
|
end
|
50
41
|
end
|
51
42
|
end
|
52
43
|
|
53
|
-
#
|
54
|
-
def
|
55
|
-
@input
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
find_labels
|
63
|
-
|
64
|
-
@input.each do |line|
|
65
|
-
|
66
|
-
# If line is empty -> next line
|
67
|
-
# Or if not is a label
|
68
|
-
if (!line.empty?) && (line.scan(/\w+:/).empty?)
|
69
|
-
|
70
|
-
parse_input(line)
|
71
|
-
@instruction = nil
|
72
|
-
|
73
|
-
# If it's a comment -> show but not work with it
|
74
|
-
if line[0] != "#"
|
75
|
-
|
76
|
-
exists_instruction
|
77
|
-
@instruction = get_instruction
|
78
|
-
|
79
|
-
parse_label
|
80
|
-
|
81
|
-
argument_size
|
82
|
-
argument_syntax
|
83
|
-
|
84
|
-
@instruction.set_arguments(@cmd[:arguments])
|
85
|
-
@output << @instruction.code
|
44
|
+
# Store labels and number line
|
45
|
+
def find_labels
|
46
|
+
@input.each_with_index do |line, i|
|
47
|
+
if line.label?(i)
|
48
|
+
label = line.split(":")[0]
|
49
|
+
if !@labels.include?(label)
|
50
|
+
@labels[label] = [*@instructions.each_with_index].search{|x, _| x >= i}.last
|
51
|
+
else
|
52
|
+
Error::message(7, i+1, line)
|
86
53
|
end
|
87
|
-
|
88
|
-
end
|
89
|
-
@line += 1
|
90
|
-
end
|
91
|
-
|
92
|
-
generate
|
93
|
-
end
|
94
|
-
|
95
|
-
# Codification log of instruction
|
96
|
-
def show
|
97
|
-
|
98
|
-
# If line was a comment -> @instruction should be nil
|
99
|
-
if @instruction.nil?
|
100
|
-
codification = ""
|
101
|
-
else
|
102
|
-
codification = @instruction.code.scan(/.{4}|.+/).join("_")
|
54
|
+
end
|
103
55
|
end
|
104
|
-
|
105
|
-
puts "@#{@line}:" \
|
106
|
-
"\t#{codification}" \
|
107
|
-
"\t#{@cmd[:comments]}"
|
108
56
|
end
|
109
57
|
|
110
|
-
# Generate output in "progfile.dat"
|
111
|
-
def generate
|
112
|
-
File.open("progfile.dat", "w") do |f|
|
113
|
-
@output.each do |line|
|
114
|
-
f.puts line
|
115
|
-
end
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
58
|
# Split on tokens
|
120
59
|
def parse_input (line)
|
121
60
|
|
122
|
-
if line
|
61
|
+
if line.comment?
|
123
62
|
@cmd[:comments] = line
|
124
63
|
else
|
125
|
-
@cmd[:name] = line.
|
126
|
-
@cmd[:
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
if @cmd[:arguments].first == "jr" ||
|
131
|
-
@cmd[:arguments].first == "nop"
|
132
|
-
@cmd[:arguments] = []
|
64
|
+
@cmd[:name] = line.instruction_name
|
65
|
+
if (@cmd[:name] == "jr ") || (@cmd[:name] == "nop ")
|
66
|
+
@cmd[:arguments] = []
|
67
|
+
else
|
68
|
+
@cmd[:arguments] = line.instruction_arguments(@cmd[:name])
|
133
69
|
end
|
134
|
-
@cmd[:comments] = line.
|
70
|
+
@cmd[:comments] = line.instruction_comments
|
135
71
|
@cmd[:comments].insert(0,"#") if !@cmd[:comments].empty?
|
136
72
|
end
|
137
73
|
end
|
138
74
|
|
75
|
+
# Obtain instruction's instance object
|
76
|
+
def get_instruction
|
77
|
+
Rips::Instructions.const_get("#{@cmd[:name].capitalize}").new
|
78
|
+
end
|
79
|
+
|
80
|
+
# Exists instruction in Instruction Set?
|
81
|
+
def exists_instruction?
|
82
|
+
if Instructions::SET.include? (@cmd[:name])
|
83
|
+
@instruction = get_instruction
|
84
|
+
else
|
85
|
+
Error::message(4, @line, @cmd[:name] )
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
139
89
|
# Translate label's name to instruction's number
|
140
90
|
def parse_label
|
141
91
|
if (@instruction.is_a? Rips::Instructions::Beqz) ||
|
@@ -146,23 +96,9 @@ module Rips
|
|
146
96
|
@cmd[:arguments] = [@labels[@cmd[:arguments].first].to_s]
|
147
97
|
end
|
148
98
|
end
|
149
|
-
|
150
|
-
# Obtain instruction's instance object
|
151
|
-
def get_instruction
|
152
|
-
Object.const_get("Rips::Instructions::#{@cmd[:name].capitalize}").new
|
153
|
-
end
|
154
|
-
|
155
|
-
# Exists instruction in Instruction Set?
|
156
|
-
def exists_instruction
|
157
|
-
if !Instructions::SET.include? (@cmd[:name])
|
158
|
-
Error::message( 4,
|
159
|
-
@line,
|
160
|
-
@cmd[:name] )
|
161
|
-
end
|
162
|
-
end
|
163
|
-
|
99
|
+
|
164
100
|
# Check number of arguments given with expected by instruction
|
165
|
-
def argument_size
|
101
|
+
def argument_size?
|
166
102
|
if @cmd[:arguments].size != @instruction.args_number
|
167
103
|
Error::message( 5,
|
168
104
|
@line,
|
@@ -173,16 +109,65 @@ module Rips
|
|
173
109
|
end
|
174
110
|
|
175
111
|
# Check if arguments are the same variable type of instruction
|
176
|
-
def argument_syntax
|
112
|
+
def argument_syntax?
|
177
113
|
@instruction.variables.each_with_index do |var,i|
|
178
|
-
if var.
|
179
|
-
@cmd[:arguments][i] =
|
114
|
+
if var.valid_syntax? @cmd[:arguments][i]
|
115
|
+
@cmd[:arguments][i] = @cmd[:arguments][i].arg_to_i
|
180
116
|
else
|
181
|
-
Error::message(
|
182
|
-
@line,
|
183
|
-
var.error(@cmd[:arguments][i]) )
|
117
|
+
Error::message(6, @line, var.error(@cmd[:arguments][i]) )
|
184
118
|
end
|
185
119
|
end
|
186
120
|
end
|
121
|
+
|
122
|
+
# Codification log of instruction
|
123
|
+
def show (i)
|
124
|
+
puts "@#{@line}:" \
|
125
|
+
"\t#{@output[i].scan(/.{4}|.+/).join("_") unless @instruction.nil?}" \
|
126
|
+
"\t#{@cmd[:comments]}"
|
127
|
+
end
|
128
|
+
|
129
|
+
# Generate output in "progfile.dat"
|
130
|
+
def generate (path)
|
131
|
+
File.open(path, "w") do |f|
|
132
|
+
@output.each do |line|
|
133
|
+
f.puts line
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
public
|
139
|
+
|
140
|
+
# Stores each new line of file
|
141
|
+
def << (value)
|
142
|
+
@input << value.strip
|
143
|
+
end
|
144
|
+
|
145
|
+
# Analyze and translate each instruction
|
146
|
+
def run (path = "progfile.dat")
|
147
|
+
find_instructions
|
148
|
+
find_labels
|
149
|
+
|
150
|
+
@input.each do |line|
|
151
|
+
if (line.instruction?) || (line.comment?)
|
152
|
+
parse_input(line)
|
153
|
+
@instruction = nil
|
154
|
+
# If it's a comment -> show but not work with it
|
155
|
+
if line.instruction?
|
156
|
+
|
157
|
+
exists_instruction?
|
158
|
+
parse_label
|
159
|
+
argument_size?
|
160
|
+
argument_syntax?
|
161
|
+
|
162
|
+
@instruction.set_arguments(@cmd[:arguments])
|
163
|
+
@output << @instruction.code
|
164
|
+
end
|
165
|
+
show(@output.size-1) if @debug
|
166
|
+
end
|
167
|
+
@line += 1
|
168
|
+
end
|
169
|
+
generate(path)
|
170
|
+
end
|
171
|
+
|
187
172
|
end
|
188
173
|
end
|
data/lib/rips/error.rb
CHANGED
@@ -3,14 +3,15 @@ module Rips
|
|
3
3
|
|
4
4
|
MESSAGES =
|
5
5
|
[ "RIPS ERROR (0). Unknown problem.",
|
6
|
-
"RIPS ERROR (1).
|
6
|
+
"RIPS ERROR (1). Invalid input file (try `rips file.rips`).",
|
7
7
|
"RIPS ERROR (2). Doesn't exist file or directory.",
|
8
8
|
"RIPS ERROR (3). Permission denied to read file.",
|
9
9
|
"RIPS ERROR (4). In line %d: doesn't exist `%s` instruction in Instruction Set.",
|
10
10
|
"RIPS ERROR (5). In line %d: for `%s` instruction wrong number of arguments (%d for %d).",
|
11
11
|
"RIPS ERROR (6). In line %d: syntax error, %s.",
|
12
12
|
"RIPS ERROR (7). In line %d: There is already a label called `%s`.",
|
13
|
-
"RIPS ERROR (8). In line %d: Unknown syntax for label `%s` (try `labelname:`)."
|
13
|
+
"RIPS ERROR (8). In line %d: Unknown syntax for label `%s` (try `labelname:`).",
|
14
|
+
"RIPS ERROR (9). Invalid output file." ]
|
14
15
|
|
15
16
|
def self.message (num, *args)
|
16
17
|
puts MESSAGES[num] % args
|
data/lib/rips/formats/format.rb
CHANGED
@@ -1,6 +1,11 @@
|
|
1
1
|
require "rips/instructions/set"
|
2
2
|
require "rips/formats"
|
3
3
|
require "rips/variables"
|
4
|
+
require "rips/utils"
|
5
|
+
|
6
|
+
class Integer
|
7
|
+
include Rips::Utils::IntegerExtension
|
8
|
+
end
|
4
9
|
|
5
10
|
module Rips
|
6
11
|
module Instructions
|
@@ -16,15 +21,7 @@ module Rips
|
|
16
21
|
@output = []
|
17
22
|
end
|
18
23
|
|
19
|
-
|
20
|
-
def args_number
|
21
|
-
@format.args_number
|
22
|
-
end
|
23
|
-
|
24
|
-
# Pass all arguments at once
|
25
|
-
def set_arguments (args)
|
26
|
-
@format.set_arguments(args)
|
27
|
-
end
|
24
|
+
private
|
28
25
|
|
29
26
|
# Add blanks (0 values) for instructions with free space
|
30
27
|
def add_blank
|
@@ -37,6 +34,18 @@ module Rips
|
|
37
34
|
end
|
38
35
|
end
|
39
36
|
|
37
|
+
public
|
38
|
+
|
39
|
+
# Return number of arguments
|
40
|
+
def args_number
|
41
|
+
@format.args_number
|
42
|
+
end
|
43
|
+
|
44
|
+
# Pass all arguments at once
|
45
|
+
def set_arguments (args)
|
46
|
+
@format.set_arguments(args)
|
47
|
+
end
|
48
|
+
|
40
49
|
# Coding to Machine Code
|
41
50
|
def code
|
42
51
|
|
data/lib/rips/utils.rb
CHANGED
@@ -1,18 +1,4 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
else
|
6
|
-
'%0*b' % [width, self]
|
7
|
-
end
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
|
-
class String
|
12
|
-
def del(regexp)
|
13
|
-
gsub(regexp,'')
|
14
|
-
end
|
15
|
-
def del!(regexp)
|
16
|
-
gsub!(regexp,'')
|
17
|
-
end
|
18
|
-
end
|
1
|
+
require "rips/utils/array"
|
2
|
+
require "rips/utils/integer"
|
3
|
+
require "rips/utils/string_variable"
|
4
|
+
require "rips/utils/string_assembler"
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require "rips/error"
|
2
|
+
|
3
|
+
module Rips
|
4
|
+
module Utils
|
5
|
+
module StringAssemblerExtension
|
6
|
+
|
7
|
+
# Delete spaces and tabs
|
8
|
+
def del(regexp)
|
9
|
+
gsub(regexp,'')
|
10
|
+
end
|
11
|
+
|
12
|
+
# Delete spaces and tabs
|
13
|
+
def del!(regexp)
|
14
|
+
gsub!(regexp,'')
|
15
|
+
end
|
16
|
+
|
17
|
+
# Return integer part of arguments of an instruction
|
18
|
+
def arg_to_i
|
19
|
+
(/\A[-]?\d+\z/ === self) ? self.to_i : self.slice(1..-1).to_i
|
20
|
+
end
|
21
|
+
|
22
|
+
# Check if string is a comment
|
23
|
+
def comment?
|
24
|
+
self[0] == "#"
|
25
|
+
end
|
26
|
+
|
27
|
+
# Check if string is a label
|
28
|
+
def label?(line)
|
29
|
+
if (!self.empty?) && (self[0] != "#") && (self[-1] == ":")
|
30
|
+
label = self.scan(/\w+:/)
|
31
|
+
if (label.size == 1)
|
32
|
+
return true
|
33
|
+
elsif (label.size > 1)
|
34
|
+
Error::message(8, line+1, self)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Check if string is a instruction
|
40
|
+
def instruction?
|
41
|
+
(!self.empty?) && (self[0] != "#") && (self.scan(/\w+:/).empty?)
|
42
|
+
end
|
43
|
+
|
44
|
+
# Get intruction's name of string
|
45
|
+
def instruction_name
|
46
|
+
self.split("#").first.split(" ").first.downcase
|
47
|
+
end
|
48
|
+
|
49
|
+
# Get intruction's arguments of string
|
50
|
+
def instruction_arguments(instruction)
|
51
|
+
args = self.split("#").first.split("#{instruction} ")
|
52
|
+
args.pop.split("#").first.del(/\s+|\t+/).split(",") unless args.empty?
|
53
|
+
end
|
54
|
+
|
55
|
+
# Get intruction's comments of string
|
56
|
+
def instruction_comments
|
57
|
+
self.split("#").slice(1..-1).join
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Rips
|
2
|
+
module Utils
|
3
|
+
module StringVariableExtension
|
4
|
+
|
5
|
+
# Check if value is a valid number (...,-1,0,1...)
|
6
|
+
def number? (value)
|
7
|
+
/\A[-]?\d+\z/ === value
|
8
|
+
end
|
9
|
+
|
10
|
+
# Check if value is between in permitted range
|
11
|
+
def valid_range? (range)
|
12
|
+
if number?(self.slice(1..-1))
|
13
|
+
self.to_i.between?(range[0], range[1])
|
14
|
+
else
|
15
|
+
self.slice(1..-1).to_i.between?(range[0], range[1])
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# Check if value is a valid inmediate (...,-1,0,1...)
|
20
|
+
def inmediate?
|
21
|
+
number?(self)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Check if value is a register ($0..15)
|
25
|
+
def register?
|
26
|
+
(self[0] == "$") && number?(self.slice(1..-1))
|
27
|
+
end
|
28
|
+
|
29
|
+
# Check if value is a port (@0..3)
|
30
|
+
def port?
|
31
|
+
(self[0] == "@") && number?(self.slice(1..-1))
|
32
|
+
end
|
33
|
+
|
34
|
+
# Check if value is an address (0..127 | label)
|
35
|
+
def address? (range)
|
36
|
+
(self.is_a?(String)) || (number?(self.slice(1..-1)) && valid_range?(range))
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -16,16 +16,11 @@ module Rips
|
|
16
16
|
end
|
17
17
|
|
18
18
|
# Check input variable syntax
|
19
|
-
def
|
20
|
-
|
21
|
-
|
22
|
-
true
|
23
|
-
elsif value.is_a?(String)
|
24
|
-
true
|
25
|
-
else
|
26
|
-
false
|
27
|
-
end
|
19
|
+
def valid_syntax? (value)
|
20
|
+
value.extend(Rips::Utils::StringVariableExtension)
|
21
|
+
value.address?(@range)
|
28
22
|
end
|
23
|
+
|
29
24
|
end
|
30
25
|
end
|
31
26
|
end
|
@@ -16,14 +16,9 @@ module Rips
|
|
16
16
|
end
|
17
17
|
|
18
18
|
# Check input variable syntax
|
19
|
-
def
|
20
|
-
|
21
|
-
|
22
|
-
if number?(value) && between?(value, @range)
|
23
|
-
true
|
24
|
-
else
|
25
|
-
false
|
26
|
-
end
|
19
|
+
def valid_syntax? (value)
|
20
|
+
value.extend(Rips::Utils::StringVariableExtension)
|
21
|
+
value.inmediate? && value.valid_range?(@range)
|
27
22
|
end
|
28
23
|
|
29
24
|
end
|
data/lib/rips/variables/port.rb
CHANGED
@@ -11,20 +11,14 @@ module Rips
|
|
11
11
|
# @range: bit's range for variable
|
12
12
|
def initialize(size = 2)
|
13
13
|
super(size)
|
14
|
-
@syntax = "@0-3"
|
15
14
|
@range = [0, 2**@length-1]
|
16
15
|
@syntax = "@#{@range[0]}-#{@range[1]}"
|
17
16
|
end
|
18
17
|
|
19
18
|
# Check input variable syntax
|
20
|
-
def
|
21
|
-
|
22
|
-
|
23
|
-
if port?(value) && between?(value, @range)
|
24
|
-
true
|
25
|
-
else
|
26
|
-
false
|
27
|
-
end
|
19
|
+
def valid_syntax? (value)
|
20
|
+
value.extend(Rips::Utils::StringVariableExtension)
|
21
|
+
value.port? && value.valid_range?(@range)
|
28
22
|
end
|
29
23
|
|
30
24
|
end
|
@@ -16,14 +16,9 @@ module Rips
|
|
16
16
|
end
|
17
17
|
|
18
18
|
# Check input variable syntax
|
19
|
-
def
|
20
|
-
|
21
|
-
|
22
|
-
if register?(value) && between?(value, @range)
|
23
|
-
true
|
24
|
-
else
|
25
|
-
false
|
26
|
-
end
|
19
|
+
def valid_syntax? (value)
|
20
|
+
value.extend(Rips::Utils::StringVariableExtension)
|
21
|
+
value.register? && value.valid_range?(@range)
|
27
22
|
end
|
28
23
|
|
29
24
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require "rips/utils"
|
2
|
+
|
1
3
|
module Rips
|
2
4
|
module Variables
|
3
5
|
|
@@ -10,35 +12,11 @@ module Rips
|
|
10
12
|
@length = length
|
11
13
|
end
|
12
14
|
|
13
|
-
# Check if value is a register ($0..15)
|
14
|
-
def register? (value)
|
15
|
-
(value[0] == "$") && number?(value.slice(1..-1))
|
16
|
-
end
|
17
|
-
|
18
|
-
# Check if value is a port (@0..3)
|
19
|
-
def port? (value)
|
20
|
-
(value[0] == "@") && number?(value.slice(1..-1))
|
21
|
-
end
|
22
|
-
|
23
|
-
# Check if value is a valid number (...,-1,0,1...)
|
24
|
-
def number? (value)
|
25
|
-
/\A[-]?\d+\z/ === value
|
26
|
-
end
|
27
|
-
|
28
|
-
# Check if value is between in permitted range
|
29
|
-
def between? (value, range)
|
30
|
-
to_i(value).between?(range[0], range[1])
|
31
|
-
end
|
32
|
-
|
33
|
-
# Return integer part of value
|
34
|
-
def to_i (value)
|
35
|
-
number?(value) ? value.to_i : value.slice(1..-1).to_i
|
36
|
-
end
|
37
|
-
|
38
15
|
# Return error message about incorrent syntax
|
39
16
|
def error (value)
|
40
17
|
"unexpected `#{value}` (expected a `#{self.class.to_s.split(':').last}` argument like `#{@syntax}`)"
|
41
|
-
end
|
18
|
+
end
|
19
|
+
|
42
20
|
end
|
43
21
|
end
|
44
22
|
end
|
data/lib/rips/version.rb
CHANGED
data/rips.gemspec
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rips
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Madh93
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-05-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -67,7 +67,8 @@ files:
|
|
67
67
|
- README.md
|
68
68
|
- Rakefile
|
69
69
|
- bin/rips
|
70
|
-
-
|
70
|
+
- examples/calc.rips
|
71
|
+
- examples/example.rips
|
71
72
|
- lib/rips.rb
|
72
73
|
- lib/rips/assembler.rb
|
73
74
|
- lib/rips/error.rb
|
@@ -99,6 +100,10 @@ files:
|
|
99
100
|
- lib/rips/instructions/set.rb
|
100
101
|
- lib/rips/instructions/sub.rb
|
101
102
|
- lib/rips/utils.rb
|
103
|
+
- lib/rips/utils/array.rb
|
104
|
+
- lib/rips/utils/integer.rb
|
105
|
+
- lib/rips/utils/string_assembler.rb
|
106
|
+
- lib/rips/utils/string_variable.rb
|
102
107
|
- lib/rips/variables.rb
|
103
108
|
- lib/rips/variables/address.rb
|
104
109
|
- lib/rips/variables/inmediate.rb
|
@@ -121,7 +126,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
121
126
|
requirements:
|
122
127
|
- - ">="
|
123
128
|
- !ruby/object:Gem::Version
|
124
|
-
version:
|
129
|
+
version: 1.9.3
|
125
130
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
126
131
|
requirements:
|
127
132
|
- - ">="
|