-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathrunner
executable file
·139 lines (123 loc) · 2.8 KB
/
runner
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#!/usr/bin/env ruby
require 'pathname'
require 'optparse'
require 'tempfile'
$verbose = false
DIR = File.dirname(__FILE__)
$assemble = "#{DIR}/assemble"
$sim = "#{DIR}/simulator"
def find_address(label, asm)
asm.open do |f|
n = 0
re = /^#{label}\s/
f.each_line do |line|
if line =~ re
return n
else
n += 1
end
end
raise "Failed to find label #{label} in #{asm}!"
end
end
def assemble(asm, mc)
cmd = "#{$assemble} #{asm} #{mc}"
unless system(cmd)
raise "'#{cmd}' failed: #{$?}"
end
end
TAG = { :register => "reg", :memory => "mem" }
def simulate(mc, extract, idx)
info = {}
pat = /^\s+#{TAG.fetch(extract)}\[ #{idx} \] (-?\d+)/
IO.popen("#{$sim} #{mc}") do |p|
done = false
last_pc = nil
begin
until done
line = p.readline
$stderr.puts(line) if $verbose
case line
when /total of (\d+) instructions executed/
then info[:instructions] = $1.to_i
when /final state of machine/
then done = true
when /\s*pc (\d+)/
then last_pc = $1.to_i
end
end
value = nil
while true
line = p.gets
break if line.nil?
if line =~ pat
info[:value] = $1.to_i
end
end
if ! info[:value]
raise "Could not parse #{extract} #{idx} from output!"
end
return info
rescue IOError => e
$stderr.puts "Error, last pc=#{last_pc}"
raise e
end
end
end
def run_prog(prog, extract)
tmp_mc = Tempfile.new([prog.basename(".as"), ".mc"])
tmp_mc.close
begin
assemble(prog, tmp_mc.path)
rescue
$stderr.puts "Assembly failed: #{$!}"
$stderr.puts "Program: #{prog}"
$stderr.puts $!.backtrace.join("\n")
exit 1
end
info = simulate(tmp_mc.path, *extract)
tmp_mc.unlink
return info
end
$prog = nil
$extract = nil
op = OptionParser.new do |opts|
opts.on("-p", "--program PROG", /.+\.as$/,
"LC2K program") do |prog|
$prog = Pathname.new(prog)
end
opts.on("-a", "--assembler ASM",
"Assembler") do |asm|
$assemble = asm
end
opts.on("-s", "--simulator SIM",
"Simulator") do |sim|
$sim = sim
end
opts.on("-m", "--memory-at ADDR", "Memory value to extract") do |memspec|
if memspec =~ /^\d+$/
$extract = [:memory, memspec.to_i]
else
$extract = [:memory, memspec]
end
end
opts.on("--reference",
"Use reference assembler and simulator") do
$assemble = './asol'
$sim = './ssol'
end
opts.on("-v", "--verbose",
"Verbose") do
$verbose = true
end
end
op.parse!(ARGV)
unless $prog && $extract
$stderr.puts op
exit 2
end
if $extract[1].is_a? String
$extract[1] = find_address($extract[1], $prog)
end
info = run_prog($prog, $extract)
puts info[:value]