Class: LibFST::Reader

Inherits:
Object
  • Object
show all
Defined in:
lib/libfst/reader.rb,
lib/libfst/reader.rb,
ext/libfst_rb.c

Defined Under Namespace

Classes: Attribute, Scope, Trace, Variable

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(filename) ⇒ Reader

Returns a new instance of Reader.



213
214
215
216
217
218
219
# File 'lib/libfst/reader.rb', line 213

def initialize(filename)
  @filename = File.expand_path(filename)
  open(@filename)
  @traces = max_handle.times.collect { |i| Trace.new(i+1) }
  @variables = []
  travel_hierarchy
end

Instance Attribute Details

#filenameString (readonly)

Returns:

  • (String)


208
209
210
# File 'lib/libfst/reader.rb', line 208

def filename
  @filename
end

#rootScope (readonly)

Returns:



211
212
213
# File 'lib/libfst/reader.rb', line 211

def root
  @root
end

#tracesArray<Trace> (readonly)

Returns:



209
210
211
# File 'lib/libfst/reader.rb', line 209

def traces
  @traces
end

#variablesArray<Variable> (readonly)

Returns:



210
211
212
# File 'lib/libfst/reader.rb', line 210

def variables
  @variables
end

Instance Method Details

#[](path) ⇒ Scope, ...

Returns the scope or variable corresponding to the specified path

Parameters:

  • path (String)

Returns:

Raises:

  • (ArgumentError)


245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
# File 'lib/libfst/reader.rb', line 245

def [](path)
  raise ArgumentError, "expecting a String, not a #{path.class}" unless path.is_a?(String)
  a = path.split('/').reject(&:empty?)
  return nil if a.empty?
  return nil if a[0] != @root.name
  scope = @root
  var = nil
  a[1..].each do |w|
    var = scope.variables.select { |v| v.name == w }.first
    return var if var
    s = scope.children.select { |v| v.name == w }.first
    return nil if s.nil?
    scope = s
  end
  scope
end

#alias_countInteger

Returns the number of variables which point to the same trace.

Returns:

  • (Integer)


313
314
315
316
317
318
# File 'ext/libfst_rb.c', line 313

static VALUE libfst_reader_alias_count(VALUE self)
{
  void *ctx = libfst_reader_from_rbobj(self);
  uint64_t alias_count = fstReaderGetAliasCount(ctx);
  return RB_ULL2NUM(alias_count);
}

#current_flat_scopeString

Returns:

  • (String)


331
332
333
334
335
336
# File 'ext/libfst_rb.c', line 331

static VALUE libfst_reader_current_flat_scope(VALUE self)
{
  void *ctx = libfst_reader_from_rbobj(self);
  const char* str = fstReaderGetCurrentFlatScope(ctx);
  return rb_utf8_str_new_cstr(str);
}

#current_scope_lengthInteger

Returns:

  • (Integer)


323
324
325
326
# File 'ext/libfst_rb.c', line 323

static VALUE libfst_reader_current_scope_length(VALUE self)
{
  return RB_INT2NUM(fstReaderGetCurrentScopeLen(libfst_reader_from_rbobj(self)));
}

#date_stringString

Date string produced by the writer of the FST file

Returns:

  • (String)


342
343
344
345
346
347
# File 'ext/libfst_rb.c', line 342

static VALUE libfst_reader_date_string(VALUE self)
{
  void *ctx = libfst_reader_from_rbobj(self);
  const char* str = fstReaderGetDateString(ctx);
  return rb_utf8_str_new_cstr(str);
}

#double_endian_match_state?Boolean

Returns:

  • (Boolean)


477
478
479
480
481
# File 'ext/libfst_rb.c', line 477

static VALUE libfst_reader_double_endian_match_state(VALUE self)
{
  void *ctx = libfst_reader_from_rbobj(self);
  return (fstReaderGetDoubleEndianMatchState(ctx) ? Qtrue : Qfalse);
}

#dump_activity_change_time(idx) ⇒ Integer

Returns:

  • (Integer)


805
806
807
808
809
810
811
# File 'ext/libfst_rb.c', line 805

static VALUE libfst_reader_dump_activity_change_time(VALUE self, VALUE idx)
{
  void *ctx = libfst_reader_from_rbobj(self);
  uint32_t x = NUM2ULONG(idx);
  uint64_t t = fstReaderGetDumpActivityChangeTime(ctx, x);
  return ULL2NUM(t);
}

#dump_activity_change_value(idx) ⇒ Integer

