libfst 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/ext/libfst_rb.c ADDED
@@ -0,0 +1,2525 @@
1
+ /* Copyright (C) 2024 Théotime Bollengier <theotime.bollengier@ensta-bretagne.fr>
2
+ *
3
+ * This file is part of libfst.rb <https://gitlab.ensta-bretagne.fr/bollenth/libfst.rb>
4
+ *
5
+ * libfst.rb is free software: you can redistribute it and/or modify it
6
+ * under the terms of the GNU General Public License as published
7
+ * by the Free Software Foundation, either version 3 of the License,
8
+ * or (at your option) any later version.
9
+ *
10
+ * libfst.rb is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13
+ * See the GNU General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU General Public License
16
+ * along with libfst.rb. If not, see <https://www.gnu.org/licenses/>. 
17
+ */
18
+
19
+ #include <ruby.h>
20
+ #include "fstapi.h"
21
+ #include "ruby/internal/arithmetic/size_t.h"
22
+
23
+
24
+ VALUE m_LibFST;
25
+ VALUE c_Reader;
26
+ VALUE c_RScope;
27
+ VALUE c_RVariable;
28
+ VALUE c_RAttribute;
29
+ VALUE c_RTrace;
30
+ VALUE c_Writer;
31
+ VALUE c_WVariable;
32
+
33
+
34
+ ID id_at_alias_of;
35
+ ID id_at_direction;
36
+ ID id_at_filename;
37
+ ID id_at_handle;
38
+ ID id_at_is_float;
39
+ ID id_at_length;
40
+ ID id_at_name;
41
+ ID id_at_sup_data_type;
42
+ ID id_at_sup_type_str;
43
+ ID id_at_sup_var_type;
44
+ ID id_at_trace;
45
+ ID id_at_traces;
46
+ ID id_at_type;
47
+ ID id_at_value;
48
+ ID id_at_variables;
49
+ ID id_at_writer;
50
+ ID id_to_s;
51
+ ID id_to_f;
52
+ ID id_to_i;
53
+ ID id_rjust;
54
+ ID id_compress_hier;
55
+ ID id_delete;
56
+ ID id_name;
57
+ ID id_component;
58
+ ID id_symbol_plus;
59
+ ID id_symbol_star;
60
+ ID id_symbol_more;
61
+ ID id_expand_path;
62
+ ID id_start_time;
63
+ ID id_end_time;
64
+ ID id_verilog;
65
+ ID id_vhdl;
66
+ ID id_verilog_or_vhdl;
67
+ ID id_vcd_module;
68
+ ID id_vcd_task;
69
+ ID id_vcd_function;
70
+ ID id_vcd_begin;
71
+ ID id_vcd_fork;
72
+ ID id_vcd_generate;
73
+ ID id_vcd_struct;
74
+ ID id_vcd_union;
75
+ ID id_vcd_class;
76
+ ID id_vcd_interface;
77
+ ID id_vcd_package;
78
+ ID id_vcd_program;
79
+ ID id_vhdl_architecture;
80
+ ID id_vhdl_procedure;
81
+ ID id_vhdl_function;
82
+ ID id_vhdl_record;
83
+ ID id_vhdl_process;
84
+ ID id_vhdl_block;
85
+ ID id_vhdl_for_generate;
86
+ ID id_vhdl_if_generate;
87
+ ID id_vhdl_generate;
88
+ ID id_vhdl_package;
89
+ ID id_vcd_event;
90
+ ID id_vcd_integer;
91
+ ID id_vcd_parameter;
92
+ ID id_vcd_real;
93
+ ID id_vcd_real_parameter;
94
+ ID id_vcd_reg;
95
+ ID id_vcd_supply0;
96
+ ID id_vcd_supply1;
97
+ ID id_vcd_time;
98
+ ID id_vcd_tri;
99
+ ID id_vcd_triand;
100
+ ID id_vcd_trior;
101
+ ID id_vcd_trireg;
102
+ ID id_vcd_tri0;
103
+ ID id_vcd_tri1;
104
+ ID id_vcd_wand;
105
+ ID id_vcd_wire;
106
+ ID id_vcd_wor;
107
+ ID id_vcd_port;
108
+ ID id_vcd_sparray;
109
+ ID id_vcd_realtime;
110
+ ID id_gen_string;
111
+ ID id_sv_bit;
112
+ ID id_sv_logic;
113
+ ID id_sv_int;
114
+ ID id_sv_shortint;
115
+ ID id_sv_longint;
116
+ ID id_sv_byte;
117
+ ID id_sv_enum;
118
+ ID id_sv_shortreal;
119
+ ID id_implicit;
120
+ ID id_input;
121
+ ID id_output;
122
+ ID id_inout;
123
+ ID id_buffer;
124
+ ID id_linkage;
125
+ ID id_misc;
126
+ ID id_array;
127
+ ID id_enum;
128
+ ID id_pack;
129
+ ID id_comment;
130
+ ID id_envvar;
131
+ ID id_supvar;
132
+ ID id_pathname;
133
+ ID id_sourcestem;
134
+ ID id_sourceistem;
135
+ ID id_valuelist;
136
+ ID id_enumtable;
137
+ ID id_unknown;
138
+ ID id_none;
139
+ ID id_unpacked;
140
+ ID id_packed;
141
+ ID id_sparse;
142
+ ID id_integer;
143
+ ID id_bit;
144
+ ID id_logic;
145
+ ID id_int;
146
+ ID id_shortint;
147
+ ID id_longint;
148
+ ID id_byte;
149
+ ID id_unsigned_integer;
150
+ ID id_unsigned_bit;
151
+ ID id_unsigned_logic;
152
+ ID id_unsigned_int;
153
+ ID id_unsigned_shortint;
154
+ ID id_unsigned_longint;
155
+ ID id_unsigned_byte;
156
+ ID id_reg;
157
+ ID id_time;
158
+ ID id_tagged_packed;
159
+ ID id_upscope;
160
+ ID id_attrend;
161
+ ID id_zlib;
162
+ ID id_fastlz;
163
+ ID id_lz4;
164
+ ID id_s;
165
+ ID id_ms;
166
+ ID id_us;
167
+ ID id_ns;
168
+ ID id_ps;
169
+ ID id_fs;
170
+ ID id_type;
171
+ ID id_subtype;
172
+ ID id_arg;
173
+ ID id_use_realpath;
174
+ ID id_vhdl_signal;
175
+ ID id_vhdl_variable;
176
+ ID id_vhdl_constant;
177
+ ID id_vhdl_file;
178
+ ID id_vhdl_memory;
179
+ ID id_vhdl_boolean;
180
+ ID id_vhdl_bit;
181
+ ID id_vhdl_bit_vector;
182
+ ID id_vhdl_std_ulogic;
183
+ ID id_vhdl_std_ulogic_vector;
184
+ ID id_vhdl_std_logic;
185
+ ID id_vhdl_std_logic_vector;
186
+ ID id_vhdl_unsigned;
187
+ ID id_vhdl_signed;
188
+ ID id_vhdl_integer;
189
+ ID id_vhdl_real;
190
+ ID id_vhdl_natural;
191
+ ID id_vhdl_positive;
192
+ ID id_vhdl_time;
193
+ ID id_vhdl_character;
194
+ ID id_vhdl_string;
195
+ ID id_direction;
196
+ ID id_length;
197
+ ID id_alias_of;
198
+ ID id_sup_type_str;
199
+ ID id_sup_var_type;
200
+ ID id_sup_data_type;
201
+
202
+
203
+ static uint64_t rb_to_uint64t(VALUE num)
204
+ {
205
+ uint64_t r = (uint64_t)NUM2ULL(num);
206
+ VALUE zero = INT2NUM(0);
207
+ if (rb_funcallv(zero, id_symbol_more, 1, &num) == Qtrue)
208
+ rb_raise(rb_eRuntimeError, "number must be positive");
209
+ return r;
210
+ }
211
+
212
+
213
+ static int rb_to_boolean(VALUE enable)
214
+ {
215
+ int r;
216
+ if (enable == Qtrue)
217
+ r = 1;
218
+ else if (enable == Qfalse)
219
+ r = 0;
220
+ else
221
+ rb_raise(rb_eTypeError, "expecting true or false, not a %s", rb_obj_classname(enable));
222
+ return r;
223
+ }
224
+
225
+
226
+ static unsigned int rb_to_unsigned_int(VALUE num)
227
+ {
228
+ unsigned int r = (unsigned int)NUM2ULONG(num);
229
+ VALUE zero = INT2NUM(0);
230
+ if (rb_funcallv(zero, id_symbol_more, 1, &num) == Qtrue)
231
+ rb_raise(rb_eRuntimeError, "number must be positive");
232
+ return r;
233
+
234
+ }
235
+
236
+
237
+ typedef struct {
238
+ void *ctx;
239
+ } fstreaderctx_t;
240
+
241
+
242
+ static void libfst_reader_free(void *p)
243
+ {
244
+ fstreaderctx_t *rctx = (fstreaderctx_t*)p;
245
+
246
+ if (rctx) {
247
+ fstReaderClose(rctx->ctx);
248
+ free(rctx);
249
+ }
250
+ }
251
+
252
+
253
+ static size_t libfst_reader_size(const void *p)
254
+ {
255
+ (void)p;
256
+ return sizeof(fstreaderctx_t);
257
+ }
258
+
259
+
260
+ const rb_data_type_t libfst_reader_type = {
261
+ .wrap_struct_name = "LibFST::Reader",
262
+ .function = {
263
+ .dmark = NULL,
264
+ .dfree = libfst_reader_free,
265
+ .dsize = libfst_reader_size,
266
+ },
267
+ .parent = NULL,
268
+ .data = NULL,
269
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY
270
+ };
271
+
272
+
273
+ inline void* libfst_reader_from_rbobj(VALUE obj) {
274
+ fstreaderctx_t *rctx;
275
+ TypedData_Get_Struct(obj, fstreaderctx_t, &libfst_reader_type, rctx);
276
+ return rctx->ctx;
277
+ }
278
+
279
+
280
+ static VALUE libfst_reader_alloc(VALUE klass)
281
+ {
282
+ fstreaderctx_t *rctx = malloc(sizeof(fstreaderctx_t));
283
+ rctx->ctx = NULL;
284
+ return TypedData_Wrap_Struct(klass, &libfst_reader_type, rctx);
285
+ }
286
+
287
+
288
+ /* @param filename [String] Path of the FST file to open.
289
+ * @return [self]
290
+ */
291
+ static VALUE libfst_reader_open(VALUE self, VALUE filename)
292
+ {
293
+ if (!rb_obj_is_kind_of(filename, rb_cString))
294
+ rb_raise(rb_eRuntimeError, "Expecting a String, not a %s", rb_obj_classname(filename));
295
+ const char *fname = rb_string_value_cstr(&filename);
296
+
297
+ fstreaderctx_t *rctx;
298
+ TypedData_Get_Struct(self, fstreaderctx_t, &libfst_reader_type, rctx);
299
+ rctx->ctx = fstReaderOpen(fname);
300
+
301
+ if (!rctx->ctx)
302
+ rb_raise(rb_eRuntimeError, "cannot read file \"%s\"", fname);
303
+
304
+ fstReaderIterBlocksSetNativeDoublesOnCallback(rctx->ctx, 1);
305
+
306
+ return self;
307
+ }
308
+
309
+
310
+ /* Returns the number of variables which point to the same trace.
311
+ * @return [Integer]
312
+ */
313
+ static VALUE libfst_reader_alias_count(VALUE self)
314
+ {
315
+ void *ctx = libfst_reader_from_rbobj(self);
316
+ uint64_t alias_count = fstReaderGetAliasCount(ctx);
317
+ return RB_ULL2NUM(alias_count);
318
+ }
319
+
320
+
321
+ /* @return [Integer]
322
+ */
323
+ static VALUE libfst_reader_current_scope_length(VALUE self)
324
+ {
325
+ return RB_INT2NUM(fstReaderGetCurrentScopeLen(libfst_reader_from_rbobj(self)));
326
+ }
327
+
328
+
329
+ /* @return [String]
330
+ */
331
+ static VALUE libfst_reader_current_flat_scope(VALUE self)
332
+ {
333
+ void *ctx = libfst_reader_from_rbobj(self);
334
+ const char* str = fstReaderGetCurrentFlatScope(ctx);
335
+ return rb_utf8_str_new_cstr(str);
336
+ }
337
+
338
+
339
+ /* Date string produced by the writer of the FST file
340
+ * @return [String]
341
+ */
342
+ static VALUE libfst_reader_date_string(VALUE self)
343
+ {
344
+ void *ctx = libfst_reader_from_rbobj(self);
345
+ const char* str = fstReaderGetDateString(ctx);
346
+ return rb_utf8_str_new_cstr(str);
347
+ }
348
+
349
+
350
+ /* Version string produced by the writer of the FST file
351
+ * @return [String]
352
+ */
353
+ static VALUE libfst_reader_version_string(VALUE self)
354
+ {
355
+ void *ctx = libfst_reader_from_rbobj(self);
356
+ const char* str = fstReaderGetVersionString(ctx);
357
+ return rb_utf8_str_new_cstr(str);
358
+ }
359
+
360
+
361
+ /* Returns the number of variables.
362
+ * @return [Integer]
363
+ */
364
+ static VALUE libfst_reader_var_count(VALUE self)
365
+ {
366
+ void *ctx = libfst_reader_from_rbobj(self);
367
+ uint64_t i = fstReaderGetVarCount(ctx);
368
+ return RB_ULL2NUM(i);
369
+ }
370
+
371
+
372
+ /* @return [Integer]
373
+ */
374
+ static VALUE libfst_reader_start_time(VALUE self)
375
+ {
376
+ void *ctx = libfst_reader_from_rbobj(self);
377
+ uint64_t i = fstReaderGetStartTime(ctx);
378
+ return RB_ULL2NUM(i);
379
+ }
380
+
381
+
382
+ /* @return [Integer]
383
+ */
384
+ static VALUE libfst_reader_end_time(VALUE self)
385
+ {
386
+ void *ctx = libfst_reader_from_rbobj(self);
387
+ uint64_t i = fstReaderGetEndTime(ctx);
388
+ return RB_ULL2NUM(i);
389
+ }
390
+
391
+
392
+ /* @return [Integer]
393
+ */
394
+ static VALUE libfst_reader_time_zero(VALUE self)
395
+ {
396
+ void *ctx = libfst_reader_from_rbobj(self);
397
+ uint64_t i = fstReaderGetTimezero(ctx);
398
+ return RB_ULL2NUM(i);
399
+ }
400
+
401
+
402
+ /* @return [Symbol] Either `:verilog`, `:vhdl` or `:verilog_or_vhdl`.
403
+ */
404
+ static VALUE libfst_reader_file_type(VALUE self)
405
+ {
406
+ void *ctx = libfst_reader_from_rbobj(self);
407
+ int ft = fstReaderGetFileType(ctx);
408
+ ID id;
409
+ switch (ft) {
410
+ case FST_FT_VERILOG:
411
+ id = id_verilog;
412
+ break;
413
+ case FST_FT_VHDL:
414
+ id = id_vhdl;
415
+ break;
416
+ case FST_FT_VERILOG_VHDL:
417
+ id = id_verilog_or_vhdl;
418
+ break;
419
+ default:
420
+ rb_raise(rb_eRuntimeError, "Unknown file type %d", ft);
421
+ }
422
+ return rb_id2sym(id);
423
+ }
424
+
425
+
426
+ /* @return [Integer]
427
+ */
428
+ static VALUE libfst_reader_memory_used_by_writer(VALUE self)
429
+ {
430
+ void *ctx = libfst_reader_from_rbobj(self);
431
+ uint64_t i = fstReaderGetMemoryUsedByWriter(ctx);
432
+ return RB_ULL2NUM(i);
433
+ }
434
+
435
+
436
+ /* @return [Integer]
437
+ */
438
+ static VALUE libfst_reader_scope_count(VALUE self)
439
+ {
440
+ void *ctx = libfst_reader_from_rbobj(self);
441
+ uint64_t i = fstReaderGetScopeCount(ctx);
442
+ return RB_ULL2NUM(i);
443
+ }
444
+
445
+
446
+ /* @return [Integer]
447
+ */
448
+ static VALUE libfst_reader_value_change_section_count(VALUE self)
449
+ {
450
+ void *ctx = libfst_reader_from_rbobj(self);
451
+ uint64_t i = fstReaderGetValueChangeSectionCount(ctx);
452
+ return RB_ULL2NUM(i);
453
+ }
454
+
455
+
456
+ /* @return [Integer]
457
+ */
458
+ static VALUE libfst_reader_number_dump_activity_changes(VALUE self)
459
+ {
460
+ void *ctx = libfst_reader_from_rbobj(self);
461
+ uint32_t i = fstReaderGetNumberDumpActivityChanges(ctx);
462
+ return RB_ULL2NUM(i);
463
+ }
464
+
465
+
466
+ /* @return [Boolean]
467
+ */
468
+ static VALUE libfst_reader_fseek_failed(VALUE self)
469
+ {
470
+ void *ctx = libfst_reader_from_rbobj(self);
471
+ return (fstReaderGetFseekFailed(ctx) ? Qtrue : Qfalse);
472
+ }
473
+
474
+
475
+ /* @return [Boolean]
476
+ */
477
+ static VALUE libfst_reader_double_endian_match_state(VALUE self)
478
+ {
479
+ void *ctx = libfst_reader_from_rbobj(self);
480
+ return (fstReaderGetDoubleEndianMatchState(ctx) ? Qtrue : Qfalse);
481
+ }
482
+
483
+
484
+ /* Returns the time scale exponent.
485
+ *
486
+ * Real time is `integer_time * 10^time_scale_exponent`.
487
+ * @return [Integer]
488
+ */
489
+ static VALUE libfst_reader_time_scale_exponent(VALUE self)
490
+ {
491
+ return INT2NUM((int)fstReaderGetTimescale(libfst_reader_from_rbobj(self)));
492
+ }
493
+
494
+
495
+ /* @return [Float]
496
+ */
497
+ static VALUE libfst_reader_time_scale(VALUE self)
498
+ {
499
+ void *ctx = libfst_reader_from_rbobj(self);
500
+ signed char s = fstReaderGetTimescale(ctx);
501
+ double d = 1.0;
502
+ switch (s) {
503
+ case 2: d = 100.0; break;
504
+ case 1: d = 10.0; break;
505
+ case 0: d = 1.0; break;
506
+ case -1: d = 100e-3; break;
507
+ case -2: d = 10e-3; break;
508
+ case -3: d = 1e-3; break;
509
+ case -4: d = 100e-6; break;
510
+ case -5: d = 10e-6; break;
511
+ case -6: d = 1e-6; break;
512
+ case -7: d = 100e-9; break;
513
+ case -8: d = 10e-9; break;
514
+ case -9: d = 1e-9; break;
515
+ case -10: d = 100e-12; break;
516
+ case -11: d = 10e-12; break;
517
+ case -12: d = 1e-12; break;
518
+ case -13: d = 100e-15; break;
519
+ case -14: d = 10e-15; break;
520
+ case -15: d = 1e-15; break;
521
+ default:
522
+ d = pow(10.0, (double)s);
523
+ }
524
+ return DBL2NUM(d);
525
+ }
526
+
527
+
528
+ /* @return [String, nil]
529
+ */
530
+ static VALUE libfst_reader_pop_scope(VALUE self)
531
+ {
532
+ void *ctx = libfst_reader_from_rbobj(self);
533
+ const char* str = fstReaderPopScope(ctx);
534
+ if (!str) return Qnil;
535
+ return rb_utf8_str_new_cstr(str);
536
+ }
537
+
538
+
539
+ /* @return [self]
540
+ */
541
+ static VALUE libfst_reader_reset_scope(VALUE self)
542
+ {
543
+ void *ctx = libfst_reader_from_rbobj(self);
544
+ fstReaderResetScope(ctx);
545
+ return self;
546
+ }
547
+
548
+
549
+ /* @return [String, nil]
550
+ * @overload push_scope(name=nil)
551
+ * @param name [String,nil]
552
+ */
553
+ static VALUE libfst_reader_push_scope(int argc, VALUE *argv, VALUE self)
554
+ {
555
+ void *ctx = libfst_reader_from_rbobj(self);
556
+ VALUE name_rb = Qnil;
557
+ const char *name_c = "";
558
+ rb_scan_args(argc, argv, "01", &name_rb);
559
+ if (!NIL_P(name_rb)) {
560
+ if (!rb_obj_is_kind_of(name_rb, rb_cString))
561
+ rb_raise(rb_eTypeError, "expecting a string, not a %s\n", rb_obj_classname(name_rb));
562
+ name_c = rb_string_value_cstr(&name_rb);
563
+ }
564
+ const char *str = fstReaderPushScope(ctx, name_c, NULL);
565
+ if (!str) return Qnil;
566
+ return rb_utf8_str_new_cstr(str);
567
+ }
568
+
569
+
570
+ /* @return [Integer]
571
+ */
572
+ static VALUE libfst_reader_iterate_hier_rewind(VALUE self)
573
+ {
574
+ void *ctx = libfst_reader_from_rbobj(self);
575
+ int r = fstReaderIterateHierRewind(ctx);
576
+ return INT2NUM(r);
577
+ }
578
+
579
+
580
+ static VALUE fstScopeType_to_symbol(enum fstScopeType t)
581
+ {
582
+ ID id;
583
+ switch (t) {
584
+ case FST_ST_VCD_MODULE: id = id_vcd_module; break;
585
+ case FST_ST_VCD_TASK: id = id_vcd_task; break;
586
+ case FST_ST_VCD_FUNCTION: id = id_vcd_function; break;
587
+ case FST_ST_VCD_BEGIN: id = id_vcd_begin; break;
588
+ case FST_ST_VCD_FORK: id = id_vcd_fork; break;
589
+ case FST_ST_VCD_GENERATE: id = id_vcd_generate; break;
590
+ case FST_ST_VCD_STRUCT: id = id_vcd_struct; break;
591
+ case FST_ST_VCD_UNION: id = id_vcd_union; break;
592
+ case FST_ST_VCD_CLASS: id = id_vcd_class; break;
593
+ case FST_ST_VCD_INTERFACE: id = id_vcd_interface; break;
594
+ case FST_ST_VCD_PACKAGE: id = id_vcd_package; break;
595
+ case FST_ST_VCD_PROGRAM: id = id_vcd_program; break;
596
+ case FST_ST_VHDL_ARCHITECTURE: id = id_vhdl_architecture; break;
597
+ case FST_ST_VHDL_PROCEDURE: id = id_vhdl_procedure; break;
598
+ case FST_ST_VHDL_FUNCTION: id = id_vhdl_function; break;
599
+ case FST_ST_VHDL_RECORD: id = id_vhdl_record; break;
600
+ case FST_ST_VHDL_PROCESS: id = id_vhdl_process; break;
601
+ case FST_ST_VHDL_BLOCK: id = id_vhdl_block; break;
602
+ case FST_ST_VHDL_FOR_GENERATE: id = id_vhdl_for_generate; break;
603
+ case FST_ST_VHDL_IF_GENERATE: id = id_vhdl_if_generate; break;
604
+ case FST_ST_VHDL_GENERATE: id = id_vhdl_generate; break;
605
+ case FST_ST_VHDL_PACKAGE: id = id_vhdl_package; break;
606
+ default: return Qnil;
607
+ }
608
+ return rb_id2sym(id);
609
+ }
610
+
611
+
612
+ static VALUE libfst_readerscope_from_struct(const struct fstHier *scop_hier)
613
+ {
614
+ VALUE args[3];
615
+ args[0] = fstScopeType_to_symbol(scop_hier->u.scope.typ);
616
+ args[1] = rb_utf8_str_new(scop_hier->u.scope.name, scop_hier->u.scope.name_length);
617
+ if (scop_hier->u.scope.component_length)
618
+ args[2] = rb_utf8_str_new(scop_hier->u.scope.component, scop_hier->u.scope.component_length);
619
+ else
620
+ args[2] = Qnil;
621
+ return rb_class_new_instance(3, args, c_RScope);
622
+ }
623
+
624
+
625
+ static VALUE fstVarType_to_symbol(enum fstVarType t)
626
+ {
627
+ ID id;
628
+ switch (t) {
629
+ case FST_VT_VCD_EVENT: id = id_vcd_event; break;
630
+ case FST_VT_VCD_INTEGER: id = id_vcd_integer; break;
631
+ case FST_VT_VCD_PARAMETER: id = id_vcd_parameter; break;
632
+ case FST_VT_VCD_REAL: id = id_vcd_real; break;
633
+ case FST_VT_VCD_REAL_PARAMETER: id = id_vcd_real_parameter; break;
634
+ case FST_VT_VCD_REG: id = id_vcd_reg; break;
635
+ case FST_VT_VCD_SUPPLY0: id = id_vcd_supply0; break;
636
+ case FST_VT_VCD_SUPPLY1: id = id_vcd_supply1; break;
637
+ case FST_VT_VCD_TIME: id = id_vcd_time; break;
638
+ case FST_VT_VCD_TRI: id = id_vcd_tri; break;
639
+ case FST_VT_VCD_TRIAND: id = id_vcd_triand; break;
640
+ case FST_VT_VCD_TRIOR: id = id_vcd_trior; break;
641
+ case FST_VT_VCD_TRIREG: id = id_vcd_trireg; break;
642
+ case FST_VT_VCD_TRI0: id = id_vcd_tri0; break;
643
+ case FST_VT_VCD_TRI1: id = id_vcd_tri1; break;
644
+ case FST_VT_VCD_WAND: id = id_vcd_wand; break;
645
+ case FST_VT_VCD_WIRE: id = id_vcd_wire; break;
646
+ case FST_VT_VCD_WOR: id = id_vcd_wor; break;
647
+ case FST_VT_VCD_PORT: id = id_vcd_port; break;
648
+ case FST_VT_VCD_SPARRAY: id = id_vcd_sparray; break;
649
+ case FST_VT_VCD_REALTIME: id = id_vcd_realtime; break;
650
+ case FST_VT_GEN_STRING: id = id_gen_string; break;
651
+ case FST_VT_SV_BIT: id = id_sv_bit; break;
652
+ case FST_VT_SV_LOGIC: id = id_sv_logic; break;
653
+ case FST_VT_SV_INT: id = id_sv_int; break;
654
+ case FST_VT_SV_SHORTINT: id = id_sv_shortint; break;
655
+ case FST_VT_SV_LONGINT: id = id_sv_longint; break;
656
+ case FST_VT_SV_BYTE: id = id_sv_byte; break;
657
+ case FST_VT_SV_ENUM: id = id_sv_enum; break;
658
+ case FST_VT_SV_SHORTREAL: id = id_sv_shortreal; break;
659
+ default: return Qnil;
660
+ }
661
+ return rb_id2sym(id);
662
+ }
663
+
664
+
665
+ static VALUE fstVarDir_to_symbol(enum fstVarDir d)
666
+ {
667
+ ID id;
668
+ switch (d) {
669
+ case FST_VD_IMPLICIT: id = id_implicit; break;
670
+ case FST_VD_INPUT: id = id_input; break;
671
+ case FST_VD_OUTPUT: id = id_output; break;
672
+ case FST_VD_INOUT: id = id_inout; break;
673
+ case FST_VD_BUFFER: id = id_buffer; break;
674
+ case FST_VD_LINKAGE: id = id_linkage; break;
675
+ default: return Qnil;
676
+ }
677
+ return rb_id2sym(id);
678
+ }
679
+
680
+
681
+ static VALUE libfst_readervar_from_struct(const struct fstHier *var_hier)
682
+ {
683
+ VALUE args[6];
684
+ args[0] = fstVarType_to_symbol(var_hier->u.var.typ);
685
+ args[1] = fstVarDir_to_symbol(var_hier->u.var.direction);
686
+ args[2] = rb_utf8_str_new(var_hier->u.var.name, var_hier->u.var.name_length);
687
+ args[3] = ULONG2NUM(var_hier->u.var.length);
688
+ args[4] = ULONG2NUM(var_hier->u.var.handle);
689
+ args[5] = var_hier->u.var.is_alias ? Qtrue : Qfalse;
690
+ return rb_class_new_instance(6, args, c_RVariable);
691
+ }
692
+
693
+
694
+ static void fstAttrType_to_symbol(enum fstAttrType t, unsigned char sbtp, VALUE *type, VALUE *subtype)
695
+ {
696
+ switch (t) {
697
+ case FST_AT_MISC:
698
+ *type = rb_id2sym(id_misc);
699
+ switch (sbtp) {
700
+ case FST_MT_COMMENT: *subtype = rb_id2sym(id_comment); break;
701
+ case FST_MT_ENVVAR: *subtype = rb_id2sym(id_envvar); break;
702
+ case FST_MT_SUPVAR: *subtype = rb_id2sym(id_supvar); break;
703
+ case FST_MT_PATHNAME: *subtype = rb_id2sym(id_pathname); break;
704
+ case FST_MT_SOURCESTEM: *subtype = rb_id2sym(id_sourcestem); break;
705
+ case FST_MT_SOURCEISTEM: *subtype = rb_id2sym(id_sourceistem); break;
706
+ case FST_MT_VALUELIST: *subtype = rb_id2sym(id_valuelist); break;
707
+ case FST_MT_ENUMTABLE: *subtype = rb_id2sym(id_enumtable); break;
708
+ case FST_MT_UNKNOWN: *subtype = rb_id2sym(id_unknown); break;
709
+ default: *subtype = Qnil;
710
+ }
711
+ break;
712
+ case FST_AT_ARRAY:
713
+ *type = rb_id2sym(id_array);
714
+ switch (sbtp) {
715
+ case FST_AR_NONE: *subtype = rb_id2sym(id_none); break;
716
+ case FST_AR_UNPACKED: *subtype = rb_id2sym(id_unpacked); break;
717
+ case FST_AR_PACKED: *subtype = rb_id2sym(id_packed); break;
718
+ case FST_AR_SPARSE: *subtype = rb_id2sym(id_sparse); break;
719
+ default: *subtype = Qnil;
720
+ }
721
+ break;
722
+ case FST_AT_ENUM:
723
+ *type = rb_id2sym(id_enum);
724
+ switch (sbtp) {
725
+ case FST_EV_SV_INTEGER: *subtype = rb_id2sym(id_integer); break;
726
+ case FST_EV_SV_BIT: *subtype = rb_id2sym(id_bit); break;
727
+ case FST_EV_SV_LOGIC: *subtype = rb_id2sym(id_logic); break;
728
+ case FST_EV_SV_INT: *subtype = rb_id2sym(id_int); break;
729
+ case FST_EV_SV_SHORTINT: *subtype = rb_id2sym(id_shortint); break;
730
+ case FST_EV_SV_LONGINT: *subtype = rb_id2sym(id_longint); break;
731
+ case FST_EV_SV_BYTE: *subtype = rb_id2sym(id_byte); break;
732
+ case FST_EV_SV_UNSIGNED_INTEGER: *subtype = rb_id2sym(id_unsigned_integer); break;
733
+ case FST_EV_SV_UNSIGNED_BIT: *subtype = rb_id2sym(id_unsigned_bit); break;
734
+ case FST_EV_SV_UNSIGNED_LOGIC: *subtype = rb_id2sym(id_unsigned_logic); break;
735
+ case FST_EV_SV_UNSIGNED_INT: *subtype = rb_id2sym(id_unsigned_int); break;
736
+ case FST_EV_SV_UNSIGNED_SHORTINT: *subtype = rb_id2sym(id_unsigned_shortint); break;
737
+ case FST_EV_SV_UNSIGNED_LONGINT: *subtype = rb_id2sym(id_unsigned_longint); break;
738
+ case FST_EV_SV_UNSIGNED_BYTE: *subtype = rb_id2sym(id_unsigned_byte); break;
739
+ case FST_EV_REG: *subtype = rb_id2sym(id_reg); break;
740
+ case FST_EV_TIME: *subtype = rb_id2sym(id_time); break;
741
+ default: *subtype = Qnil;
742
+ }
743
+ break;
744
+ case FST_AT_PACK:
745
+ *type = rb_id2sym(id_pack);
746
+ switch (sbtp) {
747
+ case FST_PT_NONE: *subtype = rb_id2sym(id_none); break;
748
+ case FST_PT_UNPACKED: *subtype = rb_id2sym(id_unpacked); break;
749
+ case FST_PT_PACKED: *subtype = rb_id2sym(id_packed); break;
750
+ case FST_PT_TAGGED_PACKED: *subtype = rb_id2sym(id_tagged_packed); break;
751
+ default: *subtype = Qnil;
752
+ }
753
+ break;
754
+ default:
755
+ *type = Qnil;
756
+ *subtype = Qnil;
757
+ }
758
+ }
759
+
760
+
761
+ static VALUE libfst_readerattr_from_struct(const struct fstHier *attr_hier)
762
+ {
763
+ VALUE args[5];
764
+ fstAttrType_to_symbol(attr_hier->u.attr.typ, attr_hier->u.attr.subtype, &args[0], &args[1]);
765
+ args[2] = rb_utf8_str_new(attr_hier->u.attr.name, attr_hier->u.attr.name_length);
766
+ args[3] = ULL2NUM(attr_hier->u.attr.arg);
767
+ args[4] = ULL2NUM(attr_hier->u.attr.arg_from_name);
768
+ return rb_class_new_instance(5, args, c_RAttribute);
769
+ }
770
+
771
+
772
+ /* Iterate through the hierarchy.
773
+ * Successively call this method until it returns `nil`.
774
+ * @return [Scope,Variable,Attribute,Symbol,nil] This method can return a {Scope}, a {Variable}, an {Attribute} or the symbol `:upscope` or `:attrend`
775
+ */
776
+ static VALUE libfst_reader_iterate_hier(VALUE self)
777
+ {
778
+ void *ctx = libfst_reader_from_rbobj(self);
779
+ struct fstHier *hier = fstReaderIterateHier(ctx);
780
+ if (!hier) return Qnil;
781
+ VALUE r = Qnil;
782
+ switch (hier->htyp) {
783
+ case FST_HT_SCOPE: r = libfst_readerscope_from_struct(hier); break;
784
+ case FST_HT_UPSCOPE: r = rb_id2sym(id_upscope); break;
785
+ case FST_HT_VAR: r = libfst_readervar_from_struct(hier); break;
786
+ case FST_HT_ATTRBEGIN: r = libfst_readerattr_from_struct(hier); break;
787
+ case FST_HT_ATTREND: r = rb_id2sym(id_attrend); break;
788
+ }
789
+ return r;
790
+ }
791
+
792
+
793
+ /* Variable handles are integers from 1 to `max_handle` inclusive.
794
+ * @return [Integer]
795
+ */
796
+ static VALUE libfst_reader_max_handle(VALUE self)
797
+ {
798
+ void *ctx = libfst_reader_from_rbobj(self);
799
+ return ULONG2NUM(fstReaderGetMaxHandle(ctx));
800
+ }
801
+
802
+
803
+ /* @return [Integer]
804
+ */
805
+ static VALUE libfst_reader_dump_activity_change_time(VALUE self, VALUE idx)
806
+ {
807
+ void *ctx = libfst_reader_from_rbobj(self);
808
+ uint32_t x = NUM2ULONG(idx);
809
+ uint64_t t = fstReaderGetDumpActivityChangeTime(ctx, x);
810
+ return ULL2NUM(t);
811
+ }
812
+
813
+
814
+ /* @return [Integer]
815
+ */
816
+ static VALUE libfst_reader_dump_activity_change_value(VALUE self, VALUE idx)
817
+ {
818
+ void *ctx = libfst_reader_from_rbobj(self);
819
+ uint32_t x = NUM2ULONG(idx);
820
+ int t = fstReaderGetDumpActivityChangeValue(ctx, x);
821
+ return INT2NUM(t);
822
+ }
823
+
824
+
825
+ typedef struct {
826
+ VALUE reader;
827
+ VALUE proc;
828
+ uint64_t start_time;
829
+ uint64_t end_time;
830
+ int limit_time;
831
+ } libfst_reader_value_change_callback_arg_t;
832
+
833
+
834
+ static void libfst_reader_value_change_callback_varlen(void *userdata, uint64_t time, fstHandle facidx, const unsigned char *value, uint32_t len)
835
+ {
836
+ libfst_reader_value_change_callback_arg_t *arg = userdata;
837
+ if (arg->limit_time && (time < arg->start_time || time > arg->end_time))
838
+ return;
839
+ VALUE time_rb = ULL2NUM(time);
840
+ VALUE trace = rb_ary_entry(rb_ivar_get(arg->reader, id_at_traces), (int)facidx - 1);
841
+ VALUE value_rb;
842
+ if (rb_ivar_get(trace, id_at_is_float) == Qtrue) {
843
+ value_rb = DBL2NUM(*(double*)value);
844
+ } else if (len > 0) {
845
+ value_rb = rb_str_new((const char*)value, len);
846
+ } else {
847
+ value_rb = rb_str_new_cstr((const char*)value);
848
+ }
849
+ VALUE args = rb_ary_new_from_args(4, trace, time_rb, value_rb, arg->reader);
850
+ rb_proc_call(arg->proc, args);
851
+ }
852
+
853
+
854
+ static void libfst_reader_value_change_callback(void *userdata, uint64_t time, fstHandle facidx, const unsigned char *value)
855
+ {
856
+ libfst_reader_value_change_callback_varlen(userdata, time, facidx, value, 0);
857
+ }
858
+
859
+
860
+ /* Read the value changes of the traces.
861
+ *
862
+ * The provided block is called for each value change found in the file.
863
+ *
864
+ * If signals are specified, the block will be called only for thoses signals.
865
+ *
866
+ * If a start time and/or an end time are specified, only value changes in this time window will be searched.
867
+ *
868
+ * @return [Integer]
869
+ * @overload read(*signals, start_time: nil, end_time: nil)
870
+ * @param signals [Trace,Variable,Scope,Integer] List of signals to be read. Either a trace, its handle, a variable or a scope. If no signal is specified, all signals are read.
871
+ * @param sart_time [Integer, Float, nil] Start time, either as an integer (in magnitude of {time_scale}) or real time as a float.
872
+ * @param end_time [Integer, Float, nil] End time, either as an integer (in magnitude of {time_scale}) or real time as a float.
873
+ * @yieldparam trace [Trace]
874
+ * @yieldparam time [Integer]
875
+ * @yieldparam value [String,Float]
876
+ * @yieldparam reader [self]
877
+ */
878
+ static VALUE libfst_reader_read(int argc, VALUE *argv, VALUE self)
879
+ {
880
+ void *ctx = libfst_reader_from_rbobj(self);
881
+ VALUE blk;
882
+ VALUE splat;
883
+ VALUE kw;
884
+ const ID kwkeys[2] = {id_start_time, id_end_time};
885
+ VALUE kwvalues[2] = {Qundef, Qundef};
886
+ uint64_t start_time, end_time;
887
+ libfst_reader_value_change_callback_arg_t cbarg;
888
+
889
+
890
+ rb_scan_args(argc, argv, "*:&", &splat, &kw, &blk);
891
+
892
+ if (NIL_P(blk))
893
+ rb_raise(rb_eRuntimeError, "read expects a block");
894
+
895
+ if (!NIL_P(kw)) {
896
+ rb_get_kwargs(kw, kwkeys, 0, 2, kwvalues);
897
+
898
+ if (kwvalues[0] == Qundef || NIL_P(kwvalues[0]))
899
+ start_time = 0;
900
+ else if (rb_obj_is_kind_of(kwvalues[0], rb_cInteger))
901
+ start_time = NUM2ULL(kwvalues[0]);
902
+ else if (rb_obj_is_kind_of(kwvalues[0], rb_cFloat))
903
+ start_time = (uint64_t)floor(NUM2DBL(kwvalues[0]) / NUM2DBL(libfst_reader_time_scale(self)));
904
+ else
905
+ rb_raise(rb_eTypeError, "expecting an Integer or a Float as start time, not a %s", rb_obj_classname(kwvalues[0]));
906
+
907
+ if (kwvalues[1] == Qundef || NIL_P(kwvalues[1]))
908
+ end_time = fstReaderGetEndTime(ctx) + 1;
909
+ else if (rb_obj_is_kind_of(kwvalues[1], rb_cInteger))
910
+ end_time = NUM2ULL(kwvalues[1]);
911
+ else if (rb_obj_is_kind_of(kwvalues[1], rb_cFloat))
912
+ end_time = (uint64_t)floor(NUM2DBL(kwvalues[1]) / NUM2DBL(libfst_reader_time_scale(self)));
913
+ else
914
+ rb_raise(rb_eTypeError, "expecting an Integer or a Float as end time, not a %s", rb_obj_classname(kwvalues[1]));
915
+
916
+ if (end_time < start_time)
917
+ rb_raise(rb_eRuntimeError, "start_time must be less than end_time (%lu, %lu)", start_time, end_time);
918
+
919
+ fstReaderSetLimitTimeRange(ctx, start_time, end_time);
920
+ cbarg.limit_time = 1;
921
+ cbarg.start_time = start_time;
922
+ cbarg.end_time = end_time;
923
+ } else {
924
+ fstReaderSetUnlimitedTimeRange(ctx);
925
+ cbarg.limit_time = 0;
926
+ }
927
+
928
+ long splatlen = rb_array_len(splat);
929
+ if (splatlen < 1) {
930
+ fstReaderSetFacProcessMaskAll(ctx);
931
+ } else {
932
+ fstReaderClrFacProcessMaskAll(ctx);
933
+ long i;
934
+ fstHandle mh = fstReaderGetMaxHandle(ctx);
935
+ for (i = 0; i < splatlen; i++) {
936
+ VALUE t = rb_ary_entry(splat, i);
937
+ fstHandle facidx;
938
+ if (rb_obj_is_kind_of(t, rb_cInteger)) {
939
+ facidx = NUM2ULONG(t);
940
+ if (facidx < 1 || facidx > mh) rb_raise(rb_eRuntimeError, "bad signal handle");
941
+ fstReaderSetFacProcessMask(ctx, facidx);
942
+ } else if (rb_obj_is_kind_of(t, c_RTrace)) {
943
+ facidx = NUM2ULONG(rb_ivar_get(t, id_at_handle));
944
+ if (facidx < 1 || facidx > mh) rb_raise(rb_eRuntimeError, "bad signal handle");
945
+ fstReaderSetFacProcessMask(ctx, facidx);
946
+ } else if (rb_obj_is_kind_of(t, c_RVariable)) {
947
+ facidx = NUM2ULONG(rb_ivar_get(rb_ivar_get(t, id_at_trace), id_at_handle));
948
+ if (facidx < 1 || facidx > mh) rb_raise(rb_eRuntimeError, "bad signal handle");
949
+ fstReaderSetFacProcessMask(ctx, facidx);
950
+ } else if (rb_obj_is_kind_of(t, c_RScope)) {
951
+ VALUE variables = rb_ivar_get(t, id_at_variables);
952
+ long varlen = rb_array_len(variables);
953
+ long j;
954
+ for (j = 0; j < varlen; j++) {
955
+ facidx = NUM2ULONG(rb_ivar_get(rb_ivar_get(rb_ary_entry(variables, j), id_at_trace), id_at_handle));
956
+ if (facidx < 1 || facidx > mh) rb_raise(rb_eRuntimeError, "bad signal handle");
957
+ fstReaderSetFacProcessMask(ctx, facidx);
958
+ }
959
+ } else {
960
+ rb_raise(rb_eTypeError, "signals can be specified either by a handle (Integer), a %"PRIsVALUE", a %"PRIsVALUE" or a %"PRIsVALUE", not a %s",
961
+ c_RTrace, c_RVariable, c_RScope, rb_obj_classname(t));
962
+ }
963
+ }
964
+ }
965
+
966
+ cbarg.reader = self;
967
+ cbarg.proc = blk;
968
+ int r = fstReaderIterBlocks2(ctx, libfst_reader_value_change_callback, libfst_reader_value_change_callback_varlen, &cbarg, NULL);
969
+ RB_GC_GUARD(cbarg.reader);
970
+ RB_GC_GUARD(cbarg.proc);
971
+ return INT2NUM(r);
972
+ }
973
+
974
+
975
+ /******************************************************************************/
976
+
977
+
978
+ typedef struct {
979
+ void *ctx;
980
+ } fstwriterctx_t;
981
+
982
+
983
+ static void libfst_writer_free(void *p)
984
+ {
985
+ fstwriterctx_t *wctx = p;
986
+
987
+ if (wctx) {
988
+ if (wctx->ctx)
989
+ fstWriterClose(wctx->ctx);
990
+ free(wctx);
991
+ }
992
+ }
993
+
994
+
995
+ static size_t libfst_writer_size(const void *p)
996
+ {
997
+ (void)p;
998
+ return sizeof(fstwriterctx_t);
999
+ }
1000
+
1001
+
1002
+ const rb_data_type_t libfst_writer_type = {
1003
+ .wrap_struct_name = "LibFST::Writer",
1004
+ .function = {
1005
+ .dmark = NULL,
1006
+ .dfree = libfst_writer_free,
1007
+ .dsize = libfst_writer_size,
1008
+ },
1009
+ .parent = NULL,
1010
+ .data = NULL,
1011
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY
1012
+ };
1013
+
1014
+
1015
+ inline void* libfst_writer_from_rbobj(VALUE obj) {
1016
+ fstwriterctx_t *wctx;
1017
+ TypedData_Get_Struct(obj, fstwriterctx_t, &libfst_writer_type, wctx);
1018
+ if (!wctx->ctx)
1019
+ rb_raise(rb_eRuntimeError, "%s object is not valid", rb_obj_classname(obj));
1020
+ return wctx->ctx;
1021
+ }
1022
+
1023
+
1024
+ static VALUE libfst_writer_alloc(VALUE klass)
1025
+ {
1026
+ fstwriterctx_t *wctx = malloc(sizeof(fstwriterctx_t));
1027
+ wctx->ctx = NULL;
1028
+ return TypedData_Wrap_Struct(klass, &libfst_writer_type, wctx);
1029
+ }
1030
+
1031
+
1032
+ /* @overload initialize(out_file_name, compress_hier: true)
1033
+ * @param out_file_name [String] path of the file to create
1034
+ * @param compress_hier [Boolean]
1035
+ */
1036
+ static VALUE libfst_writer_initialize(int argc, VALUE *argv, VALUE self)
1037
+ {
1038
+ VALUE fname;
1039
+ VALUE kw;
1040
+ const ID kwkeys[1] = {id_compress_hier};
1041
+ VALUE kwvalues[1] = {Qundef};
1042
+ rb_scan_args(argc, argv, "1:", &fname, &kw);
1043
+ fname = rb_funcallv(rb_cFile, id_expand_path, 1, &fname);
1044
+ const char *cfname = rb_string_value_cstr(&fname);
1045
+ rb_ivar_set(self, id_at_filename, fname);
1046
+ int ccomphier = 1;
1047
+ if (!NIL_P(kw)) {
1048
+ rb_get_kwargs(kw, kwkeys, 0, 1, kwvalues);
1049
+ if (kwvalues[0] != Qundef) {
1050
+ if (kwvalues[0] == Qnil || kwvalues[0] == Qfalse)
1051
+ ccomphier = 0;
1052
+ else
1053
+ ccomphier = 1;
1054
+ }
1055
+ }
1056
+
1057
+ fstwriterctx_t *wctx;
1058
+ TypedData_Get_Struct(self, fstwriterctx_t, &libfst_writer_type, wctx);
1059
+ wctx->ctx = fstWriterCreate(cfname, ccomphier);
1060
+ if (!wctx->ctx)
1061
+ rb_raise(rb_eRuntimeError, "cannot create FST file \"%"PRIsVALUE"\"", fname);
1062
+
1063
+ rb_ivar_set(self, id_at_variables, rb_ary_new());
1064
+
1065
+ return self;
1066
+ }
1067
+
1068
+
1069
+ static VALUE delete_temp_hier_file(VALUE writer)
1070
+ {
1071
+ VALUE base = rb_ivar_get(writer, id_at_filename);
1072
+ VALUE sufix = rb_sprintf(".hier");
1073
+ VALUE hierfname = rb_funcallv(base, id_symbol_plus, 1, &sufix);
1074
+ rb_funcallv(rb_cFile, id_delete, 1, &hierfname);
1075
+ return writer;
1076
+ }
1077
+
1078
+
1079
+ /* Finalize the output file then close it.
1080
+ * After this method has been called, the object is not valid anymore.
1081
+ */
1082
+ static VALUE libfst_writer_close(VALUE self)
1083
+ {
1084
+ fstwriterctx_t *wctx;
1085
+ TypedData_Get_Struct(self, fstwriterctx_t, &libfst_writer_type, wctx);
1086
+ if (!wctx->ctx)
1087
+ rb_raise(rb_eRuntimeError, "%s object is not valid", rb_obj_classname(self));
1088
+ fstWriterClose(wctx->ctx);
1089
+ wctx->ctx = NULL;
1090
+
1091
+ int state = 0;
1092
+ rb_protect(delete_temp_hier_file, self, &state);
1093
+ if (state)
1094
+ rb_set_errinfo(Qnil);
1095
+
1096
+ return self;
1097
+ }
1098
+
1099
+
1100
+ /* Set the date string to be written in the output file
1101
+ * @param date [String]
1102
+ * @return [self]
1103
+ */
1104
+ static VALUE libfst_writer_set_date_string(VALUE self, VALUE date)
1105
+ {
1106
+ void *ctx = libfst_writer_from_rbobj(self);
1107
+ const char *str = rb_string_value_cstr(&date);
1108
+ fstWriterSetDate(ctx, str);
1109
+ return self;
1110
+ }
1111
+
1112
+
1113
+ /* Set the version string to be written to the output file.
1114
+ * @param version [String]
1115
+ * @return [self]
1116
+ */
1117
+ static VALUE libfst_writer_set_version_string(VALUE self, VALUE version)
1118
+ {
1119
+ void *ctx = libfst_writer_from_rbobj(self);
1120
+ const char *str = rb_string_value_cstr(&version);
1121
+ fstWriterSetVersion(ctx, str);
1122
+ return self;
1123
+ }
1124
+
1125
+
1126
+ /* @return [Boolean]
1127
+ */
1128
+ static VALUE libfst_writer_fseek_failed(VALUE self)
1129
+ {
1130
+ void *ctx = libfst_writer_from_rbobj(self);
1131
+ return (fstWriterGetFseekFailed(ctx) ? Qtrue : Qfalse);
1132
+ }
1133
+
1134
+
1135
+ /* @return [Boolean]
1136
+ */
1137
+ static VALUE libfst_writer_dump_size_limit_reached(VALUE self)
1138
+ {
1139
+ void *ctx = libfst_writer_from_rbobj(self);
1140
+ return (fstWriterGetDumpSizeLimitReached(ctx) ? Qtrue : Qfalse);
1141
+ }
1142
+
1143
+
1144
+ /* @param numbytes [Integer]
1145
+ * @return [self]
1146
+ */
1147
+ static VALUE libfst_writer_set_dump_size_limit(VALUE self, VALUE numbytes)
1148
+ {
1149
+ void *ctx = libfst_writer_from_rbobj(self);
1150
+ uint64_t limit = rb_to_uint64t(numbytes);
1151
+ fstWriterSetDumpSizeLimit(ctx, limit);
1152
+ return self;
1153
+ }
1154
+
1155
+
1156
+ /* @return [self]
1157
+ */
1158
+ static VALUE libfst_writer_flush_context(VALUE self)
1159
+ {
1160
+ void *ctx = libfst_writer_from_rbobj(self);
1161
+ fstWriterFlushContext(ctx);
1162
+ return self;
1163
+ }
1164
+
1165
+
1166
+ /* Set time zero.
1167
+ * @param time [Integer]
1168
+ * @return [self]
1169
+ */
1170
+ static VALUE libfst_writer_set_time_zero(VALUE self, VALUE time)
1171
+ {
1172
+ void *ctx = libfst_writer_from_rbobj(self);
1173
+ fstWriterSetTimezero(ctx, NUM2LL(time));
1174
+ return self;
1175
+ }
1176
+
1177
+
1178
+ /* Set the comment to be written to the output file.
1179
+ * @param comment [String]
1180
+ * @return [self]
1181
+ */
1182
+ static VALUE libfst_writer_set_comment(VALUE self, VALUE comment)
1183
+ {
1184
+ void *ctx = libfst_writer_from_rbobj(self);
1185
+ const char *str = rb_string_value_cstr(&comment);
1186
+ fstWriterSetComment(ctx, str);
1187
+ return self;
1188
+ }
1189
+
1190
+
1191
+ /* Set whether to use parallel write mode or not (multithreaded)
1192
+ * @param enable [Boolean]
1193
+ * @return [self]
1194
+ */
1195
+ static VALUE libfst_writer_set_use_parallel_mode(VALUE self, VALUE enable)
1196
+ {
1197
+ void *ctx = libfst_writer_from_rbobj(self);
1198
+ int en = rb_to_boolean(enable);
1199
+ fstWriterSetParallelMode(ctx, en);
1200
+ return self;
1201
+ }
1202
+
1203
+
1204
+ /* @param enable [Boolean]
1205
+ * @return [self]
1206
+ */
1207
+ static VALUE libfst_writer_set_repack_on_close(VALUE self, VALUE enable)
1208
+ {
1209
+ void *ctx = libfst_writer_from_rbobj(self);
1210
+ int en = rb_to_boolean(enable);
1211
+ fstWriterSetRepackOnClose(ctx, en);
1212
+ return self;
1213
+ }
1214
+
1215
+
1216
+ static enum fstFileType symbol_to_fstFileType(VALUE sym)
1217
+ {
1218
+ ID id = rb_sym2id(sym);
1219
+ enum fstFileType t;
1220
+ if (id == id_verilog)
1221
+ t = FST_FT_VERILOG;
1222
+ else if (id == id_vhdl)
1223
+ t = FST_FT_VHDL;
1224
+ else if (id == id_verilog_or_vhdl)
1225
+ t = FST_FT_VERILOG_VHDL;
1226
+ else
1227
+ rb_raise(rb_eTypeError, "invalid file type (%"PRIsVALUE"), valid values are :verilog, :vhdl or verilog_or_vhdl", sym);
1228
+
1229
+ return t;
1230
+ }
1231
+
1232
+
1233
+ /* Indicate the file type.
1234
+ * @param type [Symbol] either `:verilog`, `:vhdl` or `:verilog_or_vhdl`
1235
+ * @return [self]
1236
+ */
1237
+ static VALUE libfst_writer_set_file_type(VALUE self, VALUE type)
1238
+ {
1239
+ void *ctx = libfst_writer_from_rbobj(self);
1240
+ fstWriterSetFileType(ctx, symbol_to_fstFileType(type));
1241
+ return self;
1242
+ }
1243
+
1244
+
1245
+ static enum fstWriterPackType symbol_to_fstWriterPackType(VALUE sym)
1246
+ {
1247
+ ID id = rb_sym2id(sym);
1248
+ enum fstWriterPackType pt;
1249
+ if (id == id_zlib)
1250
+ pt = FST_WR_PT_ZLIB;
1251
+ else if (id == id_fastlz)
1252
+ pt = FST_WR_PT_FASTLZ;
1253
+ else if (id == id_lz4)
1254
+ pt = FST_WR_PT_LZ4;
1255
+ else
1256
+ rb_raise(rb_eTypeError, "invalid pack type (%"PRIsVALUE"), valid values are :zlib, :fastlz or :lz4", sym);
1257
+ return pt;
1258
+ }
1259
+
1260
+
1261
+ /* Set the packing type.
1262
+ * @param type [Symbol] Either `:zlib`, `:fastlz` or `:lz4`
1263
+ * @return [self]
1264
+ */
1265
+ static VALUE libfst_writer_set_pack_type(VALUE self, VALUE type)
1266
+ {
1267
+ void *ctx = libfst_writer_from_rbobj(self);
1268
+ fstWriterSetPackType(ctx, symbol_to_fstWriterPackType(type));
1269
+ return self;
1270
+ }
1271
+
1272
+
1273
+ /* @param envvar [String]
1274
+ * @return [self]
1275
+ */
1276
+ static VALUE libfst_writer_set_envvar(VALUE self, VALUE envvar)
1277
+ {
1278
+ void *ctx = libfst_writer_from_rbobj(self);
1279
+ const char *str = rb_string_value_cstr(&envvar);
1280
+ fstWriterSetEnvVar(ctx, str);
1281
+ return self;
1282
+ }
1283
+
1284
+
1285
+ /* @param valuelist [String]
1286
+ * @return [self]
1287
+ */
1288
+ static VALUE libfst_writer_set_value_list(VALUE self, VALUE valuelist)
1289
+ {
1290
+ void *ctx = libfst_writer_from_rbobj(self);
1291
+ const char *str = rb_string_value_cstr(&valuelist);
1292
+ fstWriterSetValueList(ctx, str);
1293
+ return self;
1294
+ }
1295
+
1296
+
1297
+ /* @return [self]
1298
+ */
1299
+ static VALUE libfst_writer_set_upscope(VALUE self)
1300
+ {
1301
+ void *ctx = libfst_writer_from_rbobj(self);
1302
+ fstWriterSetUpscope(ctx);
1303
+ return self;
1304
+ }
1305
+
1306
+
1307
+ /* Set time scale, as a power of 10.
1308
+ * @param timescale [Integer,Symbol,Float] Either 0 for `:s`, -3 for `:ms`, -6 fo `:us`, -9 for `:ns`, -12 for `:ps` or -15 for `:fs`. If a Float is given, it must be a power of 10, such as 10e-9
1309
+ * @return [Integer]
1310
+ */
1311
+ static VALUE libfst_writer_set_time_scale(VALUE self, VALUE timescale)
1312
+ {
1313
+ int ts = 0;
1314
+ if (rb_obj_is_kind_of(timescale, rb_cInteger)) {
1315
+ ts = NUM2INT(timescale);
1316
+ if (ts > 0 || ts < -15)
1317
+ rb_raise(rb_eRangeError, "valid integer timescale values are between 0 and -15");
1318
+ } else if (rb_obj_is_kind_of(timescale, rb_cSymbol)) {
1319
+ ID id = rb_sym2id(timescale);
1320
+ if (id == id_s)
1321
+ ts = 0;
1322
+ else if (id == id_ms)
1323
+ ts = -3;
1324
+ else if (id == id_us)
1325
+ ts = -6;
1326
+ else if (id == id_ns)
1327
+ ts = -9;
1328
+ else if (id == id_ps)
1329
+ ts = -12;
1330
+ else if (id == id_fs)
1331
+ ts = -15;
1332
+ else
1333
+ rb_raise(rb_eRuntimeError, "valid timescale symbols are :s, :ms, :us, :ns, :ps and :fs");
1334
+ } else if (rb_obj_is_kind_of(timescale, rb_cFloat)) {
1335
+ double d = NUM2DBL(timescale);
1336
+ if (d <= 1e-21 || d > 1.0)
1337
+ rb_raise(rb_eRangeError, "valid float timescale values are between 1e-21 and 1.0");
1338
+ double l = log10(d);
1339
+ ts = (int)l;
1340
+ if (l != (double)ts)
1341
+ rb_raise(rb_eRangeError, "valid float timescale values must be powers of 10, such as 10e-3");
1342
+ }
1343
+ void *ctx = libfst_writer_from_rbobj(self);
1344
+ fstWriterSetTimescale(ctx, ts);
1345
+ return INT2NUM(ts);
1346
+ }
1347
+
1348
+
1349
+ /* @return [self]
1350
+ */
1351
+ static VALUE libfst_writer_set_attribute_end(VALUE self)
1352
+ {
1353
+ void *ctx = libfst_writer_from_rbobj(self);
1354
+ fstWriterSetAttrEnd(ctx);
1355
+ return self;
1356
+ }
1357
+
1358
+
1359
+ static enum fstAttrType symbol_to_fstAttrType(VALUE sym)
1360
+ {
1361
+ ID id = rb_sym2id(sym);
1362
+ enum fstAttrType t;
1363
+ if (id == id_misc)
1364
+ t = FST_AT_MISC;
1365
+ else if (id == id_array)
1366
+ t = FST_AT_ARRAY;
1367
+ else if (id == id_enum)
1368
+ t = FST_AT_ENUM;
1369
+ else if (id == id_pack)
1370
+ t = FST_AT_PACK;
1371
+ else
1372
+ rb_raise(rb_eTypeError, "invalid attribute type (%"PRIsVALUE"), valid values are :misc, :array, :enum or :pack", sym);
1373
+ return t;
1374
+ }
1375
+
1376
+
1377
+ static int symbol_to_subtype(VALUE sym, enum fstAttrType type)
1378
+ {
1379
+ int subtype = 0;
1380
+ ID id;
1381
+
1382
+ switch (type) {
1383
+ case FST_AT_MISC:
1384
+ if (NIL_P(sym)) {
1385
+ subtype = FST_MT_UNKNOWN;
1386
+ break;
1387
+ }
1388
+ id = rb_sym2id(sym);
1389
+ if (id == id_comment)
1390
+ subtype = FST_MT_COMMENT;
1391
+ else if (id == id_envvar)
1392
+ subtype = FST_MT_ENVVAR;
1393
+ else if (id == id_supvar)
1394
+ subtype = FST_MT_SUPVAR;
1395
+ else if (id == id_pathname)
1396
+ subtype = FST_MT_PATHNAME;
1397
+ else if (id == id_sourcestem)
1398
+ subtype = FST_MT_SOURCESTEM;
1399
+ else if (id == id_sourceistem)
1400
+ subtype = FST_MT_SOURCEISTEM;
1401
+ else if (id == id_valuelist)
1402
+ subtype = FST_MT_VALUELIST;
1403
+ else if (id == id_enumtable)
1404
+ subtype = FST_MT_ENUMTABLE;
1405
+ else if (id == id_unknown)
1406
+ subtype = FST_MT_UNKNOWN;
1407
+ else
1408
+ rb_raise(rb_eArgError, "invalid subtype (%"PRIsVALUE"), with type :misc, valid subtypes are :comment, :envvar, :supvar, :pathname, :sourcestem, :sourceistem, :valuelist, :enumtable and :unknown", sym);
1409
+ break;
1410
+
1411
+ case FST_AT_ARRAY:
1412
+ if (NIL_P(sym)) {
1413
+ subtype = FST_AR_NONE;
1414
+ break;
1415
+ }
1416
+ id = rb_sym2id(sym);
1417
+ if (id == id_none)
1418
+ subtype = FST_AR_NONE;
1419
+ else if (id == id_unpacked)
1420
+ subtype = FST_AR_UNPACKED;
1421
+ else if (id == id_packed)
1422
+ subtype = FST_AR_PACKED;
1423
+ else if (id == id_sparse)
1424
+ subtype = FST_AR_SPARSE;
1425
+ else
1426
+ rb_raise(rb_eArgError, "invalid subtype (%"PRIsVALUE"), with type :array, valid subtypes are :none, :unpacked, :packed and :sparse", sym);
1427
+ break;
1428
+
1429
+ case FST_AT_ENUM:
1430
+ if (NIL_P(sym)) {
1431
+ subtype = FST_EV_SV_INTEGER;
1432
+ break;
1433
+ }
1434
+ id = rb_sym2id(sym);
1435
+ if (id == id_integer)
1436
+ subtype = FST_EV_SV_INTEGER;
1437
+ else if (id == id_bit)
1438
+ subtype = FST_EV_SV_BIT;
1439
+ else if (id == id_logic)
1440
+ subtype = FST_EV_SV_LOGIC;
1441
+ else if (id == id_int)
1442
+ subtype = FST_EV_SV_INT;
1443
+ else if (id == id_shortint)
1444
+ subtype = FST_EV_SV_SHORTINT;
1445
+ else if (id == id_longint)
1446
+ subtype = FST_EV_SV_LONGINT;
1447
+ else if (id == id_byte)
1448
+ subtype = FST_EV_SV_BYTE;
1449
+ else if (id == id_unsigned_integer)
1450
+ subtype = FST_EV_SV_UNSIGNED_INTEGER;
1451
+ else if (id == id_unsigned_bit)
1452
+ subtype = FST_EV_SV_UNSIGNED_BIT;
1453
+ else if (id == id_unsigned_logic)
1454
+ subtype = FST_EV_SV_UNSIGNED_LOGIC;
1455
+ else if (id == id_unsigned_int)
1456
+ subtype = FST_EV_SV_UNSIGNED_INT;
1457
+ else if (id == id_unsigned_shortint)
1458
+ subtype = FST_EV_SV_UNSIGNED_SHORTINT;
1459
+ else if (id == id_unsigned_longint)
1460
+ subtype = FST_EV_SV_UNSIGNED_LONGINT;
1461
+ else if (id == id_unsigned_byte)
1462
+ subtype = FST_EV_SV_UNSIGNED_BYTE;
1463
+ else if (id == id_reg)
1464
+ subtype = FST_EV_REG;
1465
+ else if (id == id_time)
1466
+ subtype = FST_EV_TIME;
1467
+ else
1468
+ rb_raise(rb_eArgError, "invalid subtype (%"PRIsVALUE"), with type :enum, valid subtypes are :integer, :bit, :logic, :int, :shortint, :longint, :byte, :unsigned_integer, :unsigned_bit, :unsigned_logic, :unsigned_int, :unsigned_shortint, :unsigned_longint, :unsigned_byte, :reg and :time", sym);
1469
+ break;
1470
+
1471
+ case FST_AT_PACK:
1472
+ if (NIL_P(sym)) {
1473
+ subtype = FST_PT_NONE;
1474
+ break;
1475
+ }
1476
+ id = rb_sym2id(sym);
1477
+ if (id == id_none)
1478
+ subtype = FST_PT_NONE;
1479
+ else if (id == id_unpacked)
1480
+ subtype = FST_PT_UNPACKED;
1481
+ else if (id == id_packed)
1482
+ subtype = FST_PT_PACKED;
1483
+ else if (id == id_tagged_packed)
1484
+ subtype = FST_PT_TAGGED_PACKED;
1485
+ else
1486
+ rb_raise(rb_eArgError, "invalid subtype (%"PRIsVALUE"), with type :pack, valid subtypes are :none, :unpacked, :packed or :tagged_packed", sym);
1487
+ break;
1488
+
1489
+ default:
1490
+ rb_raise(rb_eRuntimeError, "bad type");
1491
+ }
1492
+
1493
+ return subtype;
1494
+ }
1495
+
1496
+
1497
+ /* Attributes of type `:misc` do not need a closing {Writer#set_attribute_end}, others do.
1498
+ * @return [self]
1499
+ * @overload set_attribute_begin(name, type:, subtype: nil, arg: 0)
1500
+ * @param name [String]
1501
+ * @param type [Symbol] either `:misc`, `:array`, `:enum` or `:pack`
1502
+ * @param subtype [Symbol,nil]
1503
+ * When `type` is
1504
+ * - __:misc__: `:comment`, `:envvar`, `:supvar`, `:pathname`, `:sourcestem`, `:sourceistem`, `:valuelist`, `:enumtable`, `:unknown`
1505
+ * - __:array__: `:none`, `:unpacked`, `:packed` or `:sparse`
1506
+ * - __:enum__: `:integer`, `:bit`, `:logic`, `:int`, `:shortint`, `:longint`, `:byte`, `:unsigned_integer`, `:unsigned_bit`, `:unsigned_logic`, `:unsigned_int`, `:unsigned_shortint`, `:unsigned_longint`, `:unsigned_byte`, `:reg` or `:time`
1507
+ * - __:pack__: `:none`, `:unpacked`, `:packed` or `:tagged_packed`
1508
+ * @param arg [Integer]
1509
+ */
1510
+ static VALUE libfst_writer_set_attribute_begin(int argc, VALUE *argv, VALUE self)
1511
+ {
1512
+ VALUE rbname;
1513
+ VALUE kw;
1514
+ const ID kwkeys[3] = {id_type, id_subtype, id_arg};
1515
+ VALUE kwvalues[3] = {Qundef, Qundef, Qundef};
1516
+
1517
+ rb_scan_args(argc, argv, "1:", &rbname, &kw);
1518
+ const char *attrname = rb_string_value_cstr(&rbname);
1519
+ rb_get_kwargs(kw, kwkeys, 1, 2, kwvalues);
1520
+ enum fstAttrType type = symbol_to_fstAttrType(kwvalues[0]);
1521
+ uint64_t arg = 0;
1522
+ if (kwvalues[2] != Qundef && kwvalues[2] != Qnil)
1523
+ arg = rb_to_uint64t(kwvalues[2]);
1524
+ if (kwvalues[1] == Qundef)
1525
+ kwvalues[1] = Qnil;
1526
+ int subtype = symbol_to_subtype(kwvalues[1], type);
1527
+
1528
+ void *ctx = libfst_writer_from_rbobj(self);
1529
+ fstWriterSetAttrBegin(ctx, type, subtype, attrname, arg);
1530
+ return self;
1531
+ }
1532
+
1533
+
1534
+ /* @return [self]
1535
+ * @overload set_source_stem(path, line, use_realpath: false)
1536
+ * @param path [String]
1537
+ * @param line [Integer]
1538
+ * @param use_realpath [Boolean]
1539
+ */
1540
+ static VALUE libfst_writer_set_source_stem(int argc, VALUE *argv, VALUE self)
1541
+ {
1542
+ VALUE rbpath, rbline, kw;
1543
+ const ID kwkeys[1] = {id_use_realpath};
1544
+ VALUE kwvalues[1] = {Qundef};
1545
+
1546
+ rb_scan_args(argc, argv, "2:", &rbpath, &rbline, &kw);
1547
+ rb_get_kwargs(kw, kwkeys, 0, 1, kwvalues);
1548
+
1549
+ const char *path = rb_string_value_cstr(&rbpath);
1550
+ unsigned int line = rb_to_unsigned_int(rbline);
1551
+ int use_realpath = 0;
1552
+ if (kwvalues[0] != Qundef)
1553
+ use_realpath = rb_to_boolean(kwvalues[0]);
1554
+
1555
+ void *ctx = libfst_writer_from_rbobj(self);
1556
+ fstWriterSetSourceStem(ctx, path, line, use_realpath);
1557
+
1558
+ return self;
1559
+ }
1560
+
1561
+
1562
+ /* @return [self]
1563
+ * @overload set_source_instantiation_stem(path, line, use_realpath: false)
1564
+ * @param path [String]
1565
+ * @param line [Integer]
1566
+ * @param use_realpath [Boolean]
1567
+ */
1568
+ static VALUE libfst_writer_set_source_instantiation_stem(int argc, VALUE *argv, VALUE self)
1569
+ {
1570
+ VALUE rbpath, rbline, kw;
1571
+ const ID kwkeys[1] = {id_use_realpath};
1572
+ VALUE kwvalues[1] = {Qundef};
1573
+
1574
+ rb_scan_args(argc, argv, "2:", &rbpath, &rbline, &kw);
1575
+ rb_get_kwargs(kw, kwkeys, 0, 1, kwvalues);
1576
+
1577
+ const char *path = rb_string_value_cstr(&rbpath);
1578
+ unsigned int line = rb_to_unsigned_int(rbline);
1579
+ int use_realpath = 0;
1580
+ if (kwvalues[0] != Qundef)
1581
+ use_realpath = rb_to_boolean(kwvalues[0]);
1582
+
1583
+ void *ctx = libfst_writer_from_rbobj(self);
1584
+ fstWriterSetSourceInstantiationStem(ctx, path, line, use_realpath);
1585
+
1586
+ return self;
1587
+ }
1588
+
1589
+
1590
+ static enum fstScopeType symbol_to_fstScopeType(VALUE sym)
1591
+ {
1592
+ ID id = rb_sym2id(sym);
1593
+ enum fstScopeType t;
1594
+ if (id == id_vcd_module)
1595
+ t = FST_ST_VCD_MODULE;
1596
+ else if (id == id_vcd_task)
1597
+ t = FST_ST_VCD_TASK;
1598
+ else if (id == id_vcd_function)
1599
+ t = FST_ST_VCD_FUNCTION;
1600
+ else if (id == id_vcd_begin)
1601
+ t = FST_ST_VCD_BEGIN;
1602
+ else if (id == id_vcd_fork)
1603
+ t = FST_ST_VCD_FORK;
1604
+ else if (id == id_vcd_generate)
1605
+ t = FST_ST_VCD_GENERATE;
1606
+ else if (id == id_vcd_struct)
1607
+ t = FST_ST_VCD_STRUCT;
1608
+ else if (id == id_vcd_union)
1609
+ t = FST_ST_VCD_UNION;
1610
+ else if (id == id_vcd_class)
1611
+ t = FST_ST_VCD_CLASS;
1612
+ else if (id == id_vcd_interface)
1613
+ t = FST_ST_VCD_INTERFACE;
1614
+ else if (id == id_vcd_package)
1615
+ t = FST_ST_VCD_PACKAGE;
1616
+ else if (id == id_vcd_program)
1617
+ t = FST_ST_VCD_PROGRAM;
1618
+ else if (id == id_vhdl_architecture)
1619
+ t = FST_ST_VHDL_ARCHITECTURE;
1620
+ else if (id == id_vhdl_procedure)
1621
+ t = FST_ST_VHDL_PROCEDURE;
1622
+ else if (id == id_vhdl_function)
1623
+ t = FST_ST_VHDL_FUNCTION;
1624
+ else if (id == id_vhdl_record)
1625
+ t = FST_ST_VHDL_RECORD;
1626
+ else if (id == id_vhdl_process)
1627
+ t = FST_ST_VHDL_PROCESS;
1628
+ else if (id == id_vhdl_block)
1629
+ t = FST_ST_VHDL_BLOCK;
1630
+ else if (id == id_vhdl_for_generate)
1631
+ t = FST_ST_VHDL_FOR_GENERATE;
1632
+ else if (id == id_vhdl_if_generate)
1633
+ t = FST_ST_VHDL_IF_GENERATE;
1634
+ else if (id == id_vhdl_generate)
1635
+ t = FST_ST_VHDL_GENERATE;
1636
+ else if (id == id_vhdl_package)
1637
+ t = FST_ST_VHDL_PACKAGE;
1638
+ else
1639
+ rb_raise(rb_eTypeError, "invalid scope type (%"PRIsVALUE"), valid values are :vcd_module, :vcd_task, :vcd_function, :vcd_begin, :vcd_fork, :vcd_generate, :vcd_struct, :vcd_union, :vcd_class, :vcd_interface, :vcd_package, :vcd_program, :vhdl_architecture, :vhdl_procedure, :vhdl_function, :vhdl_record, :vhdl_process, :vhdl_block, :vhdl_for_generate, :vhdl_if_generate, :vhdl_generate and :vhdl_package", sym);
1640
+ return t;
1641
+ }
1642
+
1643
+
1644
+ /* @return [self]
1645
+ * @overload set_scope(type, name: nil, component: nil)
1646
+ * @param type [Symbol] either `:vcd_module`, `:vcd_task`, `:vcd_function`, `:vcd_begin`, `:vcd_fork`, `:vcd_generate`, `:vcd_struct`, `:vcd_union`, `:vcd_class`, `:vcd_interface`, `:vcd_package`, `:vcd_program`, `:vhdl_architecture`, `:vhdl_procedure`, `:vhdl_function`, `:vhdl_record`, `:vhdl_process`, `:vhdl_block`, `:vhdl_for_generate`, `:vhdl_if_generate`, `:vhdl_generate` or `:vhdl_package`
1647
+ * @param name [String,nil]
1648
+ * @param component [String,nil]
1649
+ */
1650
+ static VALUE libfst_writer_set_scope(int argc, VALUE *argv, VALUE self)
1651
+ {
1652
+ VALUE rbtype;
1653
+ VALUE kw;
1654
+ const ID kwkeys[2] = {id_name, id_component};
1655
+ VALUE kwvalues[2] = {Qundef, Qundef};
1656
+ rb_scan_args(argc, argv, "1:", &rbtype, &kw);
1657
+ enum fstScopeType scopetype = symbol_to_fstScopeType(rbtype);
1658
+ const char *scopename = NULL;
1659
+ const char *scopecomp = NULL;
1660
+ if (!NIL_P(kw)) {
1661
+ rb_get_kwargs(kw, kwkeys, 0, 2, kwvalues);
1662
+ if (kwvalues[0] != Qundef && !NIL_P(kwvalues[0]))
1663
+ scopename = rb_string_value_cstr(&kwvalues[0]);
1664
+ if (kwvalues[1] != Qundef && !NIL_P(kwvalues[1]))
1665
+ scopecomp = rb_string_value_cstr(&kwvalues[1]);
1666
+ }
1667
+
1668
+ void *ctx = libfst_writer_from_rbobj(self);
1669
+ fstWriterSetScope(ctx, scopetype, scopename, scopecomp);
1670
+
1671
+ return self;
1672
+ }
1673
+
1674
+
1675
+ /* Advance the time cursor.
1676
+ * @param time [Integer]
1677
+ * @return [self]
1678
+ */
1679
+ static VALUE libfst_writer_emit_time_change(VALUE self, VALUE time)
1680
+ {
1681
+ uint64_t t = rb_to_uint64t(time);
1682
+ void *ctx = libfst_writer_from_rbobj(self);
1683
+ fstWriterEmitTimeChange(ctx, t);
1684
+ return self;
1685
+ }
1686
+
1687
+
1688
+ /* Create a new blackout chain block.
1689
+ * @param enable [Boolean]
1690
+ * @return [self]
1691
+ */
1692
+ static VALUE libfst_writer_emit_dump_active(VALUE self, VALUE enable)
1693
+ {
1694
+ int en = rb_to_boolean(enable);
1695
+ void *ctx = libfst_writer_from_rbobj(self);
1696
+ fstWriterEmitDumpActive(ctx, en);
1697
+ return self;
1698
+ }
1699
+
1700
+
1701
+ static enum fstVarType symbol_to_fstVarType(VALUE sym)
1702
+ {
1703
+ ID id = rb_sym2id(sym);
1704
+ enum fstVarType t;
1705
+ if (id == id_vcd_event)
1706
+ t = FST_VT_VCD_EVENT;
1707
+ else if (id == id_vcd_integer)
1708
+ t = FST_VT_VCD_INTEGER;
1709
+ else if (id == id_vcd_parameter)
1710
+ t = FST_VT_VCD_PARAMETER;
1711
+ else if (id == id_vcd_real)
1712
+ t = FST_VT_VCD_REAL;
1713
+ else if (id == id_vcd_real_parameter)
1714
+ t = FST_VT_VCD_REAL_PARAMETER;
1715
+ else if (id == id_vcd_reg)
1716
+ t = FST_VT_VCD_REG;
1717
+ else if (id == id_vcd_supply0)
1718
+ t = FST_VT_VCD_SUPPLY0;
1719
+ else if (id == id_vcd_supply1)
1720
+ t = FST_VT_VCD_SUPPLY1;
1721
+ else if (id == id_vcd_time)
1722
+ t = FST_VT_VCD_TIME;
1723
+ else if (id == id_vcd_tri)
1724
+ t = FST_VT_VCD_TRI;
1725
+ else if (id == id_vcd_triand)
1726
+ t = FST_VT_VCD_TRIAND;
1727
+ else if (id == id_vcd_trior)
1728
+ t = FST_VT_VCD_TRIOR;
1729
+ else if (id == id_vcd_trireg)
1730
+ t = FST_VT_VCD_TRIREG;
1731
+ else if (id == id_vcd_tri0)
1732
+ t = FST_VT_VCD_TRI0;
1733
+ else if (id == id_vcd_tri1)
1734
+ t = FST_VT_VCD_TRI1;
1735
+ else if (id == id_vcd_wand)
1736
+ t = FST_VT_VCD_WAND;
1737
+ else if (id == id_vcd_wire)
1738
+ t = FST_VT_VCD_WIRE;
1739
+ else if (id == id_vcd_wor)
1740
+ t = FST_VT_VCD_WOR;
1741
+ else if (id == id_vcd_port)
1742
+ t = FST_VT_VCD_PORT;
1743
+ else if (id == id_vcd_sparray)
1744
+ t = FST_VT_VCD_SPARRAY;
1745
+ else if (id == id_vcd_realtime)
1746
+ t = FST_VT_VCD_REALTIME;
1747
+ else if (id == id_gen_string)
1748
+ t = FST_VT_GEN_STRING;
1749
+ else if (id == id_sv_bit)
1750
+ t = FST_VT_SV_BIT;
1751
+ else if (id == id_sv_logic)
1752
+ t = FST_VT_SV_LOGIC;
1753
+ else if (id == id_sv_int)
1754
+ t = FST_VT_SV_INT;
1755
+ else if (id == id_sv_shortint)
1756
+ t = FST_VT_SV_SHORTINT;
1757
+ else if (id == id_sv_longint)
1758
+ t = FST_VT_SV_LONGINT;
1759
+ else if (id == id_sv_byte)
1760
+ t = FST_VT_SV_BYTE;
1761
+ else if (id == id_sv_enum)
1762
+ t = FST_VT_SV_ENUM;
1763
+ else if (id == id_sv_shortreal)
1764
+ t = FST_VT_SV_SHORTREAL;
1765
+ else
1766
+ rb_raise(rb_eArgError, "invalid variable type (%"PRIsVALUE"), valid variable types are :vcd_event, :vcd_integer, :vcd_parameter, :vcd_real, :vcd_real_parameter, :vcd_reg, :vcd_supply0, :vcd_supply1, :vcd_time, :vcd_tri, :vcd_triand, :vcd_trior, :vcd_trireg, :vcd_tri0, :vcd_tri1, :vcd_wand, :vcd_wire, :vcd_wor, :vcd_port, :vcd_sparray, :vcd_realtime, :gen_string, :sv_bit, :sv_logic, :sv_int, :sv_shortint, :sv_longint, :sv_byte, :sv_enum and :sv_shortreal", sym);
1767
+
1768
+ return t;
1769
+ }
1770
+
1771
+
1772
+ static enum fstVarDir symbol_to_fstVarDir(VALUE sym)
1773
+ {
1774
+ ID id = rb_sym2id(sym);
1775
+ enum fstVarDir d;
1776
+ if (id == id_implicit)
1777
+ d = FST_VD_IMPLICIT;
1778
+ else if (id == id_input)
1779
+ d = FST_VD_INPUT;
1780
+ else if (id == id_output)
1781
+ d = FST_VD_OUTPUT;
1782
+ else if (id == id_inout)
1783
+ d = FST_VD_INOUT;
1784
+ else if (id == id_buffer)
1785
+ d = FST_VD_BUFFER;
1786
+ else if (id == id_linkage)
1787
+ d = FST_VD_LINKAGE;
1788
+ else
1789
+ rb_raise(rb_eArgError, "invalid variable direction (%"PRIsVALUE"), valid values are :implicit, :input, :output, :inout, :buffer or :linkage", sym);
1790
+ return d;
1791
+ }
1792
+
1793
+
1794
+ static enum fstSupplementalVarType symbol_to_fstSupplementalVarType(VALUE sym)
1795
+ {
1796
+ ID id = rb_sym2id(sym);
1797
+ enum fstSupplementalVarType t;
1798
+ if (id == id_none)
1799
+ t = FST_SVT_NONE;
1800
+ else if (id == id_vhdl_signal)
1801
+ t = FST_SVT_VHDL_SIGNAL;
1802
+ else if (id == id_vhdl_variable)
1803
+ t = FST_SVT_VHDL_VARIABLE;
1804
+ else if (id == id_vhdl_constant)
1805
+ t = FST_SVT_VHDL_CONSTANT;
1806
+ else if (id == id_vhdl_file)
1807
+ t = FST_SVT_VHDL_FILE;
1808
+ else if (id == id_vhdl_memory)
1809
+ t = FST_SVT_VHDL_MEMORY;
1810
+ else
1811
+ rb_raise(rb_eTypeError, "invalid supplemental variable type (%"PRIsVALUE"), valid values are :none, :vhdl_signal, :vhdl_variable, :vhdl_constant, :vhdl_file, :vhdl_memory", sym);
1812
+
1813
+ return t;
1814
+ }
1815
+
1816
+
1817
+ static enum fstSupplementalDataType symbol_to_fstSupplementalDataType(VALUE sym)
1818
+ {
1819
+ ID id = rb_sym2id(sym);
1820
+ enum fstSupplementalDataType t;
1821
+ if (id == id_none)
1822
+ t = FST_SDT_NONE;
1823
+ else if (id == id_vhdl_boolean)
1824
+ t = FST_SDT_VHDL_BOOLEAN;
1825
+ else if (id == id_vhdl_bit)
1826
+ t = FST_SDT_VHDL_BIT;
1827
+ else if (id == id_vhdl_bit_vector)
1828
+ t = FST_SDT_VHDL_BIT_VECTOR;
1829
+ else if (id == id_vhdl_std_ulogic)
1830
+ t = FST_SDT_VHDL_STD_ULOGIC;
1831
+ else if (id == id_vhdl_std_ulogic_vector)
1832
+ t = FST_SDT_VHDL_STD_ULOGIC_VECTOR;
1833
+ else if (id == id_vhdl_std_logic)
1834
+ t = FST_SDT_VHDL_STD_LOGIC;
1835
+ else if (id == id_vhdl_std_logic_vector)
1836
+ t = FST_SDT_VHDL_STD_LOGIC_VECTOR;
1837
+ else if (id == id_vhdl_unsigned)
1838
+ t = FST_SDT_VHDL_UNSIGNED;
1839
+ else if (id == id_vhdl_signed)
1840
+ t = FST_SDT_VHDL_SIGNED;
1841
+ else if (id == id_vhdl_integer)
1842
+ t = FST_SDT_VHDL_INTEGER;
1843
+ else if (id == id_vhdl_real)
1844
+ t = FST_SDT_VHDL_REAL;
1845
+ else if (id == id_vhdl_natural)
1846
+ t = FST_SDT_VHDL_NATURAL;
1847
+ else if (id == id_vhdl_positive)
1848
+ t = FST_SDT_VHDL_POSITIVE;
1849
+ else if (id == id_vhdl_time)
1850
+ t = FST_SDT_VHDL_TIME;
1851
+ else if (id == id_vhdl_character)
1852
+ t = FST_SDT_VHDL_CHARACTER;
1853
+ else if (id == id_vhdl_string)
1854
+ t = FST_SDT_VHDL_STRING;
1855
+ else
1856
+ rb_raise(rb_eTypeError, "invalid supplemental data type (%"PRIsVALUE"), valid values are :none, :vhdl_boolean, :vhdl_bit, :vhdl_bit_vector, :vhdl_std_ulogic, :vhdl_std_ulogic_vector, :vhdl_std_logic, :vhdl_std_logic_vector, :vhdl_unsigned, :vhdl_signed, :vhdl_integer, :vhdl_real, :vhdl_natural, :vhdl_positive, :vhdl_time, :vhdl_character or :vhdl_string", sym);
1857
+ return t;
1858
+ }
1859
+
1860
+
1861
+ /* @return [Variable]
1862
+ * @overload create_variable(name, type:, direction: :implicit, length: 0, alias_of: nil, sup_type_str: nil, sup_var_type: nil, sup_data_type: nil)
1863
+ * @param name [String]
1864
+ * @param type [Symbol] either `:vcd_event`, `:vcd_integer`, `:vcd_parameter`, `:vcd_real`, `:vcd_real_parameter`, `:vcd_reg`, `:vcd_supply0`, `:vcd_supply1`, `:vcd_time`, `:vcd_tri`, `:vcd_triand`, `:vcd_trior`, `:vcd_trireg`, `:vcd_tri0`, `:vcd_tri1`, `:vcd_wand`, `:vcd_wire`, `:vcd_wor`, `:vcd_port`, `:vcd_sparray`, `:vcd_realtime`, `:gen_string`, `:sv_bit`, `:sv_logic`, `:sv_int`, `:sv_shortint`, `:sv_longint`, `:sv_byte`, `:sv_enum` or `:sv_shortreal`.
1865
+ * @param direction [Symbol] either `:implicit`, `:input`, `:output`, `:inout`, `:buffer` or `:linkage`.
1866
+ * @param length [Integer]
1867
+ * @param alias_of [Variable,nil]
1868
+ * @param sup_type_str [String,nil] supplemental type string
1869
+ * @param sup_var_type [Symbol,nil] supplemental variable type, either `:none`, `:vhdl_signal`, `:vhdl_variable`, `:vhdl_constant`, `:vhdl_file` or `:vhdl_memory`.
1870
+ * @param sup_data_type [Symbol,nil] supplemental data type, either `:none`, `:vhdl_boolean`, `:vhdl_bit`, `:vhdl_bit_vector`, `:vhdl_std_ulogic`, `:vhdl_std_ulogic_vector`, `:vhdl_std_logic`, `:vhdl_std_logic_vector`, `:vhdl_unsigned`, `:vhdl_signed`, `:vhdl_integer`, `:vhdl_real`, `:vhdl_natural`, `:vhdl_positive`, `:vhdl_time`, `:vhdl_character` or `:vhdl_string`.
1871
+ */
1872
+ static VALUE libfst_writer_create_variable(int argc, VALUE *argv, VALUE self)
1873
+ {
1874
+ VALUE rbname;
1875
+ VALUE kw;
1876
+ const ID kwkeys[7] = {id_type, id_direction, id_length, id_alias_of, id_sup_type_str, id_sup_var_type, id_sup_data_type};
1877
+ VALUE kwvalues[7] = {Qundef, Qundef, Qundef, Qundef, Qundef, Qundef, Qundef};
1878
+
1879
+ const char *name = NULL;
1880
+ enum fstVarType vt;
1881
+ enum fstVarDir vd = FST_VD_IMPLICIT;
1882
+ uint32_t len = 0;
1883
+ fstHandle aliasHandle = 0;
1884
+ const char *type = NULL;
1885
+ enum fstSupplementalVarType svt = FST_SVT_NONE;
1886
+ enum fstSupplementalDataType sdt = FST_SDT_NONE;
1887
+ VALUE alias_variable = Qnil;
1888
+
1889
+ rb_scan_args(argc, argv, "01:", &rbname, &kw);
1890
+ rb_get_kwargs(kw, kwkeys, 0, 7, kwvalues);
1891
+
1892
+ if (kwvalues[3] != Qundef && !NIL_P(kwvalues[3])) {
1893
+ if (rb_obj_is_kind_of(kwvalues[3], c_WVariable)) {
1894
+ alias_variable = kwvalues[3];
1895
+ aliasHandle = rb_to_unsigned_int(rb_ivar_get(alias_variable, id_at_handle));
1896
+ } else {
1897
+ rb_raise(rb_eTypeError, "invalid alias, expecting a %"PRIsVALUE", not a %s", c_WVariable, rb_obj_classname(kwvalues[3]));
1898
+ }
1899
+ if (!NIL_P(rb_ivar_get(alias_variable, id_at_alias_of)))
1900
+ rb_raise(rb_eRuntimeError, "do not alias a %"PRIsVALUE" which already is an alias for another %"PRIsVALUE, c_WVariable, c_WVariable);
1901
+ if (rb_ivar_get(alias_variable, id_at_writer) != self)
1902
+ rb_raise(rb_eRuntimeError, "cannot alias a variable of another %s", rb_obj_classname(self));
1903
+ }
1904
+
1905
+ if (!NIL_P(rbname)) {
1906
+ name = rb_string_value_cstr(&rbname);
1907
+ } else if (!NIL_P(alias_variable)) {
1908
+ rbname = rb_ivar_get(alias_variable, id_at_name);
1909
+ name = rb_string_value_cstr(&rbname);
1910
+ } else {
1911
+ rb_raise(rb_eArgError, "wrong number of arguments (given 0, expected 1)");
1912
+ }
1913
+
1914
+
1915
+ if (kwvalues[0] != Qundef && !NIL_P(kwvalues[0]))
1916
+ vt = symbol_to_fstVarType(kwvalues[0]);
1917
+ else if (!NIL_P(alias_variable))
1918
+ vt = symbol_to_fstVarType(rb_ivar_get(alias_variable, id_at_type));
1919
+ else
1920
+ rb_raise(rb_eArgError, "missing keyword: :type");
1921
+
1922
+ if (kwvalues[1] != Qundef && !NIL_P(kwvalues[1]))
1923
+ vd = symbol_to_fstVarDir(kwvalues[1]);
1924
+ else if (alias_variable != Qnil)
1925
+ vd = symbol_to_fstVarDir(rb_ivar_get(alias_variable, id_at_direction));
1926
+
1927
+ if (kwvalues[2] != Qundef && !NIL_P(kwvalues[2]))
1928
+ len = rb_to_unsigned_int(kwvalues[2]);
1929
+ else if (alias_variable != Qnil)
1930
+ len = rb_to_unsigned_int(rb_ivar_get(alias_variable, id_at_length));
1931
+
1932
+ if (kwvalues[4] != Qundef && !NIL_P(kwvalues[4])) {
1933
+ type = rb_string_value_cstr(&kwvalues[4]);
1934
+ } else if (alias_variable != Qnil && rb_ivar_get(alias_variable, id_at_sup_type_str) != Qnil) {
1935
+ kwvalues[4] = rb_ivar_get(alias_variable, id_at_sup_type_str);
1936
+ type = rb_string_value_cstr(&kwvalues[4]);
1937
+ }
1938
+
1939
+ if (kwvalues[5] != Qundef && !NIL_P(kwvalues[5])) {
1940
+ svt = symbol_to_fstSupplementalVarType(kwvalues[5]);
1941
+ } else if (alias_variable != Qnil && rb_ivar_get(alias_variable, id_at_sup_var_type) != Qnil) {
1942
+ kwvalues[5] = rb_ivar_get(alias_variable, id_at_sup_var_type);
1943
+ svt = symbol_to_fstSupplementalVarType(kwvalues[5]);
1944
+ }
1945
+
1946
+ if (kwvalues[6] != Qundef && !NIL_P(kwvalues[6])) {
1947
+ sdt = symbol_to_fstSupplementalDataType(kwvalues[6]);
1948
+ } else if (alias_variable != Qnil && rb_ivar_get(alias_variable, id_at_sup_data_type) != Qnil) {
1949
+ kwvalues[6] = rb_ivar_get(alias_variable, id_at_sup_data_type);
1950
+ sdt = symbol_to_fstSupplementalDataType(kwvalues[6]);
1951
+ }
1952
+
1953
+ switch (vt) {
1954
+ case FST_VT_SV_INT: /* declare as size = 32 */
1955
+ len = 32;
1956
+ break;
1957
+ case FST_VT_SV_SHORTINT: /* declare as size = 16 */
1958
+ len = 16;
1959
+ break;
1960
+ case FST_VT_SV_LONGINT: /* declare as size = 64 */
1961
+ len = 64;
1962
+ break;
1963
+ case FST_VT_SV_BYTE: /* declare as size = 8 */
1964
+ len = 8;
1965
+ break;
1966
+ case FST_VT_GEN_STRING: /* generic string type (max len is defined dynamically via fstWriterEmitVariableLengthValueChange) */
1967
+ len = 0;
1968
+ break;
1969
+ case FST_VT_VCD_EVENT:
1970
+ len = 1;
1971
+ break;
1972
+
1973
+ case FST_VT_VCD_INTEGER:
1974
+ case FST_VT_VCD_PARAMETER:
1975
+ if (len == 0)
1976
+ len = 32;
1977
+ break;
1978
+
1979
+ case FST_VT_VCD_SUPPLY0:
1980
+ case FST_VT_VCD_SUPPLY1:
1981
+ case FST_VT_VCD_TIME:
1982
+ case FST_VT_VCD_TRI:
1983
+ case FST_VT_VCD_TRIAND:
1984
+ case FST_VT_VCD_TRIOR:
1985
+ case FST_VT_VCD_TRIREG:
1986
+ case FST_VT_VCD_TRI0:
1987
+ case FST_VT_VCD_TRI1:
1988
+ case FST_VT_VCD_WAND:
1989
+ case FST_VT_VCD_WOR:
1990
+ case FST_VT_VCD_PORT:
1991
+ case FST_VT_VCD_SPARRAY:
1992
+
1993
+ case FST_VT_VCD_WIRE:
1994
+ case FST_VT_VCD_REG:
1995
+ case FST_VT_SV_BIT:
1996
+ case FST_VT_SV_LOGIC:
1997
+ if (len == 0)
1998
+ len = 1;
1999
+ break;
2000
+
2001
+
2002
+ case FST_VT_VCD_REAL:
2003
+ case FST_VT_VCD_REAL_PARAMETER:
2004
+ case FST_VT_VCD_REALTIME:
2005
+ case FST_VT_SV_SHORTREAL: /* declare and emit same as FST_VT_VCD_REAL (needs to be emitted as double, not a float) */
2006
+ len = 8; /* recast number of bytes to that of what a double is */
2007
+ break;
2008
+
2009
+ // case FST_VT_SV_ENUM: /* declare as appropriate type range */
2010
+
2011
+ default:
2012
+ break;
2013
+ }
2014
+
2015
+
2016
+ fstHandle var = 0;
2017
+ void *ctx = libfst_writer_from_rbobj(self);
2018
+ if (type == NULL && svt == FST_SVT_NONE && sdt == FST_SDT_NONE)
2019
+ var = fstWriterCreateVar(ctx, vt, vd, len, name, aliasHandle);
2020
+ else
2021
+ var = fstWriterCreateVar2(ctx, vt, vd, len, name, aliasHandle, type, svt, sdt);
2022
+
2023
+ VALUE args[10];
2024
+ args[0] = ULONG2NUM(var); // handle
2025
+ args[1] = self; // writer
2026
+ args[2] = rbname; // name
2027
+ args[3] = fstVarType_to_symbol(vt); // type
2028
+ args[4] = fstVarDir_to_symbol(vd); // direction
2029
+ args[5] = ULONG2NUM(len); // length
2030
+ args[6] = alias_variable; // alias
2031
+ args[7] = (kwvalues[4] != Qundef ? kwvalues[4] : Qnil); // sup_type_str
2032
+ args[8] = (kwvalues[5] != Qundef ? kwvalues[5] : Qnil); // sup_var_type
2033
+ args[9] = (kwvalues[6] != Qundef ? kwvalues[6] : Qnil); // sup_data_type
2034
+ VALUE variable = rb_class_new_instance(10, args, c_WVariable);
2035
+ rb_ary_push(rb_ivar_get(self, id_at_variables), variable);
2036
+
2037
+ return variable;
2038
+ }
2039
+
2040
+
2041
+ /* Use this method to emit a value change of a variable of known size (`length` different from 0 in {#create_variable}).
2042
+ *
2043
+ * `data.bytesize` must match the `length` parameter of the variable creation.
2044
+ * @param handle [Integer] handle of a variable
2045
+ * @param data [String]
2046
+ * @return [self]
2047
+ */
2048
+ static VALUE libfst_writer_emit_value_change(VALUE self, VALUE handle, VALUE data)
2049
+ {
2050
+ fstHandle hndl = rb_to_unsigned_int(handle);
2051
+ const char *dt = rb_string_value_ptr(&data);
2052
+ void *ctx = libfst_writer_from_rbobj(self);
2053
+ fstWriterEmitValueChange(ctx, hndl, dt);
2054
+ return self;
2055
+ }
2056
+
2057
+
2058
+ /* @!visibility private
2059
+ */
2060
+ static VALUE libfst_writervariable_initialize(VALUE self, VALUE handle, VALUE writer, VALUE name, VALUE type, VALUE direction, VALUE length, VALUE alias, VALUE sup_type_str, VALUE sup_var_type, VALUE sup_data_type)
2061
+ {
2062
+ rb_ivar_set(self, id_at_handle, handle);
2063
+ rb_ivar_set(self, id_at_writer, writer);
2064
+ rb_ivar_set(self, id_at_name, name);
2065
+ rb_ivar_set(self, id_at_type, type);
2066
+ rb_ivar_set(self, id_at_direction, direction);
2067
+ rb_ivar_set(self, id_at_length, length);
2068
+ if (!NIL_P(alias))
2069
+ rb_ivar_set(self, id_at_alias_of, alias);
2070
+ if (!NIL_P(sup_type_str))
2071
+ rb_ivar_set(self, id_at_sup_type_str, sup_type_str);
2072
+ if (!NIL_P(sup_var_type))
2073
+ rb_ivar_set(self, id_at_sup_var_type, sup_var_type);
2074
+ if (!NIL_P(sup_data_type))
2075
+ rb_ivar_set(self, id_at_sup_data_type, sup_data_type);
2076
+ return self;
2077
+ }
2078
+
2079
+
2080
+ static void libfst_writer_emit_string(VALUE variable, VALUE str)
2081
+ {
2082
+ void *ctx = libfst_writer_from_rbobj(rb_ivar_get(variable, id_at_writer));
2083
+ fstHandle handle = NUM2ULONG(rb_ivar_get(variable, id_at_handle));
2084
+ if (!RB_TYPE_P(str, T_STRING))
2085
+ str = rb_funcallv(str, id_to_s, 0, NULL);
2086
+ const char *ptr = rb_string_value_ptr(&str);
2087
+ long len = RSTRING_LEN(str);
2088
+ fstWriterEmitVariableLengthValueChange(ctx, handle, ptr, len);
2089
+ }
2090
+
2091
+
2092
+ static void libfst_writer_emit_event(VALUE variable)
2093
+ {
2094
+ void *ctx = libfst_writer_from_rbobj(rb_ivar_get(variable, id_at_writer));
2095
+ char buf[] = "1";
2096
+ fstHandle handle = NUM2ULONG(rb_ivar_get(variable, id_at_handle));
2097
+ fstWriterEmitValueChange(ctx, handle, buf);
2098
+ }
2099
+
2100
+
2101
+ static void libfst_writer_emit_float(VALUE variable, VALUE flt)
2102
+ {
2103
+ void *ctx = libfst_writer_from_rbobj(rb_ivar_get(variable, id_at_writer));
2104
+ fstHandle handle = NUM2ULONG(rb_ivar_get(variable, id_at_handle));
2105
+ if (!RB_FLOAT_TYPE_P(flt))
2106
+ flt = rb_funcallv(flt, id_to_f, 0, NULL);
2107
+ double d = NUM2DBL(flt);
2108
+ fstWriterEmitValueChange(ctx, handle, &d);
2109
+ }
2110
+
2111
+
2112
+ static void libfst_writer_emit_integer(VALUE variable, VALUE intg)
2113
+ {
2114
+ void *ctx = libfst_writer_from_rbobj(rb_ivar_get(variable, id_at_writer));
2115
+ fstHandle handle = NUM2ULONG(rb_ivar_get(variable, id_at_handle));
2116
+ int len = NUM2INT(rb_ivar_get(variable, id_at_length));
2117
+ if (len < 1 || len > 65536)
2118
+ rb_raise(rb_eRuntimeError, "Variable's length is strange: %d", len);
2119
+ if (!RB_INTEGER_TYPE_P(intg))
2120
+ intg = rb_funcallv(intg, id_to_i, 1, &intg);
2121
+
2122
+ if (len <= 32) {
2123
+ int64_t l = NUM2LL(intg);
2124
+ fstWriterEmitValueChange32(ctx, handle, len, l);
2125
+ } else if (len <= 63) {
2126
+ uint64_t l = NUM2LL(intg);
2127
+ fstWriterEmitValueChange64(ctx, handle, len, l);
2128
+ } else {
2129
+ /* s = intg.to_s(2).rjust(len, '0')
2130
+ */
2131
+ VALUE args[3];
2132
+ args[0] = INT2NUM(2);
2133
+ args[1] = INT2NUM(len);
2134
+ args[2] = rb_sprintf("0");
2135
+ VALUE s = rb_funcallv(intg, id_to_s, 1, args);
2136
+ VALUE t = rb_funcallv(s, id_rjust, 2, &args[1]);
2137
+ const char *ptr = rb_string_value_ptr(&t);
2138
+ fstWriterEmitValueChange(ctx, handle, ptr);
2139
+ }
2140
+ }
2141
+
2142
+
2143
+ static void libfst_writer_emit_logic(VALUE variable, VALUE logic)
2144
+ {
2145
+ void *ctx = libfst_writer_from_rbobj(rb_ivar_get(variable, id_at_writer));
2146
+ fstHandle handle = NUM2ULONG(rb_ivar_get(variable, id_at_handle));
2147
+ if (RB_INTEGER_TYPE_P(logic)) {
2148
+ libfst_writer_emit_integer(variable, logic);
2149
+ } else if (NIL_P(logic)) {
2150
+ VALUE u = rb_sprintf("u");
2151
+ VALUE f = rb_ivar_get(variable, id_at_length);
2152
+ VALUE s = rb_funcallv(u, id_symbol_star, 1, &f);
2153
+ const char *ptr = rb_string_value_ptr(&s);
2154
+ fstWriterEmitValueChange(ctx, handle, ptr);
2155
+ } else {
2156
+ VALUE s = rb_funcallv(logic, id_to_s, 0, NULL);
2157
+ VALUE len = rb_ivar_get(variable, id_at_length);
2158
+ int vlength = NUM2INT(len);
2159
+ int slength = RSTRING_LEN(s);
2160
+ if (slength < vlength) {
2161
+ VALUE args[2];
2162
+ args[0] = len;
2163
+ args[1] = rb_sprintf("u");
2164
+ s = rb_funcallv(s, id_rjust, 2, args);
2165
+ } else if (slength > vlength) {
2166
+ s = rb_str_substr(s, -vlength, vlength);
2167
+ }
2168
+ const char *ptr = rb_string_value_ptr(&s);
2169
+ fstWriterEmitValueChange(ctx, handle, ptr);
2170
+ }
2171
+ }
2172
+
2173
+
2174
+ /* Emit the given value.
2175
+ * @param value [String,Integer,Float,nil]
2176
+ * @return [Object] value
2177
+ */
2178
+ static VALUE libfst_writervariable_emit_value(VALUE self, VALUE value)
2179
+ {
2180
+ VALUE rbtype = rb_ivar_get(self, id_at_type);
2181
+ enum fstVarType type = symbol_to_fstVarType(rbtype);
2182
+ switch (type) {
2183
+ case FST_VT_VCD_REG:
2184
+ case FST_VT_VCD_SUPPLY0:
2185
+ case FST_VT_VCD_SUPPLY1:
2186
+ case FST_VT_VCD_TRI:
2187
+ case FST_VT_VCD_TRIAND:
2188
+ case FST_VT_VCD_TRIOR:
2189
+ case FST_VT_VCD_TRIREG:
2190
+ case FST_VT_VCD_TRI0:
2191
+ case FST_VT_VCD_TRI1:
2192
+ case FST_VT_VCD_WAND:
2193
+ case FST_VT_VCD_WIRE:
2194
+ case FST_VT_VCD_WOR:
2195
+ case FST_VT_VCD_PORT:
2196
+ case FST_VT_VCD_SPARRAY:
2197
+ case FST_VT_SV_BIT:
2198
+ case FST_VT_SV_LOGIC:
2199
+ libfst_writer_emit_logic(self, value);
2200
+ break;
2201
+
2202
+ case FST_VT_VCD_REAL:
2203
+ case FST_VT_VCD_REAL_PARAMETER:
2204
+ case FST_VT_VCD_REALTIME:
2205
+ case FST_VT_SV_SHORTREAL:
2206
+ libfst_writer_emit_float(self, value);
2207
+ break;
2208
+
2209
+ case FST_VT_VCD_INTEGER:
2210
+ case FST_VT_VCD_PARAMETER:
2211
+ case FST_VT_SV_INT:
2212
+ case FST_VT_SV_SHORTINT:
2213
+ case FST_VT_SV_LONGINT:
2214
+ case FST_VT_SV_BYTE:
2215
+ case FST_VT_VCD_TIME:
2216
+ libfst_writer_emit_integer(self, value);
2217
+ break;
2218
+
2219
+ case FST_VT_GEN_STRING:
2220
+ libfst_writer_emit_string(self, value);
2221
+ break;
2222
+
2223
+ case FST_VT_VCD_EVENT:
2224
+ libfst_writer_emit_event(self);
2225
+ break;
2226
+
2227
+ case FST_VT_SV_ENUM:
2228
+ rb_raise(rb_eRuntimeError, "Sorry, I dont know how to handle enums =(");
2229
+ break;
2230
+
2231
+ default:
2232
+ rb_raise(rb_eRuntimeError, "%s has invalid @type (%"PRIsVALUE")", rb_obj_classname(self), rbtype);
2233
+ }
2234
+ rb_ivar_set(self, id_at_value, value);
2235
+ return value;
2236
+ }
2237
+
2238
+
2239
+ /* Return the last set value.
2240
+ * @return [Object]
2241
+ */
2242
+ static VALUE libfst_writervariable_get_value(VALUE self)
2243
+ {
2244
+ return rb_ivar_get(self, id_at_value);
2245
+ }
2246
+
2247
+
2248
+ #ifdef TARZAN_LA_BANANE
2249
+ fstEnumHandle fstWriterCreateEnumTable(void *ctx, const char *name, uint32_t elem_count, unsigned int min_valbits, const char **literal_arr, const char **val_arr);
2250
+ void fstWriterEmitEnumTableRef(void *ctx, fstEnumHandle handle);
2251
+
2252
+ void fstWriterEmitValueChange32(void *ctx, fstHandle handle, uint32_t bits, uint32_t val);
2253
+ void fstWriterEmitValueChange64(void *ctx, fstHandle handle, uint32_t bits, uint64_t val);
2254
+ void fstWriterEmitValueChangeVec32(void *ctx, fstHandle handle, uint32_t bits, const uint32_t *val);
2255
+ void fstWriterEmitValueChangeVec64(void *ctx, fstHandle handle, uint32_t bits, const uint64_t *val);
2256
+ #endif
2257
+
2258
+
2259
+ void Init_libfst(void)
2260
+ {
2261
+ id_at_alias_of = rb_intern("@alias_of");
2262
+ id_at_direction = rb_intern("@direction");
2263
+ id_at_filename = rb_intern("@filename");
2264
+ id_at_handle = rb_intern("@handle");
2265
+ id_at_is_float = rb_intern("@is_float");
2266
+ id_at_length = rb_intern("@length");
2267
+ id_at_name = rb_intern("@name");
2268
+ id_at_sup_data_type = rb_intern("@sup_data_type");
2269
+ id_at_sup_type_str = rb_intern("@sup_type_str");
2270
+ id_at_sup_var_type = rb_intern("@sup_var_type");
2271
+ id_at_trace = rb_intern("@trace");
2272
+ id_at_traces = rb_intern("@traces");
2273
+ id_at_type = rb_intern("@type");
2274
+ id_at_value = rb_intern("@value");
2275
+ id_at_variables = rb_intern("@variables");
2276
+ id_at_writer = rb_intern("@writer");
2277
+ id_to_s = rb_intern("to_s");
2278
+ id_to_f = rb_intern("to_f");
2279
+ id_to_i = rb_intern("to_i");
2280
+ id_rjust = rb_intern("rjust");
2281
+ id_compress_hier = rb_intern("compress_hier");
2282
+ id_delete = rb_intern("delete");
2283
+ id_name = rb_intern("name");
2284
+ id_component = rb_intern("component");
2285
+ id_symbol_plus = rb_intern("+");
2286
+ id_symbol_star = rb_intern("*");
2287
+ id_symbol_more = rb_intern(">");
2288
+ id_expand_path = rb_intern("expand_path");
2289
+ id_start_time = rb_intern("start_time");
2290
+ id_end_time = rb_intern("end_time");
2291
+ id_verilog = rb_intern("verilog");
2292
+ id_vhdl = rb_intern("vhdl");
2293
+ id_verilog_or_vhdl = rb_intern("verilog_or_vhdl");
2294
+ id_vcd_module = rb_intern("vcd_module");
2295
+ id_vcd_task = rb_intern("vcd_task");
2296
+ id_vcd_function = rb_intern("vcd_function");
2297
+ id_vcd_begin = rb_intern("vcd_begin");
2298
+ id_vcd_fork = rb_intern("vcd_fork");
2299
+ id_vcd_generate = rb_intern("vcd_generate");
2300
+ id_vcd_struct = rb_intern("vcd_struct");
2301
+ id_vcd_union = rb_intern("vcd_union");
2302
+ id_vcd_class = rb_intern("vcd_class");
2303
+ id_vcd_interface = rb_intern("vcd_interface");
2304
+ id_vcd_package = rb_intern("vcd_package");
2305
+ id_vcd_program = rb_intern("vcd_program");
2306
+ id_vhdl_architecture = rb_intern("vhdl_architecture");
2307
+ id_vhdl_procedure = rb_intern("vhdl_procedure");
2308
+ id_vhdl_function = rb_intern("vhdl_function");
2309
+ id_vhdl_record = rb_intern("vhdl_record");
2310
+ id_vhdl_process = rb_intern("vhdl_process");
2311
+ id_vhdl_block = rb_intern("vhdl_block");
2312
+ id_vhdl_for_generate = rb_intern("vhdl_for_generate");
2313
+ id_vhdl_if_generate = rb_intern("vhdl_if_generate");
2314
+ id_vhdl_generate = rb_intern("vhdl_generate");
2315
+ id_vhdl_package = rb_intern("vhdl_package");
2316
+ id_vcd_event = rb_intern("vcd_event");
2317
+ id_vcd_integer = rb_intern("vcd_integer");
2318
+ id_vcd_parameter = rb_intern("vcd_parameter");
2319
+ id_vcd_real = rb_intern("vcd_real");
2320
+ id_vcd_real_parameter = rb_intern("vcd_real_parameter");
2321
+ id_vcd_reg = rb_intern("vcd_reg");
2322
+ id_vcd_supply0 = rb_intern("vcd_supply0");
2323
+ id_vcd_supply1 = rb_intern("vcd_supply1");
2324
+ id_vcd_time = rb_intern("vcd_time");
2325
+ id_vcd_tri = rb_intern("vcd_tri");
2326
+ id_vcd_triand = rb_intern("vcd_triand");
2327
+ id_vcd_trior = rb_intern("vcd_trior");
2328
+ id_vcd_trireg = rb_intern("vcd_trireg");
2329
+ id_vcd_tri0 = rb_intern("vcd_tri0");
2330
+ id_vcd_tri1 = rb_intern("vcd_tri1");
2331
+ id_vcd_wand = rb_intern("vcd_wand");
2332
+ id_vcd_wire = rb_intern("vcd_wire");
2333
+ id_vcd_wor = rb_intern("vcd_wor");
2334
+ id_vcd_port = rb_intern("vcd_port");
2335
+ id_vcd_sparray = rb_intern("vcd_sparray");
2336
+ id_vcd_realtime = rb_intern("vcd_realtime");
2337
+ id_gen_string = rb_intern("gen_string");
2338
+ id_sv_bit = rb_intern("sv_bit");
2339
+ id_sv_logic = rb_intern("sv_logic");
2340
+ id_sv_int = rb_intern("sv_int");
2341
+ id_sv_shortint = rb_intern("sv_shortint");
2342
+ id_sv_longint = rb_intern("sv_longint");
2343
+ id_sv_byte = rb_intern("sv_byte");
2344
+ id_sv_enum = rb_intern("sv_enum");
2345
+ id_sv_shortreal = rb_intern("sv_shortreal");
2346
+ id_implicit = rb_intern("implicit");
2347
+ id_input = rb_intern("input");
2348
+ id_output = rb_intern("output");
2349
+ id_inout = rb_intern("inout");
2350
+ id_buffer = rb_intern("buffer");
2351
+ id_linkage = rb_intern("linkage");
2352
+ id_misc = rb_intern("misc");
2353
+ id_array = rb_intern("array");
2354
+ id_enum = rb_intern("enum");
2355
+ id_pack = rb_intern("pack");
2356
+ id_comment = rb_intern("comment");
2357
+ id_envvar = rb_intern("envvar");
2358
+ id_supvar = rb_intern("supvar");
2359
+ id_pathname = rb_intern("pathname");
2360
+ id_sourcestem = rb_intern("sourcestem");
2361
+ id_sourceistem = rb_intern("sourceistem");
2362
+ id_valuelist = rb_intern("valuelist");
2363
+ id_enumtable = rb_intern("enumtable");
2364
+ id_unknown = rb_intern("unknown");
2365
+ id_unpacked = rb_intern("unpacked");
2366
+ id_packed = rb_intern("packed");
2367
+ id_sparse = rb_intern("sparse");
2368
+ id_integer = rb_intern("integer");
2369
+ id_bit = rb_intern("bit");
2370
+ id_logic = rb_intern("logic");
2371
+ id_int = rb_intern("int");
2372
+ id_shortint = rb_intern("shortint");
2373
+ id_longint = rb_intern("longint");
2374
+ id_byte = rb_intern("byte");
2375
+ id_unsigned_integer = rb_intern("unsigned_integer");
2376
+ id_unsigned_bit = rb_intern("unsigned_bit");
2377
+ id_unsigned_logic = rb_intern("unsigned_logic");
2378
+ id_unsigned_int = rb_intern("unsigned_int");
2379
+ id_unsigned_shortint = rb_intern("unsigned_shortint");
2380
+ id_unsigned_longint = rb_intern("unsigned_longint");
2381
+ id_unsigned_byte = rb_intern("unsigned_byte");
2382
+ id_reg = rb_intern("reg");
2383
+ id_time = rb_intern("time");
2384
+ id_none = rb_intern("none");
2385
+ id_tagged_packed = rb_intern("tagged_packed");
2386
+ id_upscope = rb_intern("upscope");
2387
+ id_attrend = rb_intern("attrend");
2388
+ id_zlib = rb_intern("zlib");
2389
+ id_fastlz = rb_intern("fastlz");
2390
+ id_lz4 = rb_intern("lz4");
2391
+ id_s = rb_intern("s");
2392
+ id_ms = rb_intern("ms");
2393
+ id_us = rb_intern("us");
2394
+ id_ns = rb_intern("ns");
2395
+ id_ps = rb_intern("ps");
2396
+ id_fs = rb_intern("fs");
2397
+ id_type = rb_intern("type");
2398
+ id_subtype = rb_intern("subtype");
2399
+ id_arg = rb_intern("arg");
2400
+ id_use_realpath = rb_intern("use_realpath");
2401
+ id_vhdl_signal = rb_intern("vhdl_signal");
2402
+ id_vhdl_variable = rb_intern("vhdl_variable");
2403
+ id_vhdl_constant = rb_intern("vhdl_constant");
2404
+ id_vhdl_file = rb_intern("vhdl_file");
2405
+ id_vhdl_memory = rb_intern("vhdl_memory");
2406
+ id_vhdl_boolean = rb_intern("vhdl_boolean");
2407
+ id_vhdl_bit = rb_intern("vhdl_bit");
2408
+ id_vhdl_bit_vector = rb_intern("vhdl_bit_vector");
2409
+ id_vhdl_std_ulogic = rb_intern("vhdl_std_ulogic");
2410
+ id_vhdl_std_ulogic_vector = rb_intern("vhdl_std_ulogic_vector");
2411
+ id_vhdl_std_logic = rb_intern("vhdl_std_logic");
2412
+ id_vhdl_std_logic_vector = rb_intern("vhdl_std_logic_vector");
2413
+ id_vhdl_unsigned = rb_intern("vhdl_unsigned");
2414
+ id_vhdl_signed = rb_intern("vhdl_signed");
2415
+ id_vhdl_integer = rb_intern("vhdl_integer");
2416
+ id_vhdl_real = rb_intern("vhdl_real");
2417
+ id_vhdl_natural = rb_intern("vhdl_natural");
2418
+ id_vhdl_positive = rb_intern("vhdl_positive");
2419
+ id_vhdl_time = rb_intern("vhdl_time");
2420
+ id_vhdl_character = rb_intern("vhdl_character");
2421
+ id_vhdl_string = rb_intern("vhdl_string");
2422
+ id_direction = rb_intern("direction");
2423
+ id_length = rb_intern("length");
2424
+ id_alias_of = rb_intern("alias_of");
2425
+ id_sup_type_str = rb_intern("sup_type_str");
2426
+ id_sup_var_type = rb_intern("sup_var_type");
2427
+ id_sup_data_type = rb_intern("sup_data_type");
2428
+
2429
+
2430
+ m_LibFST = rb_define_module("LibFST");
2431
+
2432
+ c_Reader = rb_define_class_under(m_LibFST, "Reader", rb_cObject);
2433
+ rb_define_alloc_func(c_Reader, libfst_reader_alloc);
2434
+ rb_undef_method(rb_class_of(c_Reader), "allocate");
2435
+ rb_define_protected_method(c_Reader, "open", libfst_reader_open, 1);
2436
+ rb_define_method(c_Reader, "iterate_hier", libfst_reader_iterate_hier, 0);
2437
+ rb_define_method(c_Reader, "iterate_hier_rewind", libfst_reader_iterate_hier_rewind, 0);
2438
+ rb_define_method(c_Reader, "current_scope_length", libfst_reader_current_scope_length, 0);
2439
+ rb_define_method(c_Reader, "current_flat_scope", libfst_reader_current_flat_scope, 0);
2440
+ rb_define_method(c_Reader, "pop_scope", libfst_reader_pop_scope, 0);
2441
+ rb_define_method(c_Reader, "reset_scope", libfst_reader_reset_scope, 0);
2442
+ rb_define_method(c_Reader, "push_scope", libfst_reader_push_scope, -1);
2443
+ rb_define_method(c_Reader, "fseek_failed?", libfst_reader_fseek_failed, 0);
2444
+ rb_define_method(c_Reader, "date_string", libfst_reader_date_string, 0);
2445
+ rb_define_method(c_Reader, "version_string", libfst_reader_version_string, 0);
2446
+ rb_define_method(c_Reader, "file_type", libfst_reader_file_type, 0);
2447
+ rb_define_method(c_Reader, "time_scale", libfst_reader_time_scale, 0);
2448
+ rb_define_method(c_Reader, "time_scale_exponent", libfst_reader_time_scale_exponent, 0);
2449
+ rb_define_method(c_Reader, "start_time", libfst_reader_start_time, 0);
2450
+ rb_define_method(c_Reader, "end_time", libfst_reader_end_time, 0);
2451
+ rb_define_method(c_Reader, "time_zero", libfst_reader_time_zero, 0);
2452
+ rb_define_method(c_Reader, "var_count", libfst_reader_var_count, 0);
2453
+ rb_define_method(c_Reader, "scope_count", libfst_reader_scope_count, 0);
2454
+ rb_define_method(c_Reader, "alias_count", libfst_reader_alias_count, 0);
2455
+ rb_define_method(c_Reader, "max_handle", libfst_reader_max_handle, 0);
2456
+ rb_define_method(c_Reader, "value_change_section_count", libfst_reader_value_change_section_count, 0);
2457
+ rb_define_method(c_Reader, "memory_used_by_writer", libfst_reader_memory_used_by_writer, 0);
2458
+ rb_define_method(c_Reader, "double_endian_match_state?", libfst_reader_double_endian_match_state, 0);
2459
+ rb_define_method(c_Reader, "number_dump_activity_changes", libfst_reader_number_dump_activity_changes, 0);
2460
+ rb_define_method(c_Reader, "dump_activity_change_time", libfst_reader_dump_activity_change_time, 1);
2461
+ rb_define_method(c_Reader, "dump_activity_change_value", libfst_reader_dump_activity_change_value, 1);
2462
+ rb_define_method(c_Reader, "read", libfst_reader_read, -1);
2463
+
2464
+ c_RScope = rb_define_class_under(c_Reader, "Scope", rb_cObject);
2465
+ c_RVariable = rb_define_class_under(c_Reader, "Variable", rb_cObject);
2466
+ c_RAttribute = rb_define_class_under(c_Reader, "Attribute", rb_cObject);
2467
+ c_RTrace = rb_define_class_under(c_Reader, "Trace", rb_cObject);
2468
+
2469
+ rb_undef_method(rb_class_of(c_RVariable), "new");
2470
+ rb_undef_method(rb_class_of(c_RAttribute), "new");
2471
+
2472
+
2473
+ c_Writer = rb_define_class_under(m_LibFST, "Writer", rb_cObject);
2474
+ rb_define_alloc_func(c_Writer, libfst_writer_alloc);
2475
+ rb_undef_method(rb_class_of(c_Writer), "allocate");
2476
+ rb_define_method(c_Writer, "initialize", libfst_writer_initialize, -1);
2477
+ rb_define_method(c_Writer, "close", libfst_writer_close, 0);
2478
+ rb_define_attr(c_Writer, "filename", 1, 0); // @return [String]
2479
+ rb_define_attr(c_Writer, "variables", 1, 0); // @return [Array<Variable>]
2480
+ rb_define_method(c_Writer, "set_date_string", libfst_writer_set_date_string, 1);
2481
+ rb_define_method(c_Writer, "set_version_string", libfst_writer_set_version_string, 1);
2482
+ rb_define_method(c_Writer, "set_time_zero", libfst_writer_set_time_zero, 1);
2483
+ rb_define_method(c_Writer, "set_time_scale", libfst_writer_set_time_scale, 1);
2484
+ rb_define_method(c_Writer, "set_file_type", libfst_writer_set_file_type, 1);
2485
+ rb_define_method(c_Writer, "set_pack_type", libfst_writer_set_pack_type, 1);
2486
+ rb_define_method(c_Writer, "set_comment", libfst_writer_set_comment, 1);
2487
+ rb_define_method(c_Writer, "set_envvar", libfst_writer_set_envvar, 1);
2488
+ rb_define_method(c_Writer, "set_value_list", libfst_writer_set_value_list, 1);
2489
+ rb_define_method(c_Writer, "set_attribute_begin", libfst_writer_set_attribute_begin, -1);
2490
+ rb_define_method(c_Writer, "set_attribute_end", libfst_writer_set_attribute_end, 0);
2491
+ rb_define_method(c_Writer, "set_scope", libfst_writer_set_scope, -1);
2492
+ rb_define_method(c_Writer, "set_upscope", libfst_writer_set_upscope, 0);
2493
+ rb_define_method(c_Writer, "set_source_stem", libfst_writer_set_source_stem, -1);
2494
+ rb_define_method(c_Writer, "set_source_instantiation_stem", libfst_writer_set_source_instantiation_stem, -1);
2495
+ rb_define_method(c_Writer, "create_variable", libfst_writer_create_variable, -1);
2496
+ rb_define_method(c_Writer, "emit_time_change", libfst_writer_emit_time_change, 1);
2497
+ rb_define_method(c_Writer, "emit_value_change", libfst_writer_emit_value_change, 2);
2498
+
2499
+ rb_define_method(c_Writer, "emit_dump_active", libfst_writer_emit_dump_active, 1);
2500
+ rb_define_method(c_Writer, "fseek_failed?", libfst_writer_fseek_failed, 0);
2501
+ rb_define_method(c_Writer, "dump_size_limit_reached?", libfst_writer_dump_size_limit_reached, 0);
2502
+ rb_define_method(c_Writer, "set_dump_size_limit", libfst_writer_set_dump_size_limit, 1);
2503
+ rb_define_method(c_Writer, "set_use_parallel_mode", libfst_writer_set_use_parallel_mode, 1);
2504
+ rb_define_method(c_Writer, "set_repack_on_close", libfst_writer_set_repack_on_close, 1);
2505
+ rb_define_method(c_Writer, "flush_context", libfst_writer_flush_context, 0);
2506
+
2507
+ c_WVariable = rb_define_class_under(c_Writer, "Variable", rb_cObject);
2508
+ rb_undef_method(rb_class_of(c_WVariable), "new");
2509
+ rb_define_method(c_WVariable, "initialize", libfst_writervariable_initialize, 10);
2510
+ rb_define_method(c_WVariable, "value=", libfst_writervariable_emit_value, 1);
2511
+ rb_define_method(c_WVariable, "value", libfst_writervariable_get_value, 0);
2512
+ rb_define_attr(c_WVariable, "handle", 1, 0); // @return [Integer]
2513
+ rb_define_attr(c_WVariable, "writer", 1, 0); // @return [Writer]
2514
+ rb_define_attr(c_WVariable, "name", 1, 0); // @return [String]
2515
+ rb_define_attr(c_WVariable, "type", 1, 0); // @return [Symbol] either `:vcd_event`, `:vcd_integer`, `:vcd_parameter`, `:vcd_real`, `:vcd_real_parameter`, `:vcd_reg`, `:vcd_supply0`, `:vcd_supply1`, `:vcd_time`, `:vcd_tri`, `:vcd_triand`, `:vcd_trior`, `:vcd_trireg`, `:vcd_tri0`, `:vcd_tri1`, `:vcd_wand`, `:vcd_wire`, `:vcd_wor`, `:vcd_port`, `:vcd_sparray`, `:vcd_realtime`, `:gen_string`, `:sv_bit`, `:sv_logic`, `:sv_int`, `:sv_shortint`, `:sv_longint`, `:sv_byte`, `:sv_enum` or `:sv_shortreal`
2516
+ rb_define_attr(c_WVariable, "direction", 1, 0); // @return [Symbol] either `:implicit`, `:input`, `:output`, `:inout`, `:buffer` or `:linkage`
2517
+ rb_define_attr(c_WVariable, "length", 1, 0); // @return [Integer]
2518
+ rb_define_attr(c_WVariable, "alias_of", 1, 0); // @return [Variable,nil]
2519
+ rb_define_attr(c_WVariable, "sup_type_str", 1, 0); // @return [String,nil] supplemental type string
2520
+ rb_define_attr(c_WVariable, "sup_var_type", 1, 0); // @return [Symbol,nil] supplemental variable type, either `:none`, `:vhdl_signal`, `:vhdl_variable`, `:vhdl_constant`, `:vhdl_file` or `:vhdl_memory`
2521
+ rb_define_attr(c_WVariable, "sup_data_type", 1, 0); // @return [Symbol,nil] supplemental data type, either `:none`, `:vhdl_boolean`, `:vhdl_bit`, `:vhdl_bit_vector`, `:vhdl_std_ulogic`, `:vhdl_std_ulogic_vector`, `:vhdl_std_logic`, `:vhdl_std_logic_vector`, `:vhdl_unsigned`, `:vhdl_signed`, `:vhdl_integer`, `:vhdl_real`, `:vhdl_natural`, `:vhdl_positive`, `:vhdl_time`, `:vhdl_character` or `:vhdl_string`
2522
+
2523
+ }
2524
+
2525
+