HDLRuby 2.2.17 → 2.3.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -157,6 +157,13 @@ extern Value mul_value(Value src0, Value src1, Value dst);
157
157
  * @return dst */
158
158
  extern Value div_value(Value src0, Value src1, Value dst);
159
159
 
160
+ /** Computes the modulo of two general values.
161
+ * @param src0 the first source value of the addition
162
+ * @param src1 the second source value of the addition
163
+ * @param dst the destination value
164
+ * @return dst */
165
+ extern Value mod_value(Value src0, Value src1, Value dst);
166
+
160
167
  /** Computes the not of a value.
161
168
  * @param src the source value of the not
162
169
  * @param dst the destination value
@@ -605,14 +612,18 @@ extern Value read_range(Value value, long long first, long long last,
605
612
  * @param src the source value
606
613
  * @param first the first index of the range
607
614
  * @param last the last index of the range
615
+ * @param base the type of the elements
608
616
  * @param dst the destination value
609
617
  * @return dst */
610
- extern Value write_range(Value src, long long first, long long last, Value dst);
618
+ extern Value write_range(Value src, long long first, long long last,
619
+ Type base, Value dst);
611
620
 
612
621
  /** Writes to a range within a value but without overwrite with Z.
613
622
  * @param src the source value
614
623
  * @param first the first index of the range
615
624
  * @param last the last index of the range
625
+ * @param base the type of the elements
616
626
  * @param dst the destination value
617
627
  * @return dst */