Returns:

  • (Integer)


816
817
818
819
820
821
822
# File 'ext/libfst_rb.c', line 816

static VALUE libfst_reader_dump_activity_change_value(VALUE self, VALUE idx)
{
  void *ctx = libfst_reader_from_rbobj(self);
  uint32_t x = NUM2ULONG(idx);
  int t = fstReaderGetDumpActivityChangeValue(ctx, x);
  return INT2NUM(t);
}

#end_timeInteger

Returns:

  • (Integer)


384
385
386
387
388
389
# File 'ext/libfst_rb.c', line 384

static VALUE libfst_reader_end_time(VALUE self)
{
  void *ctx = libfst_reader_from_rbobj(self);
  uint64_t i = fstReaderGetEndTime(ctx);
  return RB_ULL2NUM(i);
}

#file_typeSymbol

Returns Either :verilog, :vhdl or :verilog_or_vhdl.

Returns:

  • (Symbol)

    Either :verilog, :vhdl or :verilog_or_vhdl.



404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
# File 'ext/libfst_rb.c', line 404

static VALUE libfst_reader_file_type(VALUE self)
{
  void *ctx = libfst_reader_from_rbobj(self);
  int ft = fstReaderGetFileType(ctx);
  ID id;
  switch (ft) {
    case FST_FT_VERILOG:
      id = id_verilog;
      break;
    case FST_FT_VHDL:
      id = id_vhdl;
      break;
    case FST_FT_VERILOG_VHDL:
      id = id_verilog_or_vhdl;
      break;
    default:
      rb_raise(rb_eRuntimeError, "Unknown file type %d", ft);
  }
  return rb_id2sym(id);
}

#fseek_failed?Boolean

Returns:

  • (Boolean)


468
469
470
471
472
# File 'ext/libfst_rb.c', line 468

static VALUE libfst_reader_fseek_failed(VALUE self)
{
  void *ctx = libfst_reader_from_rbobj(self);
  return (fstReaderGetFseekFailed(ctx) ? Qtrue : Qfalse);
}

#iterate_hierScope, ...

Iterate through the hierarchy. Successively call this method until it returns nil.

Returns:



776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
# File 'ext/libfst_rb.c', line 776

static VALUE libfst_reader_iterate_hier(VALUE self)
{
  void *ctx = libfst_reader_from_rbobj(self);
  struct fstHier *hier = fstReaderIterateHier(ctx);
  if (!hier) return Qnil;
  VALUE r = Qnil;
  switch (hier->htyp) {
    case FST_HT_SCOPE:      r = libfst_readerscope_from_struct(hier); break;
    case FST_HT_UPSCOPE:    r = rb_id2sym(id_upscope); break;
    case FST_HT_VAR:        r = libfst_readervar_from_struct(hier); break;
    case FST_HT_ATTRBEGIN:  r = libfst_readerattr_from_struct(hier); break;
    case FST_HT_ATTREND:    r = rb_id2sym(id_attrend); break;
  }
  return r;
}

#iterate_hier_rewindInteger

Returns:

  • (Integer)


572
573
574
575
576
577
# File 'ext/libfst_rb.c', line 572

static VALUE libfst_reader_iterate_hier_rewind(VALUE self)
{
  void *ctx = libfst_reader_from_rbobj(self);
  int r = fstReaderIterateHierRewind(ctx);
  return INT2NUM(r);
}

#max_handleInteger

Variable handles are integers from 1 to max_handle inclusive.

Returns:

  • (Integer)


796
797
798
799
800
# File 'ext/libfst_rb.c', line 796

static VALUE libfst_reader_max_handle(VALUE self)
{
  void *ctx = libfst_reader_from_rbobj(self);
  return ULONG2NUM(fstReaderGetMaxHandle(ctx));
}

#memory_used_by_writerInteger

Returns:

  • (Integer)


428
429
430
431
432
433
# File 'ext/libfst_rb.c', line 428

static VALUE libfst_reader_memory_used_by_writer(VALUE self)
{
  void *ctx = libfst_reader_from_rbobj(self);
  uint64_t i = fstReaderGetMemoryUsedByWriter(ctx);
  return RB_ULL2NUM(i);
}

#number_dump_activity_changesInteger

Returns:

  • (Integer)


458
459
460
461
462
463
# File 'ext/libfst_rb.c', line 458

