redshift 1.3.24 → 1.3.30
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +49 -0
- data/RELEASE-NOTES +34 -3
- data/Rakefile +81 -0
- data/bench/bench +1 -1
- data/bench/formula.rb +2 -3
- data/examples/pid.rb +6 -6
- data/examples/robots/lib/shell-world.rb +1 -1
- data/examples/scheduler.rb +6 -1
- data/ext/redshift/dvector-float/dvector-float.c +184 -0
- data/ext/redshift/dvector-float/dvector-float.h +36 -0
- data/ext/redshift/dvector-float/dvector-float.rb +33 -0
- data/ext/redshift/dvector-float/extconf.rb +2 -0
- data/lib/redshift/redshift.rb +5 -5
- data/lib/redshift/target/c/component-gen.rb +1 -1
- data/lib/redshift/target/c/flow-gen.rb +1 -1
- data/lib/redshift/target/c/flow/delay.rb +1 -1
- data/lib/redshift/target/c/world-gen.rb +101 -101
- data/lib/redshift/util/isaac.rb +2 -2
- data/lib/redshift/util/tkar-driver.rb +1 -1
- data/test/test.rb +1 -1
- data/test/test_buffer.rb +2 -2
- data/test/test_connect.rb +2 -2
- data/test/test_connect_parallel.rb +2 -2
- data/test/test_connect_strict.rb +4 -5
- data/test/test_constant.rb +2 -4
- data/test/test_delay.rb +2 -2
- data/test/test_derivative.rb +2 -2
- data/test/test_discrete.rb +2 -4
- data/test/test_discrete_isolated.rb +2 -4
- data/test/test_dvector-float.rb +110 -0
- data/test/test_dvector.rb +15 -17
- data/test/test_exit.rb +2 -4
- data/test/test_flow.rb +2 -4
- data/test/test_flow_link.rb +2 -4
- data/test/test_flow_sub.rb +2 -4
- data/test/test_flow_trans.rb +23 -25
- data/test/test_inherit.rb +2 -4
- data/test/test_inherit_event.rb +2 -4
- data/test/test_inherit_flow.rb +2 -4
- data/test/test_inherit_link.rb +2 -4
- data/test/test_inherit_setup.rb +2 -4
- data/test/test_inherit_state.rb +2 -4
- data/test/test_inherit_transition.rb +2 -4
- data/test/test_numerics.rb +2 -4
- data/test/test_queue.rb +3 -3
- data/test/test_queue_alone.rb +2 -2
- data/test/test_reset.rb +2 -4
- data/test/test_setup.rb +2 -4
- data/test/test_strict_continuity.rb +2 -4
- data/test/test_strict_reset_error.rb +2 -4
- data/test/test_strictness_error.rb +2 -4
- data/test/test_sync.rb +2 -2
- data/test/test_world.rb +2 -4
- metadata +80 -106
- data/.bnsignore +0 -27
- data/.gitignore +0 -9
- data/README +0 -25
- data/TODO +0 -431
- data/bench/aug17-ruby19.bench +0 -86
- data/bench/aug17.bench +0 -86
- data/bench/aug7.bench +0 -86
- data/bench/prof.html +0 -0
- data/examples/robots/README +0 -49
- data/ext/redshift/util/isaac/extconf.rb +0 -2
- data/ext/redshift/util/isaac/isaac.c +0 -129
- data/ext/redshift/util/isaac/rand.c +0 -140
- data/ext/redshift/util/isaac/rand.h +0 -61
- data/rakefile +0 -50
@@ -0,0 +1,36 @@
|
|
1
|
+
#ifndef dvector_float_h
|
2
|
+
#define dvector_float_h
|
3
|
+
|
4
|
+
#include <ruby.h>
|
5
|
+
|
6
|
+
typedef struct {
|
7
|
+
long len;
|
8
|
+
long capa;
|
9
|
+
float *ptr;
|
10
|
+
} RS_DVectorFloat;
|
11
|
+
|
12
|
+
extern void rs_dvf_grow(RS_DVectorFloat *dvf);
|
13
|
+
extern void rs_dvf_shrink(RS_DVectorFloat *dvf);
|
14
|
+
|
15
|
+
inline static RS_DVectorFloat *rs_dvf(VALUE obj)
|
16
|
+
{
|
17
|
+
return (RS_DVectorFloat *)DATA_PTR(obj);
|
18
|
+
}
|
19
|
+
|
20
|
+
inline static void rs_dvf_push(RS_DVectorFloat *dvf, float val)
|
21
|
+
{
|
22
|
+
if (dvf->len == dvf->capa) {
|
23
|
+
rs_dvf_grow(dvf);
|
24
|
+
}
|
25
|
+
dvf->ptr[dvf->len++] = val;
|
26
|
+
}
|
27
|
+
|
28
|
+
inline static float rs_dvf_pop(RS_DVectorFloat *dvf)
|
29
|
+
{
|
30
|
+
if (dvf->len == 0) {
|
31
|
+
return 0;
|
32
|
+
}
|
33
|
+
return dvf->ptr[--dvf->len];
|
34
|
+
}
|
35
|
+
|
36
|
+
#endif
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module RedShift; end
|
2
|
+
|
3
|
+
# A linear collection of single-precision floats.
|
4
|
+
#
|
5
|
+
# Intended primarily for access from C code, using the inline
|
6
|
+
# rs_dvf_push() and rs_dvf_pop() functions.
|
7
|
+
#
|
8
|
+
# Implements some of the same methods as Array, but not all.
|
9
|
+
#
|
10
|
+
# Like an Array, a DVector grows implicitly as elements are
|
11
|
+
# pushed. But unlike an Array, a DVector shrinks only explicitly.
|
12
|
+
# This is to minimize realloc() calls when a DVector rapidly
|
13
|
+
# grows and shrinks.
|
14
|
+
|
15
|
+
class RedShift::DVectorFloat
|
16
|
+
include Enumerable
|
17
|
+
require 'redshift/dvector-float/dvector_float.so'
|
18
|
+
|
19
|
+
def self.[](*elts)
|
20
|
+
new elts
|
21
|
+
end
|
22
|
+
|
23
|
+
def initialize(elts=nil)
|
24
|
+
push(*elts) if elts
|
25
|
+
end
|
26
|
+
|
27
|
+
def inspect; to_a.inspect; end
|
28
|
+
def to_s; to_a.to_s; end
|
29
|
+
|
30
|
+
def dup
|
31
|
+
self.class.new to_a
|
32
|
+
end
|
33
|
+
end
|
data/lib/redshift/redshift.rb
CHANGED
@@ -69,8 +69,8 @@ end
|
|
69
69
|
|
70
70
|
module RedShift
|
71
71
|
include Math
|
72
|
-
|
73
|
-
VERSION = '1.3.
|
72
|
+
|
73
|
+
VERSION = '1.3.30'
|
74
74
|
|
75
75
|
Infinity = Math::Infinity
|
76
76
|
|
@@ -87,7 +87,7 @@ module RedShift
|
|
87
87
|
$REDSHIFT_DEBUG = setting
|
88
88
|
end
|
89
89
|
end
|
90
|
-
|
90
|
+
|
91
91
|
# Returns a list of all worlds (instances of RedShift::World and subclasses),
|
92
92
|
# or just those descending from +world_class+.
|
93
93
|
# Not very efficient, since it uses <tt>ObjectSpace.each_object</tt>, but
|
@@ -99,7 +99,7 @@ module RedShift
|
|
99
99
|
end
|
100
100
|
|
101
101
|
# class Warning < Exception; end
|
102
|
-
#
|
102
|
+
#
|
103
103
|
# # Warn with string str and skipping n stack frames.
|
104
104
|
# def warn str, n = 0
|
105
105
|
# warning = sprintf "\nWarning: #{str}\n\t#{caller(n).join("\n\t")}\n"
|
@@ -112,7 +112,7 @@ module RedShift
|
|
112
112
|
# module_function :warn
|
113
113
|
|
114
114
|
@library_calls = []
|
115
|
-
|
115
|
+
|
116
116
|
# Defer a block until just after the library ruby code is loaded, but before
|
117
117
|
# commit. Necessary for defining inline C functions or shadow_attrs. Note that
|
118
118
|
# a whole require statement could be placed inside the with_library block.
|
@@ -173,7 +173,7 @@ module RedShift; class Flow
|
|
173
173
|
raise(NameError, "No such link, #{link}") unless link_type
|
174
174
|
strict = (link_strictness == :strict)
|
175
175
|
|
176
|
-
flow_fn.include link_type.shadow_library_include_file
|
176
|
+
flow_fn.file.include link_type.shadow_library_include_file
|
177
177
|
|
178
178
|
link_cname = "link_#{link}"
|
179
179
|
get_var_cname = "get_#{link}__#{var}"
|
@@ -73,7 +73,7 @@ module RedShift; class DelayFlow
|
|
73
73
|
flow.translate(self, "delay", cl, 0, delay_by)
|
74
74
|
end
|
75
75
|
|
76
|
-
include World.shadow_library_include_file
|
76
|
+
source_file.include World.shadow_library_include_file
|
77
77
|
|
78
78
|
# Note: cases 1,2 must proceed to allow alg deps to be computed,
|
79
79
|
# since their values are used later.
|
@@ -20,7 +20,6 @@ class World
|
|
20
20
|
1); \\
|
21
21
|
list_i--)
|
22
22
|
|
23
|
-
int dummy;
|
24
23
|
'.tabto(0)
|
25
24
|
# Note: EACH_COMP_DO(lc) block may use move_comp and remove_comp
|
26
25
|
# but it should (re)move none or all. Must have declarations for comp
|
@@ -32,30 +31,30 @@ class World
|
|
32
31
|
double value;
|
33
32
|
} CVCacheEntry;
|
34
33
|
}
|
35
|
-
|
34
|
+
|
36
35
|
shadow_library_include_file.declare :link_cache_entry => %{
|
37
36
|
typedef struct {
|
38
37
|
ComponentShadow **link_ptr;
|
39
38
|
VALUE value;
|
40
39
|
} LinkCacheEntry;
|
41
40
|
}
|
42
|
-
|
41
|
+
|
43
42
|
shadow_library_include_file.declare :port_cache_entry => %{
|
44
43
|
typedef struct {
|
45
44
|
VALUE input_port;
|
46
45
|
VALUE other_port;
|
47
46
|
} PortCacheEntry;
|
48
47
|
}
|
49
|
-
|
48
|
+
|
50
49
|
# Initial size for the constant value cache.
|
51
50
|
CV_CACHE_SIZE = 64
|
52
51
|
|
53
52
|
# Initial size for the link cache.
|
54
53
|
LINK_CACHE_SIZE = 64
|
55
|
-
|
54
|
+
|
56
55
|
# Initial size for the port cache.
|
57
56
|
PORT_CACHE_SIZE = 64
|
58
|
-
|
57
|
+
|
59
58
|
World.subclasses.each do |sub|
|
60
59
|
file_name = CGenerator.make_c_name(sub.name).to_s
|
61
60
|
sub.shadow_library_file file_name
|
@@ -80,7 +79,7 @@ class World
|
|
80
79
|
:active_E=, :prev_active_E=, :awake=,
|
81
80
|
:strict_sleep=, :inert=, :diff_list=,
|
82
81
|
:queue_sleep=
|
83
|
-
|
82
|
+
|
84
83
|
shadow_attr_reader :time_step => "double time_step"
|
85
84
|
shadow_attr_accessor :zeno_limit => "long zeno_limit"
|
86
85
|
shadow_attr_accessor :step_count => "long step_count"
|
@@ -95,7 +94,7 @@ class World
|
|
95
94
|
"long input_depth_limit"
|
96
95
|
shadow_attr_accessor :alg_depth_limit =>
|
97
96
|
"long alg_depth_limit"
|
98
|
-
|
97
|
+
|
99
98
|
shadow_attr_accessor :base_clock => "double base_clock"
|
100
99
|
shadow_attr_accessor :base_step_count =>
|
101
100
|
"long base_step_count"
|
@@ -118,7 +117,7 @@ class World
|
|
118
117
|
shadow->cv_cache_used = 0;
|
119
118
|
}
|
120
119
|
free_function.free "free(shadow->constant_value_cache)"
|
121
|
-
|
120
|
+
|
122
121
|
shadow_struct.declare :link_cache => %{
|
123
122
|
LinkCacheEntry *link_cache;
|
124
123
|
int link_cache_size;
|
@@ -131,7 +130,7 @@ class World
|
|
131
130
|
shadow->link_cache_used = 0;
|
132
131
|
}
|
133
132
|
free_function.free "free(shadow->link_cache)"
|
134
|
-
|
133
|
+
|
135
134
|
shadow_struct.declare :port_cache => %{
|
136
135
|
PortCacheEntry *port_cache;
|
137
136
|
int port_cache_size;
|
@@ -143,15 +142,15 @@ class World
|
|
143
142
|
shadow->port_cache_used = 0;
|
144
143
|
}
|
145
144
|
free_function.free "free(shadow->port_cache)"
|
146
|
-
|
145
|
+
|
147
146
|
class << self
|
148
147
|
# Redefines World#new so that a library commit happens first.
|
149
148
|
def new(*args, &block)
|
150
|
-
commit # redefines World.new
|
149
|
+
commit # redefines World.new
|
151
150
|
new(*args, &block) # which is what this line calls
|
152
151
|
end
|
153
152
|
end
|
154
|
-
|
153
|
+
|
155
154
|
define_c_method :time_step= do
|
156
155
|
arguments :time_step
|
157
156
|
body %{
|
@@ -163,7 +162,7 @@ class World
|
|
163
162
|
}
|
164
163
|
returns "shadow->time_step" ## needed?
|
165
164
|
end
|
166
|
-
|
165
|
+
|
167
166
|
define_c_method :clock do
|
168
167
|
returns %{
|
169
168
|
rb_float_new(
|
@@ -171,8 +170,8 @@ class World
|
|
171
170
|
(shadow->step_count - shadow->base_step_count) * shadow->time_step)
|
172
171
|
}
|
173
172
|
end
|
174
|
-
|
175
|
-
# This is for when Component#world is nonpersistent
|
173
|
+
|
174
|
+
# This is for when Component#world is nonpersistent
|
176
175
|
# _load_data_method.post_code %{
|
177
176
|
# rb_funcall(shadow->self, #{shadow_library_include_file.declare_symbol "__restore__world__refs"}, 0);
|
178
177
|
# }
|
@@ -180,7 +179,7 @@ class World
|
|
180
179
|
define_c_method :bump_d_tick do
|
181
180
|
body "shadow->d_tick++"
|
182
181
|
end
|
183
|
-
|
182
|
+
|
184
183
|
slif = shadow_library_include_file
|
185
184
|
slif.declare :get_shadow => %{
|
186
185
|
inline static ComponentShadow *get_shadow(VALUE comp)
|
@@ -220,13 +219,13 @@ class World
|
|
220
219
|
}
|
221
220
|
}
|
222
221
|
}
|
223
|
-
|
222
|
+
|
224
223
|
for (shadow->rk_level = 1; shadow->rk_level <= 3; shadow->rk_level++) {
|
225
224
|
len = rs_dv(shadow->diff_list)->len;
|
226
225
|
comp_ary = rs_dv(shadow->diff_list)->ptr;
|
227
226
|
for (ci = 0; ci < len; ci++) {
|
228
227
|
Data_Get_Struct(comp_ary[ci], ComponentShadow, comp_shdw);
|
229
|
-
|
228
|
+
|
230
229
|
if (shadow->rk_level == 1 && !comp_shdw->has_diff) {
|
231
230
|
if (ci < len-1) {
|
232
231
|
comp_ary[ci] = comp_ary[len-1];
|
@@ -250,7 +249,7 @@ class World
|
|
250
249
|
}
|
251
250
|
}
|
252
251
|
}
|
253
|
-
|
252
|
+
|
254
253
|
shadow->rk_level = 4;
|
255
254
|
for (li = 0; li < 2; li++) {
|
256
255
|
len = rs_dv(comp_dvector[li])->len;
|
@@ -266,7 +265,7 @@ class World
|
|
266
265
|
var->rk_level < shadow->rk_level &&
|
267
266
|
!var->algebraic)
|
268
267
|
(*var->flow)((ComponentShadow *)comp_shdw);
|
269
|
-
|
268
|
+
|
270
269
|
if (var->rk_level == 4)
|
271
270
|
var->d_tick = 1; //# var will be current in discrete_step
|
272
271
|
else
|
@@ -289,14 +288,14 @@ class World
|
|
289
288
|
# scope :static
|
290
289
|
# returns "rb_obj_instance_eval(0, 0, comp)"
|
291
290
|
# end
|
292
|
-
#
|
291
|
+
#
|
293
292
|
# shadow_library_source_file.define(:call_block).instance_eval do
|
294
293
|
# arguments "VALUE arg1", "VALUE block"
|
295
294
|
# return_type "VALUE"
|
296
295
|
# scope :static
|
297
296
|
# returns "rb_funcall(block, #{declare_symbol :call}, 0)"
|
298
297
|
# end
|
299
|
-
|
298
|
+
|
300
299
|
discrete_step_definer = proc do
|
301
300
|
parent.declare :static_locals => %{
|
302
301
|
static VALUE ExitState, GuardWrapperClass, ExprWrapperClass;
|
@@ -304,7 +303,7 @@ class World
|
|
304
303
|
static VALUE QMatchClass, ConnectClass;
|
305
304
|
static VALUE PostClass, DynamicEventClass, SyncClass;
|
306
305
|
}.tabto(0)
|
307
|
-
|
306
|
+
|
308
307
|
declare :locals => %{
|
309
308
|
VALUE comp;
|
310
309
|
ComponentShadow *comp_shdw;
|
@@ -315,11 +314,11 @@ class World
|
|
315
314
|
int list_i;
|
316
315
|
int did_reset;
|
317
316
|
}.tabto(0)
|
318
|
-
|
317
|
+
|
319
318
|
insteval_proc = declare_symbol :insteval_proc
|
320
319
|
epi = Component::EventPhaseItem
|
321
320
|
spi = Component::SyncPhaseItem
|
322
|
-
|
321
|
+
|
323
322
|
parent.declare :step_discrete_subs => %{
|
324
323
|
inline static VALUE cur_syncs(ComponentShadow *comp_shdw)
|
325
324
|
{
|
@@ -468,7 +467,7 @@ class World
|
|
468
467
|
}
|
469
468
|
return 1;
|
470
469
|
}
|
471
|
-
|
470
|
+
|
472
471
|
inline static int comp_can_sync(ComponentShadow *comp_shdw,
|
473
472
|
#{World.shadow_struct_name} *shadow)
|
474
473
|
{
|
@@ -476,7 +475,7 @@ class World
|
|
476
475
|
int can_sync = 1;
|
477
476
|
VALUE syncs = cur_syncs(comp_shdw);
|
478
477
|
assert(RTEST(syncs));
|
479
|
-
|
478
|
+
|
480
479
|
for (i = RARRAY_LEN(syncs) - 1; i >= 0; i--) {
|
481
480
|
VALUE sync = RARRAY_PTR(syncs)[i];
|
482
481
|
assert(RARRAY_LEN(sync) == 3);
|
@@ -484,18 +483,18 @@ class World
|
|
484
483
|
VALUE event = RARRAY_PTR(sync)[#{spi::EVENT_IDX}];
|
485
484
|
ComponentShadow *link_shdw =
|
486
485
|
*(ComponentShadow **)(((char *)comp_shdw) + link_offset);
|
487
|
-
|
486
|
+
|
488
487
|
if (!link_shdw || !RTEST(link_shdw->trans)) {
|
489
488
|
can_sync = 0;
|
490
489
|
break;
|
491
490
|
}
|
492
|
-
|
491
|
+
|
493
492
|
int found = 0;
|
494
493
|
VALUE link_events = cur_events(link_shdw);
|
495
494
|
if (RTEST(link_events)) {
|
496
495
|
VALUE *ptr = RARRAY_PTR(link_events);
|
497
496
|
long len = RARRAY_LEN(link_events);
|
498
|
-
|
497
|
+
|
499
498
|
for (j = len; j > 0; j--, ptr++) {
|
500
499
|
VALUE link_event = RARRAY_PTR(*ptr)[#{epi::E_IDX}];
|
501
500
|
if (link_event == event) {
|
@@ -504,23 +503,23 @@ class World
|
|
504
503
|
}
|
505
504
|
}
|
506
505
|
}
|
507
|
-
|
506
|
+
|
508
507
|
if (!found) {
|
509
508
|
can_sync = 0;
|
510
509
|
break;
|
511
510
|
}
|
512
511
|
}
|
513
|
-
|
512
|
+
|
514
513
|
//%% hook_can_sync(comp_shdw->self, INT2BOOL(can_sync));
|
515
514
|
return can_sync;
|
516
515
|
}
|
517
|
-
|
516
|
+
|
518
517
|
inline static int eval_events(ComponentShadow *comp_shdw,
|
519
518
|
#{World.shadow_struct_name} *shadow)
|
520
519
|
{
|
521
520
|
VALUE events = cur_events(comp_shdw);
|
522
521
|
int has_events = RTEST(events);
|
523
|
-
|
522
|
+
|
524
523
|
if (has_events) {
|
525
524
|
VALUE *ptr = RARRAY_PTR(events);
|
526
525
|
long len = RARRAY_LEN(events);
|
@@ -547,13 +546,13 @@ class World
|
|
547
546
|
|
548
547
|
return has_events;
|
549
548
|
}
|
550
|
-
|
549
|
+
|
551
550
|
inline static void cache_new_constant_value(
|
552
551
|
double *dbl_ptr, double value,
|
553
552
|
#{World.shadow_struct_name} *shadow)
|
554
553
|
{
|
555
554
|
CVCacheEntry *entry;
|
556
|
-
|
555
|
+
|
557
556
|
if (!shadow->constant_value_cache) {
|
558
557
|
int n = #{CV_CACHE_SIZE};
|
559
558
|
shadow->constant_value_cache = malloc(n*sizeof(CVCacheEntry));
|
@@ -577,7 +576,7 @@ class World
|
|
577
576
|
entry->value = value;
|
578
577
|
shadow->cv_cache_used += 1;
|
579
578
|
}
|
580
|
-
|
579
|
+
|
581
580
|
inline static int assign_new_constant_values(
|
582
581
|
#{World.shadow_struct_name} *shadow)
|
583
582
|
{
|
@@ -593,16 +592,16 @@ class World
|
|
593
592
|
}
|
594
593
|
shadow->cv_cache_used = 0;
|
595
594
|
}
|
596
|
-
|
595
|
+
|
597
596
|
return did_reset;
|
598
597
|
}
|
599
|
-
|
598
|
+
|
600
599
|
inline static void cache_new_link(
|
601
600
|
ComponentShadow **link_ptr, VALUE value,
|
602
601
|
#{World.shadow_struct_name} *shadow)
|
603
602
|
{
|
604
603
|
LinkCacheEntry *entry;
|
605
|
-
|
604
|
+
|
606
605
|
if (!shadow->link_cache) {
|
607
606
|
int n = #{LINK_CACHE_SIZE};
|
608
607
|
shadow->link_cache = malloc(n*sizeof(LinkCacheEntry));
|
@@ -625,12 +624,12 @@ class World
|
|
625
624
|
entry->value = value;
|
626
625
|
shadow->link_cache_used += 1;
|
627
626
|
}
|
628
|
-
|
627
|
+
|
629
628
|
inline static int assign_new_links(
|
630
629
|
#{World.shadow_struct_name} *shadow)
|
631
630
|
{
|
632
631
|
int did_reset = shadow->link_cache_used;
|
633
|
-
|
632
|
+
|
634
633
|
if (shadow->link_cache_used) {
|
635
634
|
int i;
|
636
635
|
LinkCacheEntry *entry;
|
@@ -646,15 +645,15 @@ class World
|
|
646
645
|
}
|
647
646
|
shadow->link_cache_used = 0;
|
648
647
|
}
|
649
|
-
|
648
|
+
|
650
649
|
return did_reset;
|
651
650
|
}
|
652
|
-
|
651
|
+
|
653
652
|
inline static void cache_new_port(VALUE input_port, VALUE other_port,
|
654
653
|
#{World.shadow_struct_name} *shadow)
|
655
654
|
{
|
656
655
|
PortCacheEntry *entry;
|
657
|
-
|
656
|
+
|
658
657
|
if (!shadow->port_cache) {
|
659
658
|
int n = #{PORT_CACHE_SIZE};
|
660
659
|
shadow->port_cache = malloc(n*sizeof(PortCacheEntry));
|
@@ -677,12 +676,12 @@ class World
|
|
677
676
|
entry->other_port = other_port;
|
678
677
|
shadow->port_cache_used += 1;
|
679
678
|
}
|
680
|
-
|
679
|
+
|
681
680
|
inline static int assign_new_ports(
|
682
681
|
#{World.shadow_struct_name} *shadow)
|
683
682
|
{
|
684
683
|
int did_reset = shadow->port_cache_used;
|
685
|
-
|
684
|
+
|
686
685
|
if (shadow->port_cache_used) {
|
687
686
|
int i;
|
688
687
|
PortCacheEntry *entry;
|
@@ -694,10 +693,10 @@ class World
|
|
694
693
|
}
|
695
694
|
shadow->port_cache_used = 0;
|
696
695
|
}
|
697
|
-
|
696
|
+
|
698
697
|
return did_reset;
|
699
698
|
}
|
700
|
-
|
699
|
+
|
701
700
|
inline static int eval_continuous_resets(ComponentShadow *comp_shdw,
|
702
701
|
#{World.shadow_struct_name} *shadow)
|
703
702
|
{
|
@@ -769,7 +768,7 @@ class World
|
|
769
768
|
}
|
770
769
|
}
|
771
770
|
}
|
772
|
-
|
771
|
+
|
773
772
|
return has_cont_resets;
|
774
773
|
}
|
775
774
|
|
@@ -822,11 +821,11 @@ class World
|
|
822
821
|
new_value, shadow);
|
823
822
|
}
|
824
823
|
}
|
825
|
-
|
824
|
+
|
826
825
|
if (has_link_resets) {
|
827
826
|
VALUE *ptr = RARRAY_PTR(link_resets);
|
828
827
|
long len = RARRAY_LEN(link_resets);
|
829
|
-
|
828
|
+
|
830
829
|
for (i = 0; i < len; i++) {
|
831
830
|
VALUE pair = ptr[i];
|
832
831
|
int offset = NUM2INT(RARRAY_PTR(pair)[0]);
|
@@ -872,10 +871,10 @@ class World
|
|
872
871
|
new_value, shadow);
|
873
872
|
}
|
874
873
|
}
|
875
|
-
|
874
|
+
|
876
875
|
return has_const_resets || has_link_resets;
|
877
876
|
}
|
878
|
-
|
877
|
+
|
879
878
|
inline static int eval_port_connects(ComponentShadow *comp_shdw,
|
880
879
|
#{World.shadow_struct_name} *shadow)
|
881
880
|
{
|
@@ -895,7 +894,7 @@ class World
|
|
895
894
|
VALUE connect_spec = RARRAY_PTR(pair)[1];
|
896
895
|
VALUE input_port;
|
897
896
|
VALUE other_port;
|
898
|
-
|
897
|
+
|
899
898
|
input_port = rb_funcall(comp, #{declare_symbol :port}, 1, input_var);
|
900
899
|
if (connect_spec == Qnil) {
|
901
900
|
other_port = Qnil;
|
@@ -914,7 +913,7 @@ class World
|
|
914
913
|
return 1;
|
915
914
|
}
|
916
915
|
}
|
917
|
-
|
916
|
+
|
918
917
|
inline static int assign_new_cont_values(ComponentShadow *comp_shdw)
|
919
918
|
{
|
920
919
|
VALUE resets = cur_resets(comp_shdw);
|
@@ -947,7 +946,7 @@ class World
|
|
947
946
|
{
|
948
947
|
long i;
|
949
948
|
VALUE comp = comp_shdw->self;
|
950
|
-
|
949
|
+
|
951
950
|
assert(RTEST(actions));
|
952
951
|
|
953
952
|
for (i = 0; i < RARRAY_LEN(actions); i++) {
|
@@ -981,7 +980,7 @@ class World
|
|
981
980
|
}
|
982
981
|
}
|
983
982
|
}
|
984
|
-
|
983
|
+
|
985
984
|
inline static void start_trans(ComponentShadow *comp_shdw,
|
986
985
|
#{World.shadow_struct_name} *shadow,
|
987
986
|
VALUE trans, VALUE dest)
|
@@ -990,7 +989,7 @@ class World
|
|
990
989
|
comp_shdw->dest = dest;
|
991
990
|
//%% hook_start_transition(comp_shdw->self, trans, dest);
|
992
991
|
}
|
993
|
-
|
992
|
+
|
994
993
|
inline static void finish_trans(ComponentShadow *comp_shdw,
|
995
994
|
#{World.shadow_struct_name} *shadow)
|
996
995
|
{ //%% hook_finish_transition(comp_shdw->self, comp_shdw->trans,
|
@@ -1004,19 +1003,19 @@ class World
|
|
1004
1003
|
comp_shdw->trans = Qnil;
|
1005
1004
|
comp_shdw->dest = Qnil;
|
1006
1005
|
}
|
1007
|
-
|
1006
|
+
|
1008
1007
|
inline static void abort_trans(ComponentShadow *comp_shdw)
|
1009
1008
|
{
|
1010
1009
|
comp_shdw->trans = Qnil;
|
1011
1010
|
comp_shdw->dest = Qnil;
|
1012
1011
|
}
|
1013
|
-
|
1012
|
+
|
1014
1013
|
inline static void check_strict(ComponentShadow *comp_shdw)
|
1015
1014
|
{
|
1016
1015
|
ContVar *vars = (ContVar *)&FIRST_CONT_VAR(comp_shdw);
|
1017
1016
|
long count = comp_shdw->var_count;
|
1018
1017
|
long i;
|
1019
|
-
|
1018
|
+
|
1020
1019
|
for(i = 0; i < count; i++) {
|
1021
1020
|
ContVar *var = &vars[i];
|
1022
1021
|
if (var->ck_strict) {
|
@@ -1030,7 +1029,7 @@ class World
|
|
1030
1029
|
}
|
1031
1030
|
}
|
1032
1031
|
}
|
1033
|
-
|
1032
|
+
|
1034
1033
|
inline static void check_guards(#{World.shadow_struct_name} *shadow,
|
1035
1034
|
int sync_retry)
|
1036
1035
|
{
|
@@ -1040,13 +1039,13 @@ class World
|
|
1040
1039
|
int list_i;
|
1041
1040
|
VALUE *ptr;
|
1042
1041
|
long len, cur;
|
1043
|
-
|
1042
|
+
|
1044
1043
|
EACH_COMP_DO(shadow->prev_awake) {
|
1045
1044
|
int enabled = 0;
|
1046
|
-
|
1045
|
+
|
1047
1046
|
if (shadow->discrete_step == 0)
|
1048
1047
|
comp_shdw->checked = 0;
|
1049
|
-
|
1048
|
+
|
1050
1049
|
len = RARRAY_LEN(comp_shdw->outgoing) - 1; //# last is flags
|
1051
1050
|
cur = len;
|
1052
1051
|
|
@@ -1060,20 +1059,20 @@ class World
|
|
1060
1059
|
cur -= 4 * comp_shdw->tmp.trans.idx;
|
1061
1060
|
else
|
1062
1061
|
comp_shdw->tmp.trans.idx = 0;
|
1063
|
-
|
1062
|
+
|
1064
1063
|
while (cur >= 4) {
|
1065
1064
|
VALUE trans, dest, guard, strict;
|
1066
|
-
|
1065
|
+
|
1067
1066
|
strict = ptr[--cur];
|
1068
1067
|
guard = ptr[--cur];
|
1069
|
-
|
1068
|
+
|
1070
1069
|
enabled = !RTEST(guard) ||
|
1071
1070
|
((comp_shdw->checked && RTEST(strict)) ? 0 :
|
1072
1071
|
guard_enabled(comp, guard, shadow->discrete_step));
|
1073
|
-
|
1072
|
+
|
1074
1073
|
//%% hook_eval_guard(comp, guard, INT2BOOL(enabled),
|
1075
1074
|
//%% ptr[cur-2], ptr[cur-1]);
|
1076
|
-
|
1075
|
+
|
1077
1076
|
if (enabled) {
|
1078
1077
|
dest = ptr[--cur];
|
1079
1078
|
trans = ptr[--cur];
|
@@ -1089,7 +1088,7 @@ class World
|
|
1089
1088
|
else
|
1090
1089
|
cur -= 2;
|
1091
1090
|
}
|
1092
|
-
|
1091
|
+
|
1093
1092
|
if (!enabled) {
|
1094
1093
|
VALUE qrc;
|
1095
1094
|
if (comp_shdw->strict)
|
@@ -1106,7 +1105,7 @@ class World
|
|
1106
1105
|
}
|
1107
1106
|
assert(rs_dv(shadow->prev_awake)->len == 0);
|
1108
1107
|
}
|
1109
|
-
|
1108
|
+
|
1110
1109
|
inline static void do_sync_phase(#{World.shadow_struct_name} *shadow)
|
1111
1110
|
{
|
1112
1111
|
VALUE comp;
|
@@ -1114,7 +1113,7 @@ class World
|
|
1114
1113
|
RS_DVector *list;
|
1115
1114
|
int list_i;
|
1116
1115
|
int changed;
|
1117
|
-
|
1116
|
+
|
1118
1117
|
do {
|
1119
1118
|
changed = 0;
|
1120
1119
|
EACH_COMP_DO(shadow->curr_S) {
|
@@ -1127,17 +1126,17 @@ class World
|
|
1127
1126
|
move_comp(comp, shadow->curr_S, shadow->prev_awake);
|
1128
1127
|
}
|
1129
1128
|
}
|
1130
|
-
|
1129
|
+
|
1131
1130
|
assert(rs_dv(shadow->curr_S)->len == 0);
|
1132
1131
|
SWAP_VALUE(shadow->curr_S, shadow->next_S);
|
1133
1132
|
//%% hook_sync_step(shadow->curr_S, INT2BOOL(changed));
|
1134
1133
|
} while (changed);
|
1135
|
-
|
1134
|
+
|
1136
1135
|
move_all_comps(shadow->curr_S, shadow->curr_T);
|
1137
1136
|
}
|
1138
|
-
|
1137
|
+
|
1139
1138
|
}.tabto(0)
|
1140
|
-
|
1139
|
+
|
1141
1140
|
comp_id = declare_class RedShift::Component
|
1142
1141
|
get_const = proc {|k| "rb_const_get(#{comp_id}, #{declare_symbol k})"}
|
1143
1142
|
init %{
|
@@ -1154,7 +1153,7 @@ class World
|
|
1154
1153
|
ExprWrapperClass = #{get_const[:ExprWrapper]};
|
1155
1154
|
DynamicEventClass = #{get_const[:DynamicEventValue]};
|
1156
1155
|
}
|
1157
|
-
|
1156
|
+
|
1158
1157
|
body %{
|
1159
1158
|
//%% hook_begin();
|
1160
1159
|
shadow->zeno_counter = 0;
|
@@ -1162,9 +1161,9 @@ class World
|
|
1162
1161
|
for (shadow->discrete_step = 0 ;; shadow->discrete_step++) {
|
1163
1162
|
//%% hook_begin_step();
|
1164
1163
|
int sync_retry = 0;
|
1165
|
-
|
1164
|
+
|
1166
1165
|
SWAP_VALUE(shadow->prev_awake, shadow->awake);
|
1167
|
-
|
1166
|
+
|
1168
1167
|
while (rs_dv(shadow->prev_awake)->len) {
|
1169
1168
|
//%% hook_enter_guard_phase();
|
1170
1169
|
check_guards(shadow, sync_retry);
|
@@ -1175,7 +1174,7 @@ class World
|
|
1175
1174
|
//%% hook_leave_sync_phase();
|
1176
1175
|
sync_retry = 1;
|
1177
1176
|
}
|
1178
|
-
|
1177
|
+
|
1179
1178
|
if (!rs_dv(shadow->curr_T)->len) {
|
1180
1179
|
//%% hook_end_step();
|
1181
1180
|
break; //# out of main loop
|
@@ -1187,7 +1186,7 @@ class World
|
|
1187
1186
|
rs_dv_push(rs_dv(shadow->active_E), comp);
|
1188
1187
|
//%% hook_end_eval_events(comp);
|
1189
1188
|
}
|
1190
|
-
|
1189
|
+
|
1191
1190
|
//# Export new event values.
|
1192
1191
|
EACH_COMP_DO(shadow->active_E) {
|
1193
1192
|
SWAP_VALUE(comp_shdw->event_values, comp_shdw->next_event_values);
|
@@ -1195,7 +1194,7 @@ class World
|
|
1195
1194
|
}
|
1196
1195
|
SWAP_VALUE(shadow->active_E, shadow->prev_active_E);
|
1197
1196
|
assert(rs_dv(shadow->active_E)->len == 0);
|
1198
|
-
|
1197
|
+
|
1199
1198
|
//%% hook_enter_eval_phase();
|
1200
1199
|
EACH_COMP_DO(shadow->curr_T) {
|
1201
1200
|
//%% hook_begin_eval_resets(comp);
|
@@ -1204,10 +1203,10 @@ class World
|
|
1204
1203
|
eval_constant_resets(comp_shdw, shadow);
|
1205
1204
|
eval_port_connects(comp_shdw, shadow);
|
1206
1205
|
//%% hook_end_eval_resets(comp);
|
1207
|
-
|
1206
|
+
|
1208
1207
|
if (RTEST(cur_actions(comp_shdw)))
|
1209
1208
|
rs_dv_push(rs_dv(shadow->curr_A), comp);
|
1210
|
-
|
1209
|
+
|
1211
1210
|
if (RTEST(cur_posts(comp_shdw)))
|
1212
1211
|
rs_dv_push(rs_dv(shadow->curr_P), comp);
|
1213
1212
|
}
|
@@ -1237,7 +1236,7 @@ class World
|
|
1237
1236
|
}
|
1238
1237
|
rs_dv(shadow->curr_P)->len = 0;
|
1239
1238
|
//%% hook_leave_post_phase();
|
1240
|
-
|
1239
|
+
|
1241
1240
|
EACH_COMP_DO(shadow->curr_T) {
|
1242
1241
|
finish_trans(comp_shdw, shadow);
|
1243
1242
|
}
|
@@ -1246,20 +1245,20 @@ class World
|
|
1246
1245
|
shadow->d_tick++;
|
1247
1246
|
//## replace "1" with "some comp entered new
|
1248
1247
|
//## state with new alg. eqs"
|
1249
|
-
|
1248
|
+
|
1250
1249
|
EACH_COMP_DO(shadow->curr_T) {
|
1251
1250
|
check_strict(comp_shdw);
|
1252
1251
|
//## optimize: only keep comps with var->ck_strict on this list
|
1253
1252
|
//## option to skip this check
|
1254
1253
|
}
|
1255
|
-
|
1254
|
+
|
1256
1255
|
//# Check for zeno problem.
|
1257
1256
|
if (shadow->zeno_limit >= 0) {
|
1258
1257
|
shadow->zeno_counter++;
|
1259
1258
|
if (shadow->zeno_counter > shadow->zeno_limit)
|
1260
1259
|
rb_funcall(shadow->self, #{declare_symbol :step_zeno}, 0);
|
1261
1260
|
}
|
1262
|
-
|
1261
|
+
|
1263
1262
|
EACH_COMP_DO(shadow->curr_T) {
|
1264
1263
|
if (comp_shdw->state == ExitState)
|
1265
1264
|
remove_comp(comp, shadow->curr_T, shadow);
|
@@ -1275,17 +1274,17 @@ class World
|
|
1275
1274
|
RARRAY_LEN(comp_shdw->event_values));
|
1276
1275
|
}
|
1277
1276
|
rs_dv(shadow->prev_active_E)->len = 0;
|
1278
|
-
|
1277
|
+
|
1279
1278
|
//%% hook_end_step();
|
1280
1279
|
}
|
1281
|
-
|
1280
|
+
|
1282
1281
|
move_all_comps(shadow->strict_sleep, shadow->awake);
|
1283
1282
|
|
1284
1283
|
//%% hook_end();
|
1285
1284
|
shadow->discrete_step = 0;
|
1286
1285
|
shadow->zeno_counter = 0;
|
1287
1286
|
}
|
1288
|
-
|
1287
|
+
|
1289
1288
|
# only call this when all defs have been added
|
1290
1289
|
def parent.to_s
|
1291
1290
|
@cached_output ||= super
|
@@ -1294,30 +1293,31 @@ class World
|
|
1294
1293
|
|
1295
1294
|
hook = /\bhook_\w+/
|
1296
1295
|
world_classes = World.subclasses + [World]
|
1297
|
-
hooks = Hash.new {|h,cl| h[cl] =
|
1296
|
+
hooks = Hash.new {|h,cl| h[cl] =
|
1297
|
+
cl.instance_methods(true).grep(hook).sort.map{|s|s.to_sym} }
|
1298
1298
|
hooks[World.superclass] = nil
|
1299
1299
|
known_hooks = nil
|
1300
|
-
|
1300
|
+
|
1301
1301
|
world_classes.each do |cl|
|
1302
1302
|
cl_hooks = hooks[cl]
|
1303
1303
|
next if hooks[cl.superclass] == hooks[cl]
|
1304
|
-
|
1304
|
+
|
1305
1305
|
cl.class_eval do
|
1306
1306
|
shadow_library_source_file.include(Component.shadow_library_include_file)
|
1307
1307
|
shadow_library_source_file.include("dvector/dvector.h")
|
1308
|
-
|
1308
|
+
|
1309
1309
|
if (instance_methods(false) + protected_instance_methods(false) +
|
1310
1310
|
private_instance_methods(false)).grep(/^step_discrete$/).size > 0
|
1311
1311
|
warn "Redefining step_discrete in #{self}"
|
1312
1312
|
end
|
1313
|
-
|
1313
|
+
|
1314
1314
|
meth = define_c_method(:step_discrete, &discrete_step_definer)
|
1315
1315
|
private :step_discrete
|
1316
|
-
|
1316
|
+
|
1317
1317
|
before_commit do
|
1318
1318
|
# at this point, we know the file is complete
|
1319
1319
|
file_str = meth.parent.to_s
|
1320
|
-
|
1320
|
+
|
1321
1321
|
known_hooks ||= file_str.scan(hook).map {|s|s.to_sym}
|
1322
1322
|
unknown_hooks = cl_hooks - known_hooks
|
1323
1323
|
|