redshift 1.3.24 → 1.3.30
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/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
|
|