618
- extern Value write_range_no_z(Value src, long long first, long long last, Value dst);
628
+ extern Value write_range_no_z(Value src, long long first, long long last,
629
+ Type base, Value dst);
@@ -397,6 +397,9 @@ static Value set_undefined_bitstring(Value dst) {
397
397
 
398
398
  /* set the type and size of the destination. */
399
399
  dst->numeric = 0;
400
+ /* Ensures the buffer of dst has the write size (in cas it was a fromer
401
+ * numeric for example). */
402
+ resize_value(dst,width);
400
403
 
401
404
  /* Get access to the destination data. */
402
405
  char* dst_data = dst->data_str;
@@ -604,7 +607,7 @@ static Value mul_value_defined_bitstring(Value src0, Value src1, Value dst) {
604
607
  dst->type = src0->type;
605
608
  dst->numeric = 1;
606
609
 
607
- /* Perform the addition. */
610
+ /* Perform the multiplication. */
608
611
  dst->data_int = value2integer(src0) * value2integer(src1);
609
612
  return dst;
610
613
  }
@@ -620,12 +623,29 @@ static Value div_value_defined_bitstring(Value src0, Value src1, Value dst) {
620
623
  dst->type = src0->type;
621
624
  dst->numeric = 1;
622
625
 
623
- /* Perform the addition. */
626
+ /* Perform the division. */
624
627
  dst->data_int = value2integer(src0) / value2integer(src1);
625
628
  return dst;
626
629
  }
627
630
 
628
631
 
632
+ /** Computes the modulo of two defined bitstring values.
633
+ * @param src0 the first source value of the addition
634
+ * @param src1 the second source value of the addition
635
+ * @param dst the destination value
636
+ * @return dst */
637
+ static Value mod_value_defined_bitstring(Value src0, Value src1, Value dst) {
638
+ /* Sets state of the destination using the first source. */
639
+ dst->type = src0->type;
640
+ dst->numeric = 1;
641
+
642
+ /* Perform the modulo. */
643
+ // printf("modulo with src0=%lld src1=%lld, result=%lld\n",value2integer(src0),value2integer(src1),value2integer(src0) % value2integer(src1));
644
+ dst->data_int = value2integer(src0) % value2integer(src1);
645
+ return dst;
646
+ }
647
+
648
+
629
649
  /** Computes the lesser comparision of two defined bitstring values.
630
650
  * @param src0 the first source value of the addition
631
651
  * @param src1 the second source value of the addition
@@ -1334,10 +1354,11 @@ Value read_range_bitstring(Value src, long long first, long long last,
1334
1354
  * @param src the source value
1335
1355
  * @param first the first index of the range
1336
1356
  * @param last the last index of the range
1357
+ * @param base the type of the elements
1337
1358
  * @param dst the destination value
1338
1359
  * @return dst */
1339
1360
  Value write_range_bitstring(Value src, long long first, long long last,
1340
- Value dst) {
1361
+ Type base, Value dst) {
1341
1362
  unsigned long long i;
1342
1363
  /* Ensure first is the smaller. */
1343
1364
  if (first > last) {
@@ -1350,7 +1371,8 @@ Value write_range_bitstring(Value src, long long first, long long last,
1350
1371
  unsigned long long src_width = type_width(src->type);
1351
1372
  unsigned long long dst_width = type_width(dst->type);
1352
1373
  /* scale the range according to the base type. */
1353
- unsigned long long bw = dst->type->base;
1374
+ // unsigned long long bw = dst->type->base;
1375
+ unsigned long long bw = type_width(base);
1354
1376
  first *= bw;
1355
1377
  last *= bw;
1356
1378
  last += bw-1;
@@ -1371,10 +1393,11 @@ Value write_range_bitstring(Value src, long long first, long long last,
1371
1393
  * @param src the source value
1372
1394
  * @param first the first index of the range
1373
1395
  * @param last the last index of the range
1396
+ * @param base the type of the elements
1374
1397
  * @param dst the destination value
1375
1398
  * @return dst */
1376
1399
  Value write_range_bitstring_no_z(Value src, long long first, long long last,
1377
- Value dst) {
1400
+ Type base, Value dst) {
1378
1401
  unsigned long long i;
1379
1402
  /* Ensure first is the smaller. */
1380
1403
  if (first > last) {
@@ -1386,7 +1409,8 @@ Value write_range_bitstring_no_z(Value src, long long first, long long last,
1386
1409
  unsigned long long src_width = type_width(src->type);
1387
1410
  unsigned long long dst_width = type_width(dst->type);
1388
1411
  /* scale the range according to the base type. */
1389
- unsigned long long bw = dst->type->base;
1412
+ // unsigned long long bw = dst->type->base;
1413
+ unsigned long long bw = type_width(base);
1390
1414
  first *= bw;
1391
1415
  last *= bw;
1392
1416
  /* Access the source and destination bitstring data. */
@@ -1415,7 +1439,10 @@ fix_numeric_type(Type type, unsigned long long val) {
1415
1439
  /* Get the width of the type. */
1416
1440
  int width = type_width(type);
1417
1441
  /* Compute the base mask. */
1418
- unsigned long long mask = ((unsigned long long)(-1)) << width;
1442
+ // unsigned long long mask = ((unsigned long long)(-1)) << width;
1443
+ /* NOTE: (ull)-1 << 64 becomes (ull)-1 on Intel processors, this is
1444
+ * totally not what I expected (I expected 0). */
1445
+ unsigned long long mask = width == 64 ? 0 : ((unsigned long long)(-1)) << width;
1419
1446
  // printf("width=%i val=%llu mask=%llx\n",width,val,mask);
1420
1447
 
1421
1448
  /* Is the type signed? */
@@ -1516,6 +1543,23 @@ static Value div_value_numeric(Value src0, Value src1, Value dst) {
1516
1543
  }
1517
1544
 
1518
1545
 
1546
+ /** Computes the modulo of two numeric values.
1547
+ * @param src0 the first source value of the addition
1548
+ * @param src1 the second source value of the addition
1549
+ * @param dst the destination value
1550
+ * @return dst */
1551
+ static Value mod_value_numeric(Value src0, Value src1, Value dst) {
1552
+ /* Sets state of the destination using the first source. */
1553
+ dst->type = src0->type;
1554
+ dst->numeric = 1;
1555
+
1556
+ /* Perform the division. */
1557
+ // printf("modulo numeric with src0=%lld src1=%lld, result=%lld\n",src0->data_int, src1->data_int,src0->data_int % src1->data_int);
1558
+ dst->data_int = fix_numeric_type(dst->type, src0->data_int % src1->data_int);
1559
+ return dst;
1560
+ }
1561
+
1562
+
1519
1563
  /** Computes the NOT of a numeric value.
1520
1564
  * @param src the source value of the not
1521
1565
  * @param dst the destination value
@@ -1690,7 +1734,7 @@ static Value concat_value_numeric_array(int num, int dir,
1690
1734
  unsigned int i,pos;
1691
1735
  /* Compute the bit width of the destination. */
1692
1736
  unsigned int width = 0;
1693
- // printf("concat_value_numeric with dir=%d\n",dir);
1737
+ // printf("concat_value_numeric with dir=%d and width=%llu\n",dir,type_width(args[0]->type));
1694
1738
  for(i=0; i<num; ++i) width += type_width(args[i]->type);
1695
1739
 
1696
1740
  /* Sets state of the destination using the bit width. */
@@ -1714,6 +1758,7 @@ static Value concat_value_numeric_array(int num, int dir,
1714
1758
  pos += arg_width;
1715
1759
  }
1716
1760
  /* Return the destination. */
1761
+ // printf("Result is dst=%llx\n",dst->data_int);
1717
1762
  return dst;
1718
1763
  }
1719
1764
 
@@ -1724,6 +1769,7 @@ static Value concat_value_numeric_array(int num, int dir,
1724
1769
  * @param dst the destination value
1725
1770
  * @return dst */
1726
1771
  static Value cast_value_numeric(Value src, Type type, Value dst) {
1772
+ // printf("cast_value_numeric with src=%llx",src->data_int);
1727
1773
  /* Copy the source to the destination. */
1728
1774
  dst->data_int = src->data_int;
1729
1775
  /* Update the destination type to the cast. */
@@ -1783,6 +1829,7 @@ static int same_content_value_range_numeric(Value value0,
1783
1829
  * @return dst */
1784
1830
  Value read_range_numeric(Value value, long long first, long long last,
1785
1831
  Type base, Value dst) {
1832
+ /* printf("read_range_numeric with value=%llx and first=%llu and last=%llu\n",value->data_int,first,last); */
1786
1833
  /* Ensure first is the smaller. */
1787
1834
  if (first > last) {
1788
1835
  long long tmp = last;
@@ -1795,15 +1842,18 @@ Value read_range_numeric(Value value, long long first, long long last,
1795
1842
  unsigned long long bw = type_width(base);
1796
1843
  /* Scale the range according to the base type. */
1797
1844
  first *= bw;
1845
+ last *= bw;
1798
1846
  length *= bw;
1799
- // printf("first=%lld last=%lld bw=%llu length=%lld\n",first,last,bw,length);
1847
+ /* printf("first=%lld last=%lld bw=%llu length=%lld\n",first,last,bw,length); */
1800
1848
 
1801
1849
  /* Set the type and size of the destination from the type of the source.*/
1802
1850
  dst->type = make_type_vector(get_type_bit(),length);
1803
1851
  dst->numeric = 1;
1804
1852
 
1805
1853
  /* Compute the read mask. */
1806
- unsigned long long mask = ((-1LL) << first) & (~((-1LL) << (last+1)));
1854
+ // unsigned long long mask = ((-1LL) << first) & (~((-1LL) << (last+1)));
1855
+ /* NOTE: once again, << 64 does not work like expected. */
1856
+ unsigned long long mask = mask+bw < 64 ? (~((-1LL) << (last+bw))) : -1LL;
1807
1857
  /* Performs the read. */
1808
1858
  unsigned long long data = (value->data_int & mask) >> first;
1809
1859
  /* Write it to the destination. */
@@ -1818,10 +1868,11 @@ Value read_range_numeric(Value value, long long first, long long last,
1818
1868
  * @param src the source value
1819
1869
  * @param first the first index of the range
1820
1870
  * @param last the last index of the range
1871
+ * @param base the type of the elements
1821
1872
  * @param dst the destination value
1822
1873
  * @return dst */
1823
1874
  Value write_range_numeric(Value src, long long first, long long last,
1824
- Value dst) {
1875
+ Type base, Value dst) {
1825
1876
  // printf("write_range_numeric\n");
1826
1877
  /* Ensure first is the smaller. */
1827
1878
  if (first > last) {
@@ -1833,7 +1884,8 @@ Value write_range_numeric(Value src, long long first, long long last,
1833
1884
  unsigned long long src_width = type_width(src->type);
1834
1885
  unsigned long long dst_width = type_width(dst->type);
1835
1886
  /* scale the range according to the base type of the destination. */
1836
- unsigned long long bw = dst->type->base;
1887
+ // unsigned long long bw = dst->type->base;
1888
+ unsigned long long bw = type_width(base);
1837
1889
  // printf("src_width=%llu dst_wdith=%llu bw=%llu\n",src_width,dst_width,bw);
1838
1890
  first *= bw;
1839
1891
  last *= bw;
@@ -1999,6 +2051,33 @@ Value div_value(Value src0, Value src1, Value dst) {
1999
2051
  }
2000
2052
 
2001
2053
 
2054
+ /** Computes the modulo of two general values.
2055
+ * @param src0 the first source value of the addition
2056
+ * @param src1 the second source value of the addition
2057
+ * @param dst the destination value
2058
+ * @return dst */
2059
+ Value mod_value(Value src0, Value src1, Value dst) {
2060
+ /* Might allocate a new value so save the current pool state. */
2061
+ unsigned int pos = get_value_pos();
2062
+ /* Do a numeric computation if possible, otherwise fallback to bitstring
2063
+ * computation. */
2064
+ if (src0->numeric && src1->numeric) {
2065
+ /* Both sources are numeric. */
2066
+ return mod_value_numeric(src0,src1,dst);
2067
+ } else if (is_defined_value(src0) && is_defined_value(src1)) {
2068
+ /* Both sources can be converted to numeric values. */
2069
+ return mod_value_defined_bitstring(src0,src1,dst);
2070
+ } else {
2071
+ /* Cannot compute (for now), simply undefines the destination. */
2072
+ /* First ensure dst has the right shape. */
2073
+ copy_value(src0,dst);
2074
+ /* Then make it undefined. */
2075
+ set_undefined_bitstring(dst);
2076
+ }
2077
+ return dst;
2078
+ }
2079
+
2080
+
2002
2081
  /** Computes the NOT of a general value.
2003
2082
  * @param src the source value of the not
2004
2083
  * @param dst the destination value
@@ -2618,14 +2697,17 @@ Value read_range(Value value, long long first, long long last, Type base,
2618
2697
  * @param src the source value
2619
2698
  * @param first the first index of the range
2620
2699
  * @param last the last index of the range
2700
+ * @param base the type of the elements
2621
2701
  * @param dst the destination value
2622
2702
  * @return dst */
2623
- Value write_range(Value src, long long first, long long last, Value dst) {
2703
+ Value write_range(Value src, long long first, long long last, Type base,
2704
+ Value dst) {
2624
2705
  // printf("write_range\n");
2625
2706
  /* Is the value numeric? */
2626
2707
  if ((src->numeric) && (dst->numeric)) {
2627
2708
  /* Yes, do a numeric range read. */
2628
- return write_range_numeric(src,first,last,dst);
2709
+ // return write_range_numeric(src,first,last,dst);
2710
+ return write_range_numeric(src,first,last,base,dst);
2629
2711
  } else {
2630
2712
  /* No, do a bitstring range read. */
2631
2713
  if (dst->numeric) {
@@ -2635,7 +2717,8 @@ Value write_range(Value src, long long first, long long last, Value dst) {
2635
2717
  /* Need to convert the source to a bitstring. */
2636
2718
  src = set_bitstring_value(src,get_value());
2637
2719
  }
2638
- return write_range_bitstring(src,first,last,dst);
2720
+ // return write_range_bitstring(src,first,last,dst);
2721
+ return write_range_bitstring(src,first,last,base,dst);
2639
2722
  }
2640
2723
  }
2641
2724
 
@@ -2644,14 +2727,16 @@ Value write_range(Value src, long long first, long long last, Value dst) {
2644
2727
  * @param src the source value
2645
2728
  * @param first the first index of the range
2646
2729
  * @param last the last index of the range
2730
+ * @param base the type of the elements
2647
2731
  * @param dst the destination value
2648
2732
  * @return dst */
2649
- Value write_range_no_z(Value src, long long first, long long last, Value dst) {
2733
+ Value write_range_no_z(Value src, long long first, long long last, Type base,
2734
+ Value dst) {
2650
2735
  // printf("write_range_no_z\n");
2651
2736
  /* Is the value numeric? */
2652
2737
  if ((src->numeric) && (dst->numeric)) {
2653
2738
  /* Yes, do a numeric range read. */
2654
- return write_range_numeric(src,first,last,dst);
2739
+ return write_range_numeric(src,first,last,base,dst);
2655
2740
  } else {
2656
2741
  /* No, do a bitstring range read. */
2657
2742
  if (dst->numeric) {
@@ -2661,7 +2746,8 @@ Value write_range_no_z(Value src, long long first, long long last, Value dst) {
2661
2746
  /* Need to convert the source to a bitstring. */
2662
2747
  src = set_bitstring_value(src,get_value());
2663
2748
  }
2664
- return write_range_bitstring_no_z(src,first,last,dst);
2749
+ // return write_range_bitstring_no_z(src,first,last,dst);
2750
+ return write_range_bitstring_no_z(src,first,last,base,dst);
2665
2751
  }
2666
2752
  }
2667
2753
 
@@ -365,6 +365,7 @@ void* behavior_run(void* arg) {
365
365
  * @note create a thread per timed behavior. */
366
366
  void hruby_sim_start_timed_behaviors() {
367
367
  int i;
368
+ pthread_mutex_lock(&hruby_sim_mutex);
368
369
  /* Sets the end flags to 0. */
369
370
  sim_end_flag = 0;
370
371
  /* Create and start the threads. */
@@ -375,6 +376,7 @@ void hruby_sim_start_timed_behaviors() {
375
376
  pthread_create(&timed_behaviors[i]->thread,NULL,
376
377
  &behavior_run,timed_behaviors[i]);
377
378
  }
379
+ pthread_mutex_unlock(&hruby_sim_mutex);
378
380
  }
379
381
 
380
382
  /** Ends waiting all the threads properly terminates. */
@@ -497,12 +499,18 @@ void transmit_to_signal_range(Value value, RefRangeS ref) {
497
499
  SignalI signal = ref.signal;
498
500
  unsigned long long first = ref.first;
499
501
  unsigned long long last = ref.last;
502
+ /* The base type is stored here to avoid allocating a new type each time.
503
+ * It have an arbitrary base size a single element. */
504
+ static TypeS baseT = { 1, 1 };
505
+ baseT.base = signal->f_value->type->base;
500
506
  // printf("Tansmit to signal range: %s(%p) [%lld:%lld]\n",signal->name,signal,first,last);
501
507
  /* Can transmit, copy the content. */
502
508
  if (signal->fading)
503
- signal->f_value = write_range(value,first,last,signal->f_value);
509
+ signal->f_value = write_range(value,first,last,&baseT,
510
+ signal->f_value);
504
511
  else
505
- signal->f_value = write_range_no_z(value,first,last,signal->f_value);
512
+ signal->f_value = write_range_no_z(value,first,last,&baseT,
513
+ signal->f_value);
506
514
  /* And touch the signal. */
507
515
  touch_signal(signal);
508
516
  }
@@ -551,9 +559,9 @@ void transmit_to_signal_range_seq(Value value, RefRangeS ref) {
551
559
  // printf("Tansmit to signal range: %s(%p)\n",signal->name,signal);
552
560
  /* Can transmit, copy the content. */
553
561
  if (signal->fading)
554
- write_range(value,first,last,signal->f_value);
562
+ write_range(value,first,last,signal->f_value->type,signal->f_value);
555
563
  else
556
- write_range_no_z(value,first,last,signal->f_value);
564
+ write_range_no_z(value,first,last,signal->f_value->type,signal->f_value);
557
565
  /* And touch the signal. */
558
566
  touch_signal_seq(signal);
559
567
  }
@@ -81,20 +81,31 @@ module HDLRuby::High::Std
81
81
  end
82
82
 
83
83
 
84
- ##
85
- # Module for wrapping channel ports.
86
- module ChannelPortWrapping
84
+ # ##
85
+ # # Module for wrapping channel ports.
86
+ # module ChannelPortWrapping
87
+ # # Wrap with +args+ arguments.
88
+ # def wrap(*args)
89
+ # return ChannelPortB.new(self,*args)
90
+ # end
91
+ # end
92
+
93
+ ## Describes a channel port.
94
+ class ChannelPort
87
95
  # Wrap with +args+ arguments.
88
96
  def wrap(*args)
89
97
  return ChannelPortB.new(self,*args)
90
98
  end
99
+
100
+ # The scope the port has been declared in.
101
+ attr_reader :scope
91
102
  end
92
103
 
93
104
 
94
105
  ##
95
106
  # Describes a read port to a channel.
96
- class ChannelPortR
97
- include ChannelPortWrapping
107
+ class ChannelPortR < ChannelPort
108
+ # include ChannelPortWrapping
98
109
 
99
110
  # Creates a new channel reader running in +namespace+ and
100
111
  # reading using +reader_proc+ and reseting using +reseter_proc+.
@@ -105,6 +116,7 @@ module HDLRuby::High::Std
105
116
  @namespace = namespace
106
117
  @reader_proc = reader_proc.to_proc
107
118
  @rester_proc = reseter_proc ? reseter_proc.to_proc : proc {}
119
+ @scope = HDLRuby::High.cur_scope
108
120
  end
109
121
 
110
122
  ## Performs a read on the channel using +args+ and +ruby_block+
@@ -137,8 +149,8 @@ module HDLRuby::High::Std
137
149
 
138
150
  ##
139
151
  # Describes a writer port to a channel.
140
- class ChannelPortW
141
- include ChannelPortWrapping
152
+ class ChannelPortW < ChannelPort
153
+ # include ChannelPortWrapping
142
154
 
143
155
  # Creates a new channel writer running in +namespace+ and
144
156
  # writing using +writer_proc+ and reseting using +reseter_proc+.
@@ -149,6 +161,7 @@ module HDLRuby::High::Std
149
161
  @namespace = namespace
150
162
  @writer_proc = writer_proc.to_proc
151
163
  @reseter_proc = reseter_proc ? reseter_proc.to_proc : proc {}
164
+ @scope = HDLRuby::High.cur_scope
152
165
  end
153
166
 
154
167
  ## Performs a write on the channel using +args+ and +ruby_block+
@@ -181,8 +194,8 @@ module HDLRuby::High::Std
181
194
 
182
195
  ##
183
196
  # Describes an access port to a channel.
184
- class ChannelPortA
185
- include ChannelPortWrapping
197
+ class ChannelPortA < ChannelPort
198
+ # include ChannelPortWrapping
186
199
 
187
200
  # Creates a new channel accesser running in +namespace+
188
201
  # and reading using +reader_proc+, writing using +writer_proc+,
@@ -198,6 +211,7 @@ module HDLRuby::High::Std
198
211
  @reader_proc = reader_proc ? reader_proc.to_proc : proc { }
199
212
  @writer_proc = writer_proc ? writer_proc.to_proc : proc { }
200
213
  @reseter_proc = reseter_proc ? reseter_proc.to_proc : proc {}
214
+ @scope = HDLRuby::High.cur_scope
201
215
  end
202
216
 
203
217
  ## Performs a read on the channel using +args+ and +ruby_block+
@@ -243,8 +257,8 @@ module HDLRuby::High::Std
243
257
 
244
258
  ##
245
259
  # Describes port wrapper (Box) for fixing arugments.
246
- class ChannelPortB
247
- include ChannelPortWrapping
260
+ class ChannelPortB < ChannelPort
261
+ # include ChannelPortWrapping
248
262
 
249
263
  # Creates a new channel box over channel port +port+ fixing +args+
250
264
  # as arguments.
@@ -273,6 +287,8 @@ module HDLRuby::High::Std
273
287
  @args_write = args.clone
274
288
  @args_access = args.clone
275
289
  end
290
+
291
+ @scope = @port.scope
276
292
  end
277
293
 
278
294
  ## Performs a read on the channel using +args+ and +ruby_block+
@@ -324,6 +340,12 @@ module HDLRuby::High::Std
324
340
  # building a channel.
325
341
  attr_reader :namespace
326
342
 
343
+ # The read port if any.
344
+ attr_reader :read_port
345
+
346
+ # The write port if any.
347
+ attr_reader :write_port
348
+
327
349
  ## Creates a new channel instance with +name+ built from +ruby_block+.
328
350
  def initialize(name,&ruby_block)
329
351
  # Check and set the name of the channel.
@@ -338,6 +360,10 @@ module HDLRuby::High::Std
338
360
  # Keep access to self.
339
361
  obj = self
340
362
 
363
+ # At first there no read nor write port.
364
+ @read_port = nil
365
+ @write_port = nil
366
+
341
367
  # The reader input ports by name.
342
368
  @reader_inputs = {}
343
369
  # The reader output ports by name.
@@ -359,11 +385,6 @@ module HDLRuby::High::Std
359
385
  # The accesser inout ports by name.
360
386
  @accesser_inouts = {}
361
387
 
362
- # # The default reset procedures (reseters), by default do nothing.
363
- # @input_reseter_proc = proc {}
364
- # @output_reseter_proc = proc {}
365
- # @inout_reseter_proc = proc {}
366
-
367
388
  # The branch channels
368
389
  @branches = {}
369
390
 
@@ -419,6 +440,11 @@ module HDLRuby::High::Std
419
440
  HDLRuby::High.space_reg(@name) { obj }
420
441
  end
421
442
 
443
+ # Get the parent system.
444
+ def parent_system
445
+ return self.scope.parent_system
446
+ end
447
+
422
448
  # The methods for defining the channel
423
449
 
424
450
  # For the channel itself
@@ -598,15 +624,30 @@ module HDLRuby::High::Std
598
624
  @writer_inouts.values
599
625
  end
600
626
 
627
+ ## Tells if the channel support inout port.
628
+ def inout?
629
+ return @accesser_inputs.any? || @accesser_outputs.any? ||
630
+ @accesser_inouts.any?
631
+ end
632
+
601
633
  # Defines a branch in the channel named +name+ built executing
602
634
  # +ruby_block+.
603
- def brancher(name,&ruby_block)
635
+ # Alternatively, a ready channel instance can be passed as argument
636
+ # as +channelI+.
637
+ def brancher(name,channelI = nil,&ruby_block)
604
638
  # Ensure name is a symbol.
605
639
  name = name.to_s unless name.respond_to?(:to_sym)
606
640
  name = name.to_sym
607
- # Create the branch.
608
- channelI = HDLRuby::High.channel_instance(name, &ruby_block)
641
+ # Is there a ready channel instance.
642
+ if channelI then
643
+ # Yes, use it directly.
644
+ @branches[name] = channelI
645
+ return self
646
+ end
647
+ # Now, create the branch.
648
+ channelI = HDLRuby::High::Std.channel_instance(name, &ruby_block)
609
649
  @branches[name] = channelI
650
+ return self
610
651
  end
611
652
 
612
653
 
@@ -619,60 +660,90 @@ module HDLRuby::High::Std
619
660
  name = name.to_s unless name.respond_to?(:to_sym)
620
661
  name = name.to_sym
621
662
  # Get the branch.
663
+ channelI = @branches[name]
622
664
  return @branches[name]
623
665
  end
624
666
 
625
667
 
626
668
  # Reader, writer and accesser side.
627
669
 
628
- ## Declares the ports for the reader and assigned them to +name+.
629
- def input(name)
670
+ ## Declares the reader port as and assigned them to +name+.
671
+ def input(name = nil)
630
672
  # Ensure name is a symbol.
673
+ name = HDLRuby.uniq_name unless name
631
674
  name = name.to_sym
675
+ # Ensure the port is not already existing.
676
+ if @read_port then
677
+ raise "Read port already declared for channel instance: " +
678
+ self.name
679
+ end
680
+
632
681
  # Access the ports
633
- loc_inputs = @reader_inputs
634
- loc_outputs = @reader_outputs
635
- loc_inouts = @reader_inouts
682
+ # loc_inputs = @reader_inputs
683
+ # loc_outputs = @reader_outputs
684
+ # loc_inouts = @reader_inouts
685
+ loc_inputs = @reader_inputs.merge(@accesser_inputs)
686
+ loc_outputs = @reader_outputs.merge(@accesser_outputs)
687
+ loc_inouts = @reader_inouts.merge(@accesser_inouts)
688
+ locs = loc_inputs.merge(loc_outputs).merge(loc_inouts)
636
689
  # The generated port with corresponding channel port pairs.
637
690
  port_pairs = []
638
- # Add them to the current system.
639
- HDLRuby::High.cur_system.open do
640
- # The inputs
641
- loc_inputs.each do |name,sig|
642
- # puts "name=#{name} sig.name=#{sig.name}"
643
- port_pairs << [sig, sig.type.input(name)]
691
+ if HDLRuby::High.cur_system == self.parent_system then
692
+ # Port in same system as the channel case.
693
+ # Add them to the current system.
694
+ HDLRuby::High.cur_system.open do
695
+ locs.each do |name,sig|
696
+ port_pairs << [sig, sig.type.inner(name)]
697
+ end
644
698
  end
645
- # The outputs
646
- loc_outputs.each do |name,sig|
647
- port_pairs << [sig, sig.type.output(name)]
699
+ obj = self
700
+ # Make the inner connection
701
+ port_pairs.each do |sig, port|
702
+ sig.parent.open do
703
+ port.to_ref <= sig
704
+ end
648
705
  end
649
- # The inouts
650
- loc_inouts.each do |name,sig|
651
- port_pairs << [sig, sig.type.inout(name)]
706
+ else
707
+ # Port in different system as the channel case.
708
+ # Add them to the current system.
709
+ HDLRuby::High.cur_system.open do
710
+ # The inputs
711
+ loc_inputs.each do |name,sig|
712
+ # puts "name=#{name} sig.name=#{sig.name}"
713
+ port_pairs << [sig, sig.type.input(name)]
714
+ end
715
+ # The outputs
716
+ loc_outputs.each do |name,sig|
717
+ port_pairs << [sig, sig.type.output(name)]
718
+ end
719
+ # The inouts
720
+ loc_inouts.each do |name,sig|
721
+ port_pairs << [sig, sig.type.inout(name)]
722
+ end
652
723
  end
653
- end
654
- obj = self
655
- # Make the connection of the instance.
656
- HDLRuby::High.cur_system.on_instance do |inst|
657
- obj.scope.open do
658
- port_pairs.each do |sig, port|
659
- RefObject.new(inst,port.to_ref) <= sig
724
+ obj = self
725
+ # Make the connection of the instance.
726
+ HDLRuby::High.cur_system.on_instance do |inst|
727
+ obj.scope.open do
728
+ port_pairs.each do |sig, port|
729
+ RefObject.new(inst,port.to_ref) <= sig
730
+ end
660
731
  end
661
732
  end
662
733
  end
663
734
 
664
735
  # Fill the reader namespace with the access to the reader signals.
665
- @reader_inputs.each do |name,sig|
736
+ loc_inputs.each do |name,sig|
666
737
  @reader_namespace.add_method(sig.name) do
667
738
  HDLRuby::High.top_user.send(name)
668
739
  end
669
740
  end
670
- @reader_outputs.each do |name,sig|
741
+ loc_outputs.each do |name,sig|
671
742
  @reader_namespace.add_method(sig.name) do
672
743
  HDLRuby::High.top_user.send(name)
673
744
  end
674
745
  end
675
- @reader_inouts.each do |name,sig|
746
+ loc_inouts.each do |name,sig|
676
747
  @reader_namespace.add_method(sig.name) do
677
748
  HDLRuby::High.top_user.send(name)
678
749
  end
@@ -682,56 +753,88 @@ module HDLRuby::High::Std
682
753
  # NOTE: for now, simply associate the channel to name.
683
754
  chp = ChannelPortR.new(@reader_namespace,@reader_proc,@input_reseter_proc)
684
755
  HDLRuby::High.space_reg(name) { chp }
756
+ # Save the port in the channe to avoid conflicting declaration.
757
+ @read_port = chp
685
758
  return chp
686
759
  end
687
760
 
688
761
  ## Declares the ports for the writer and assigned them to +name+.
689
- def output(name)
762
+ def output(name = nil)
690
763
  # Ensure name is a symbol.
764
+ name = HDLRuby.uniq_name unless name
691
765
  name = name.to_sym
766
+ # Ensure the port is not already existing.
767
+ if @write_port then
768
+ raise "Write port already declared for channel instance: " +
769
+ self.name
770
+ end
692
771
  # Access the ports
693
- loc_inputs = @writer_inputs
694
- loc_outputs = @writer_outputs
695
- loc_inouts = @writer_inouts
772
+ # loc_inputs = @writer_inputs
773
+ # loc_outputs = @writer_outputs
774
+ # loc_inouts = @writer_inouts
775
+ loc_inputs = @writer_inputs.merge(@accesser_inputs)
776
+ loc_outputs = @writer_outputs.merge(@accesser_outputs)
777
+ loc_inouts = @writer_inouts.merge(@accesser_inouts)
778
+ locs = loc_inputs.merge(loc_outputs).merge(loc_inouts)
696
779
  # The generated port with corresponding channel port pairs.
697
780
  port_pairs = []
698
- # Add them to the current system.
699
- HDLRuby::High.cur_system.open do
700
- # The inputs
701
- loc_inputs.each do |name,sig|
702
- port_pairs << [sig, sig.type.input(name)]
781
+ # puts "cur_system=#{HDLRuby::High.cur_system} self.parent_system=#{self.parent_system}"
782
+ if HDLRuby::High.cur_system == self.parent_system then
783
+ # puts "Inner found!"
784
+ # Port in same system as the channel case.
785
+ # Add them to the current system.
786
+ HDLRuby::High.cur_system.open do
787
+ locs.each do |name,sig|
788
+ port_pairs << [sig, sig.type.inner(name)]
789
+ end
703
790
  end
704
- # The outputs
705
- loc_outputs.each do |name,sig|
706
- port_pairs << [sig, sig.type.output(name)]
791
+ obj = self
792
+ # Make the inner connection
793
+ port_pairs.each do |sig, port|
794
+ sig.parent.open do
795
+ port.to_ref <= sig
796
+ end
707
797
  end
708
- # The inouts
709
- loc_inouts.each do |name,sig|
710
- port_pairs << [sig, sig.type.inout(name)]
798
+ else
799
+ # Portds in different system as the channel's case.
800
+ # Add them to the current system.
801
+ HDLRuby::High.cur_system.open do
802
+ # The inputs
803
+ loc_inputs.each do |name,sig|
804
+ port_pairs << [sig, sig.type.input(name)]
805
+ end
806
+ # The outputs
807
+ loc_outputs.each do |name,sig|
808
+ port_pairs << [sig, sig.type.output(name)]
809
+ end
810
+ # The inouts
811
+ loc_inouts.each do |name,sig|
812
+ port_pairs << [sig, sig.type.inout(name)]
813
+ end
711
814
  end
712
- end
713
- obj = self
714
- # Make the connection of the instance.
715
- HDLRuby::High.cur_system.on_instance do |inst|
716
- obj.scope.open do
717
- port_pairs.each do |sig, port|
718
- RefObject.new(inst,port.to_ref) <= sig
815
+ obj = self
816
+ # Make the connection of the instance.
817
+ HDLRuby::High.cur_system.on_instance do |inst|
818
+ obj.scope.open do
819
+ port_pairs.each do |sig, port|
820
+ RefObject.new(inst,port.to_ref) <= sig
821
+ end
719
822
  end
720
823
  end
721
824
  end
722
825
 
723
826
  # Fill the writer namespace with the access to the writer signals.
724
- @writer_inputs.each do |name,sig|
827
+ loc_inputs.each do |name,sig|
725
828
  @writer_namespace.add_method(sig.name) do
726
829
  HDLRuby::High.top_user.send(name)
727
830
  end
728
831
  end
729
- @writer_outputs.each do |name,sig|
832
+ loc_outputs.each do |name,sig|
730
833
  @writer_namespace.add_method(sig.name) do
731
834
  HDLRuby::High.top_user.send(name)
732
835
  end
733
836
  end
734
- @writer_inouts.each do |name,sig|
837
+ loc_inouts.each do |name,sig|
735
838
  @writer_namespace.add_method(sig.name) do
736
839
  HDLRuby::High.top_user.send(name)
737
840
  end
@@ -741,73 +844,28 @@ module HDLRuby::High::Std
741
844
  # NOTE: for now, simply associate the channel to name.
742
845
  chp = ChannelPortW.new(@writer_namespace,@writer_proc,@output_reseter_proc)
743
846
  HDLRuby::High.space_reg(name) { chp }
847
+ # Save the port in the channe to avoid conflicting declaration.
848
+ @write_port = chp
744
849
  return chp
745
850
  end
746
851
 
747
- ## Declares the ports for the accesser and assigned them to +name+.
748
- def inout(name)
852
+
853
+ ## Declares the accesser port and assigned them to +name+.
854
+ def inout(name = nil)
749
855
  # Ensure name is a symbol.
856
+ name = HDLRuby.uniq_name unless name
750
857
  name = name.to_sym
751
- # Access the ports
752
- loc_inputs = @accesser_inputs
753
- loc_outputs = @accesser_outputs
754
- loc_inouts = @accesser_inouts
755
- # The generated port with corresponding channel port pairs.
756
- port_pairs = []
757
- # Add them to the current system.
758
- HDLRuby::High.cur_system.open do
759
- # The inputs
760
- loc_inputs.each do |name,sig|
761
- port_pairs << [sig, sig.type.input(name)]
762
- end
763
- # The outputs
764
- loc_outputs.each do |name,sig|
765
- port_pairs << [sig, sig.type.output(name)]
766
- end
767
- # The inouts
768
- loc_inouts.each do |name,sig|
769
- port_pairs << [sig, sig.type.inout(name)]
770
- end
771
- end
772
- obj = self
773
- # Make the connection of the instance.
774
- HDLRuby::High.cur_system.on_instance do |inst|
775
- obj.scope.open do
776
- port_pairs.each do |sig, port|
777
- RefObject.new(inst,port.to_ref) <= sig
778
- end
779
- end
858
+ # Ensure the port is not already existing.
859
+ if @read_port then
860
+ raise "Read port already declared for channel instance: " +
861
+ self.name
780
862
  end
781
863
 
782
- # Set ups the accesser's namespace
783
- @accesser_inputs.each do |name,sig|
784
- @accesser_namespace.add_method(sig.name) do
785
- HDLRuby::High.top_user.send(name)
786
- end
787
- end
788
- @accesser_outputs.each do |name,sig|
789
- @accesser_namespace.add_method(sig.name) do
790
- HDLRuby::High.top_user.send(name)
791
- end
792
- end
793
- @accesser_inouts.each do |name,sig|
794
- @accesser_namespace.add_method(sig.name) do
795
- HDLRuby::High.top_user.send(name)
796
- end
864
+ if @write_port then
865
+ raise "Write port already declared for channel instance: " +
866
+ self.name
797
867
  end
798
868
 
799
- # Give access to the ports through name.
800
- # NOTE: for now, simply associate the channel to name.
801
- chp = ChannelPortA.new(@accesser_namespace,@reader_proc,@writer_proc,@inout_reseter_proc)
802
- HDLRuby::High.space_reg(name) { chp }
803
- return chp
804
- end
805
-
806
- ## Declares the ports for accessing the channel as an inner component
807
- # and assigned them to +name+.
808
- def inner(name)
809
- # Ensure name is a symbol.
810
- name = name.to_sym
811
869
  # Access the ports
812
870
  loc_inputs = @accesser_inputs.merge(@reader_inputs).
813
871
  merge(@writer_inputs)
@@ -818,21 +876,51 @@ module HDLRuby::High::Std
818
876
  locs = loc_inputs.merge(loc_outputs).merge(loc_inouts)
819
877
  # The generated port with corresponding channel port pairs.
820
878
  port_pairs = []
821
- # Add them to the current system.
822
- HDLRuby::High.cur_system.open do
823
- locs.each do |name,sig|
824
- port_pairs << [sig, sig.type.inner(name)]
879
+ if HDLRuby::High.cur_system == self.parent_system then
880
+ # Port in same system as the channel case.
881
+ # Add them to the current system.
882
+ HDLRuby::High.cur_system.open do
883
+ locs.each do |name,sig|
884
+ port_pairs << [sig, sig.type.inner(name)]
885
+ end
825
886
  end
826
- end
827
- obj = self
828
- # Make the inner connection
829
- port_pairs.each do |sig, port|
830
- sig.parent.open do
831
- port.to_ref <= sig
887
+ obj = self
888
+ # Make the inner connection
889
+ port_pairs.each do |sig, port|
890
+ sig.parent.open do
891
+ port.to_ref <= sig
892
+ end
893
+ end
894
+ else
895
+ # Port in different system as the channel case.
896
+ # Add them to the current system.
897
+ HDLRuby::High.cur_system.open do
898
+ # The inputs
899
+ loc_inputs.each do |name,sig|
900
+ # puts "name=#{name} sig.name=#{sig.name}"
901
+ port_pairs << [sig, sig.type.input(name)]
902
+ end
903
+ # The outputs
904
+ loc_outputs.each do |name,sig|
905
+ port_pairs << [sig, sig.type.output(name)]
906
+ end
907
+ # The inouts
908
+ loc_inouts.each do |name,sig|
909
+ port_pairs << [sig, sig.type.inout(name)]
910
+ end
911
+ end
912
+ obj = self
913
+ # Make the connection of the instance.
914
+ HDLRuby::High.cur_system.on_instance do |inst|
915
+ obj.scope.open do
916
+ port_pairs.each do |sig, port|
917
+ RefObject.new(inst,port.to_ref) <= sig
918
+ end
919
+ end
832
920
  end
833
921
  end
834
922
 
835
- # Set ups the accesser's namespace
923
+ # Fill the reader namespace with the access to the reader signals.
836
924
  loc_inputs.each do |name,sig|
837
925
  @accesser_namespace.add_method(sig.name) do
838
926
  HDLRuby::High.top_user.send(name)
@@ -853,37 +941,121 @@ module HDLRuby::High::Std
853
941
  # NOTE: for now, simply associate the channel to name.
854
942
  chp = ChannelPortA.new(@accesser_namespace,@reader_proc,@writer_proc,@inout_reseter_proc)
855
943
  HDLRuby::High.space_reg(name) { chp }
944
+ # Save the port in the channe to avoid conflicting declaration.
945
+ @read_port = chp
946
+ @write_port = chp
856
947
  return chp
857
948
  end
858
949
 
950
+ # ## Declares the ports for accessing the channel as an inner component
951
+ # # and assigned them to +name+.
952
+ # def inner(name)
953
+ # # Ensure name is a symbol.
954
+ # name = name.to_sym
955
+ # # Access the ports
956
+ # loc_inputs = @accesser_inputs.merge(@reader_inputs).
957
+ # merge(@writer_inputs)
958
+ # loc_outputs = @accesser_outputs.merge(@reader_outputs).
959
+ # merge(@writer_outputs)
960
+ # loc_inouts = @accesser_inouts.merge(@reader_inouts).
961
+ # merge(@writer_inouts)
962
+ # locs = loc_inputs.merge(loc_outputs).merge(loc_inouts)
963
+ # # The generated port with corresponding channel port pairs.
964
+ # port_pairs = []
965
+ # # Add them to the current system.
966
+ # HDLRuby::High.cur_system.open do
967
+ # locs.each do |name,sig|
968
+ # port_pairs << [sig, sig.type.inner(name)]
969
+ # end
970
+ # end
971
+ # obj = self
972
+ # # Make the inner connection
973
+ # port_pairs.each do |sig, port|
974
+ # sig.parent.open do
975
+ # port.to_ref <= sig
976
+ # end
977
+ # end
978
+
979
+ # # Set ups the accesser's namespace
980
+ # loc_inputs.each do |name,sig|
981
+ # @accesser_namespace.add_method(sig.name) do
982
+ # HDLRuby::High.top_user.send(name)
983
+ # end
984
+ # end
985
+ # loc_outputs.each do |name,sig|
986
+ # @accesser_namespace.add_method(sig.name) do
987
+ # HDLRuby::High.top_user.send(name)
988
+ # end
989
+ # end
990
+ # loc_inouts.each do |name,sig|
991
+ # @accesser_namespace.add_method(sig.name) do
992
+ # HDLRuby::High.top_user.send(name)
993
+ # end
994
+ # end
995
+
996
+ # # Give access to the ports through name.
997
+ # # NOTE: for now, simply associate the channel to name.
998
+ # chp = ChannelPortA.new(@accesser_namespace,@reader_proc,@writer_proc,@inout_reseter_proc)
999
+ # HDLRuby::High.space_reg(name) { chp }
1000
+ # return chp
1001
+ # end
1002
+
1003
+
859
1004
 
860
1005
  ## Performs a read on the channel using +args+ and +ruby_block+
861
1006
  # as arguments.
1007
+ # NOTE:
1008
+ # * Will generate a port if not present.
1009
+ # * Will generate an error if a read is tempted while the read
1010
+ # port has been declared within another system.
862
1011
  def read(*args,&ruby_block)
863
- # Gain access to the reader as local variable.
864
- reader_proc = @reader_proc
865
- # # The context is the one of the reader.
866
- # Execute the code generating the reader in context.
867
- HDLRuby::High.space_push(@namespace)
868
- HDLRuby::High.cur_block.open do
869
- instance_exec(ruby_block,*args,&reader_proc)
1012
+ # Is there a port to read?
1013
+ unless self.read_port then
1014
+ # No, generate a new one.
1015
+ # Is it possible to be inout?
1016
+ if self.inout? then
1017
+ # Yes, create an inout port.
1018
+ self.inout(HDLRuby.uniq_name)
1019
+ else
1020
+ # No, create an input port.
1021
+ self.input(HDLRuby.uniq_name)
1022
+ end
870
1023
  end
871
- HDLRuby::High.space_pop
1024
+ # Ensure the read port is within current system.
1025
+ unless self.read_port.scope.system != HDLRuby::High.cur_system then
1026
+ raise "Cannot read from a port external of current system for channel " + self.name
1027
+ end
1028
+ # Performs the read.
1029
+ self.read_port.read(*args,&ruby_block)
872
1030
  end
873
1031
 
874
1032
  ## Performs a write on the channel using +args+ and +ruby_block+
875
1033
  # as arguments.
1034
+ # NOTE:
1035
+ # * Will generate a port if not present.
1036
+ # * Will generate an error if a read is tempted while the read
1037
+ # port has been declared within another system.
876
1038
  def write(*args,&ruby_block)
877
- # Gain access to the writer as local variable.
878
- writer_proc = @writer_proc
879
- # # The context is the one of the writer.
880
- # Execute the code generating the writer in context.
881
- HDLRuby::High.space_push(@namespace)
882
- HDLRuby::High.cur_block.open do
883
- instance_exec(ruby_block,*args,&writer_proc)
1039
+ # Is there a port to write?
1040
+ unless self.write_port then
1041
+ # No, generate a new one.
1042
+ # Is it possible to be inout?
1043
+ if self.inout? then
1044
+ # Yes, create an inout port.
1045
+ self.inout(HDLRuby.uniq_name)
1046
+ else
1047
+ # No, create an output port.
1048
+ self.output(HDLRuby.uniq_name)
1049
+ end
884
1050
  end
885
- HDLRuby::High.space_pop
1051
+ # Ensure the write port is within current system.
1052
+ unless self.write_port.scope.system != HDLRuby::High.cur_system then
1053
+ raise "Cannot write from a port external of current system for channel " + self.name
1054
+ end
1055
+ # Performs the write.
1056
+ self.write_port.write(*args,&ruby_block)
886
1057
  end
1058
+
887
1059
 
888
1060
  ## Performs a reset on the channel using +args+ and +ruby_block+
889
1061
  # as arguments.
@@ -902,10 +1074,12 @@ module HDLRuby::High::Std
902
1074
 
903
1075
 
904
1076
  # Wrapper to make an object run like a channel port.
905
- class ChannelPortObject
1077
+ class ChannelPortObject < ChannelPort
906
1078
  # Create a new object wrapper for +obj+.
907
1079
  def initialize(obj)
908
1080
  @obj = obj
1081
+
1082
+ @scope = HDLRuby::High.cur_scope
909
1083
  end
910
1084
 
911
1085
  # Port read with arguments +args+ executing +ruby_block+ in
@@ -946,9 +1120,13 @@ module HDLRuby::High::Std
946
1120
 
947
1121
 
948
1122
  # Wrap object +obj+ to act like a channel port.
949
- def channel_port(obj)
1123
+ def self.channel_port(obj)
1124
+ return obj if obj.is_a?(ChannelPort) # No need to wrap.
950
1125
  return ChannelPortObject.new(obj)
951
1126
  end
1127
+ def channel_port(obj)
1128
+ return HDLRuby::High::Std.channel_port(obj)
1129
+ end
952
1130
  end
953
1131
 
954
1132