static VALUE libfst_reader_number_dump_activity_changes(VALUE self)
{
  void *ctx = libfst_reader_from_rbobj(self);
  uint32_t i = fstReaderGetNumberDumpActivityChanges(ctx);
  return RB_ULL2NUM(i);
}

#pop_scopeString?

Returns:

  • (String, nil)


530
531
532
533
534
535
536
# File 'ext/libfst_rb.c', line 530

static VALUE libfst_reader_pop_scope(VALUE self)
{
  void *ctx = libfst_reader_from_rbobj(self);
  const char* str = fstReaderPopScope(ctx);
  if (!str) return Qnil;
  return rb_utf8_str_new_cstr(str);
}

#pretty_time(timei) ⇒ String

Pretty print the integer time given as parametter according to the time scale

Parameters:

  • timei (Integer)

Returns:

  • (String)


265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
# File 'lib/libfst/reader.rb', line 265

def pretty_time(timei)
  return '0 s' if timei == 0
  i = time_scale_exponent
  e = (i/3)*3
  f = 10**(i - e)
  timei *= f
  loop do
    break if e >= 0
    m = timei % 1000
    break if m != 0
    timei /= 1000
    e += 3
  end
  s = timei.to_s
  l = s.length
  i = ((l-1)/3)*3
  return "#{timei} #{['', 'm', 'µ', 'n', 'p', 'f'][-e/3]}s" if i <= 0 or e+i > 0
  e += i
  ent = s[0...l-i]
  frac = s[l-i..].sub(/0+$/, '')
  "#{ent}.#{frac} #{['', 'm', 'µ', 'n', 'p', 'f'][-e/3]}s"
end

#push_scope(name = nil) ⇒ String?

Parameters:

  • name (String, nil) (defaults to: nil)

Returns:

  • (String, nil)


553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
# File 'ext/libfst_rb.c', line 553

static VALUE libfst_reader_push_scope(int argc, VALUE *argv, VALUE self)
{
  void *ctx = libfst_reader_from_rbobj(self);
  VALUE name_rb = Qnil;
  const char *name_c = "";
  rb_scan_args(argc, argv, "01", &name_rb);
  if (!NIL_P(name_rb)) {
    if (!rb_obj_is_kind_of(name_rb, rb_cString))
      rb_raise(rb_eTypeError, "expecting a string, not a %s\n", rb_obj_classname(name_rb));
    name_c = rb_string_value_cstr(&name_rb);
  }
  const char *str = fstReaderPushScope(ctx, name_c, NULL);
  if (!str) return Qnil;
  return rb_utf8_str_new_cstr(str);
}

#read(*signals, start_time: nil, end_time: nil) {|trace, time, value, reader| ... } ⇒ Integer

Read the value changes of the traces.

The provided block is called for each value change found in the file.

If signals are specified, the block will be called only for thoses signals.

If a start time and/or an end time are specified, only value changes in this time window will be searched.

Parameters:

  • 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.

  • sart_time (Integer, Float, nil)

    Start time, either as an integer (in magnitude of #time_scale) or real time as a float.

  • end_time (Integer, Float, nil) (defaults to: nil)

    End time, either as an integer (in magnitude of #time_scale) or real time as a float.

Yield Parameters:

  • trace (Trace)
  • time (Integer)
  • value (String, Float)
  • reader (self)

Returns:

  • (Integer)


878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
# File 'ext/libfst_rb.c', line 878

static VALUE libfst_reader_read(int argc, VALUE *argv, VALUE self)
{
  void *ctx = libfst_reader_from_rbobj(self);
  VALUE blk;
  VALUE splat;
  VALUE kw;
  const ID kwkeys[2] = {id_start_time, id_end_time};
  VALUE kwvalues[2] = {Qundef, Qundef};
  uint64_t start_time, end_time;
  libfst_reader_value_change_callback_arg_t cbarg;


  rb_scan_args(argc, argv, "*:&", &splat, &kw, &blk);

  if (NIL_P(blk))
    rb_raise(rb_eRuntimeError, "read expects a block");

  if (!NIL_P(kw)) {
    rb_get_kwargs(kw, kwkeys, 0, 2, kwvalues);

    if (kwvalues[0] == Qundef || NIL_P(kwvalues[0]))
      start_time = 0;
    else if (rb_obj_is_kind_of(kwvalues[0], rb_cInteger))
      start_time = NUM2ULL(kwvalues[0]);
    else if (rb_obj_is_kind_of(kwvalues[0], rb_cFloat))
      start_time = (uint64_t)floor(NUM2DBL(kwvalues[0]) / NUM2DBL(libfst_reader_time_scale(self)));
    else
      rb_raise(rb_eTypeError, "expecting an Integer or a Float as start time, not a %s", rb_obj_classname(kwvalues[0]));

    if (kwvalues[1] == Qundef || NIL_P(kwvalues[1]))
      end_time = fstReaderGetEndTime(ctx) + 1;
    else if (rb_obj_is_kind_of(kwvalues[1], rb_cInteger))
      end_time = NUM2ULL(kwvalues[1]);
    else if (rb_obj_is_kind_of(kwvalues[1], rb_cFloat))
      end_time = (uint64_t)floor(NUM2DBL(kwvalues[1]) / NUM2DBL(libfst_reader_time_scale(self)));
    else
      rb_raise(rb_eTypeError, "expecting an Integer or a Float as end time, not a %s", rb_obj_classname(kwvalues[1]));

    if (end_time < start_time)
      rb_raise(rb_eRuntimeError, "start_time must be less than end_time (%lu, %lu)", start_time, end_time);

    fstReaderSetLimitTimeRange(ctx, start_time, end_time);
    cbarg.limit_time = 1;
    cbarg.start_time = start_time;
    cbarg.end_time = end_time;
  } else {
    fstReaderSetUnlimitedTimeRange(ctx);
    cbarg.limit_time = 0;
  }

  long splatlen = rb_array_len(splat);
  if (splatlen < 1) {
    fstReaderSetFacProcessMaskAll(ctx);
  } else {
    fstReaderClrFacProcessMaskAll(ctx);
    long i;
    fstHandle mh = fstReaderGetMaxHandle(ctx);
    for (i = 0; i < splatlen; i++) {
      VALUE t = rb_ary_entry(splat, i);
      fstHandle facidx;
      if (rb_obj_is_kind_of(t, rb_cInteger)) {
        facidx = NUM2ULONG(t);
        if (facidx < 1 || facidx > mh) rb_raise(rb_eRuntimeError, "bad signal handle");
        fstReaderSetFacProcessMask(ctx, facidx);
      } else if (rb_obj_is_kind_of(t, c_RTrace)) {
        facidx = NUM2ULONG(rb_ivar_get(t, id_at_handle));
        if (facidx < 1 || facidx > mh) rb_raise(rb_eRuntimeError, "bad signal handle");
        fstReaderSetFacProcessMask(ctx, facidx);
      } else if (rb_obj_is_kind_of(t, c_RVariable)) {
        facidx = NUM2ULONG(rb_ivar_get(rb_ivar_get(t, id_at_trace), id_at_handle));
        if (facidx < 1 || facidx > mh) rb_raise(rb_eRuntimeError, "bad signal handle");
        fstReaderSetFacProcessMask(ctx, facidx);
      } else if (rb_obj_is_kind_of(t, c_RScope)) {
        VALUE variables = rb_ivar_get(t, id_at_variables);
        long varlen = rb_array_len(variables);
        long j;
        for (j = 0; j < varlen; j++) {
          facidx = NUM2ULONG(rb_ivar_get(rb_ivar_get(rb_ary_entry(variables, j), id_at_trace), id_at_handle));
          if (facidx < 1 || facidx > mh) rb_raise(rb_eRuntimeError, "bad signal handle");
          fstReaderSetFacProcessMask(ctx, facidx);
        }
      } else {
        rb_raise(rb_eTypeError, "signals can be specified either by a handle (Integer), a %"PRIsVALUE", a %"PRIsVALUE" or a %"PRIsVALUE", not a %s",
            c_RTrace, c_RVariable, c_RScope, rb_obj_classname(t));
      }
    }
  }

  cbarg.reader = self;
  cbarg.proc = blk;
  int r = fstReaderIterBlocks2(ctx, libfst_reader_value_change_callback, libfst_reader_value_change_callback_varlen, &cbarg, NULL);
  RB_GC_GUARD(cbarg.reader);
  RB_GC_GUARD(cbarg.proc);
  return INT2NUM(r);
}

#reset_scopeself

Returns:

  • (self)


541
542
543
544
545
546
# File 'ext/libfst_rb.c', line 541

static VALUE libfst_reader_reset_scope(VALUE self)
{
  void *ctx = libfst_reader_from_rbobj(self);
  fstReaderResetScope(ctx);
  return self;
}

#scope_countInteger

Returns:

  • (Integer)


438
439
440
441
442
443
# File 'ext/libfst_rb.c', line 438

static VALUE libfst_reader_scope_count(VALUE self)
{
  void *ctx = libfst_reader_from_rbobj(self);
  uint64_t i = fstReaderGetScopeCount(ctx);
  return RB_ULL2NUM(i);
}

#start_timeInteger

Returns:

  • (Integer)


374
375
376
377
378
379
# File 'ext/libfst_rb.c', line 374

static VALUE libfst_reader_start_time(VALUE self)
{
  void *ctx = libfst_reader_from_rbobj(self);
  uint64_t i = fstReaderGetStartTime(ctx);
  return RB_ULL2NUM(i);
}

#time_scaleFloat

Returns:

  • (Float)


497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
# File 'ext/libfst_rb.c', line 497

static VALUE libfst_reader_time_scale(VALUE self)
{
  void *ctx = libfst_reader_from_rbobj(self);
  signed char s = fstReaderGetTimescale(ctx);
  double d = 1.0;
  switch (s) {
    case   2: d = 100.0;   break;
    case   1: d =  10.0;   break;
    case   0: d =   1.0;   break;
    case  -1: d = 100e-3;  break;
    case  -2: d =  10e-3;  break;
    case  -3: d =   1e-3;  break;
    case  -4: d = 100e-6;  break;
    case  -5: d =  10e-6;  break;
    case  -6: d =   1e-6;  break;
    case  -7: d = 100e-9;  break;
    case  -8: d =  10e-9;  break;
    case  -9: d =   1e-9;  break;
    case -10: d = 100e-12; break;
    case -11: d =  10e-12; break;
    case -12: d =   1e-12; break;
    case -13: d = 100e-15; break;
    case -14: d =  10e-15; break;
    case -15: d =   1e-15; break;
    default:
      d = pow(10.0, (double)s);
  }
  return DBL2NUM(d);
}

#time_scale_exponentInteger

Returns the time scale exponent.

Real time is integer_time * 10^time_scale_exponent.

Returns:

  • (Integer)


489
490
491
492
# File 'ext/libfst_rb.c', line 489

static VALUE libfst_reader_time_scale_exponent(VALUE self)
{
  return INT2NUM((int)fstReaderGetTimescale(libfst_reader_from_rbobj(self)));
}

#time_zeroInteger

Returns:

  • (Integer)


394
395
396
397
398
399
# File 'ext/libfst_rb.c', line 394

static VALUE libfst_reader_time_zero(VALUE self)
{
  void *ctx = libfst_reader_from_rbobj(self);
  uint64_t i = fstReaderGetTimezero(ctx);
  return RB_ULL2NUM(i);
}

#trace(name) ⇒ Trace?

Find a Trace by its name or path

Parameters:

  • name (String)

    name or path to look for

Returns:



225
226
227
228
229
230
# File 'lib/libfst/reader.rb', line 225

def trace(name)
  @traces.each do |t|
    return t if t.name == name or t.path == name
  end
  nil
end

#value_change_section_countInteger

Returns:

  • (Integer)


448
449
450
451
452
453
# File 'ext/libfst_rb.c', line 448

static VALUE libfst_reader_value_change_section_count(VALUE self)
{
  void *ctx = libfst_reader_from_rbobj(self);
  uint64_t i = fstReaderGetValueChangeSectionCount(ctx);
  return RB_ULL2NUM(i);
}

#var_countInteger

Returns the number of variables.

Returns:

  • (Integer)


364
365
366
367
368
369
# File 'ext/libfst_rb.c', line 364

static VALUE libfst_reader_var_count(VALUE self)
{
  void *ctx = libfst_reader_from_rbobj(self);
  uint64_t i = fstReaderGetVarCount(ctx);
  return RB_ULL2NUM(i);
}

#variable(name) ⇒ Variable?

Find a Variable by its name or path

Parameters:

  • name (String)

    name or path to look for

Returns:



235
236
237
238
239
240
# File 'lib/libfst/reader.rb', line 235

def variable(name)
  @variables.each do |v|
    return v if v.name == name or v.path == name
  end
  nil
end

#version_stringString

Version string produced by the writer of the FST file

Returns:

  • (String)


353
354
355
356
357
358
# File 'ext/libfst_rb.c', line 353

static VALUE libfst_reader_version_string(VALUE self)
{
  void *ctx = libfst_reader_from_rbobj(self);
  const char* str = fstReaderGetVersionString(ctx);
  return rb_utf8_str_new_cstr(str);
}