Skip to content
This repository
Browse code

Replace the NetPartSelect:BI with NetTran(VP).

Fold the bi-directional part select into the pass switch (tran) support
so that it can be really bi-directional. This involves adding a new
tranvp device that does part select in tran islands, and reworking the
tran island resolution to handle non-identical nodes. This will be needed
for resistive tran devices anyhow.
  • Loading branch information...
commit 73e2b297df13e925fe6ee3901d18960afd9c2ee4 1 parent 6e5373c
Stephen Williams authored
14 design_dump.cc
@@ -109,6 +109,9 @@ ostream& operator << (ostream&o, ivl_switch_type_t val)
109 109 case IVL_SW_RTRANIF1:
110 110 o << "rtranif1";
111 111 break;
  112 + case IVL_SW_TRAN_VP:
  113 + o << "tran(VP)";
  114 + break;
112 115 }
113 116 return o;
114 117 }
@@ -518,9 +521,6 @@ void NetPartSelect::dump_node(ostream&o, unsigned ind) const
518 521 case PV:
519 522 pt = "PV";
520 523 break;
521   - case BI:
522   - pt = "BI";
523   - break;
524 524 }
525 525 o << setw(ind) << "" << "NetPartSelect(" << pt << "): "
526 526 << name();
@@ -639,7 +639,13 @@ void NetTaskDef::dump(ostream&o, unsigned ind) const
639 639 void NetTran::dump_node(ostream&o, unsigned ind) const
640 640 {
641 641 o << setw(ind) << "" << type_ << " " << name()
642   - << " island " << island << endl;
  642 + << " island " << island;
  643 + if (type_ == IVL_SW_TRAN_VP) {
  644 + o << " width=" << vector_width()
  645 + << " part=" << part_width()
  646 + << " offset=" << part_offset();
  647 + }
  648 + o << endl;
643 649 dump_node_pins(o, ind+4);
644 650 dump_obj_attr(o, ind+4);
645 651 }
87 elab_net.cc
@@ -2375,29 +2375,54 @@ NetNet* PEConcat::elaborate_lnet_common_(Design*des, NetScope*scope,
2375 2375 osig->local_flag(true);
2376 2376 osig->set_line(*this);
2377 2377
2378   - if (debug_elaborate) {
2379   - cerr << get_fileline() << ": debug: Generating part selects "
2380   - << "to connect input l-value to subexpressions."
2381   - << endl;
2382   - }
  2378 + if (bidirectional_flag) {
  2379 + if (debug_elaborate) {
  2380 + cerr << get_fileline() << ": debug: Generating tran(VP) "
  2381 + << "to connect input l-value to subexpressions."
  2382 + << endl;
  2383 + }
2383 2384
2384   - NetPartSelect::dir_t part_dir = bidirectional_flag
2385   - ? NetPartSelect::BI
2386   - : NetPartSelect::VP;
  2385 + for (unsigned idx = 0 ; idx < nets.count() ; idx += 1) {
  2386 + unsigned wid = nets[idx]->vector_width();
  2387 + unsigned off = width - wid;
  2388 + NetTran*ps = new NetTran(scope, scope->local_symbol(),
  2389 + osig->vector_width(), wid, off);
  2390 + des->add_node(ps);
  2391 + ps->set_line(*this);
2387 2392
2388   - for (unsigned idx = 0 ; idx < nets.count() ; idx += 1) {
2389   - unsigned wid = nets[idx]->vector_width();
2390   - unsigned off = width - wid;
2391   - NetPartSelect*ps = new NetPartSelect(osig, off, wid, part_dir);
2392   - des->add_node(ps);
  2393 + connect(ps->pin(0), osig->pin(0));
  2394 + connect(ps->pin(1), nets[idx]->pin(0));
2393 2395
2394   - connect(ps->pin(1), osig->pin(0));
2395   - connect(ps->pin(0), nets[idx]->pin(0));
  2396 + join_island(ps);
  2397 +
  2398 + ivl_assert(*this, wid <= width);
  2399 + width -= wid;
  2400 + }
  2401 +
  2402 + } else {
  2403 + if (debug_elaborate) {
  2404 + cerr << get_fileline() << ": debug: Generating part selects "
  2405 + << "to connect input l-value to subexpressions."
  2406 + << endl;
  2407 + }
2396 2408
2397   - assert(wid <= width);
2398   - width -= wid;
  2409 + NetPartSelect::dir_t part_dir = NetPartSelect::VP;
  2410 +
  2411 + for (unsigned idx = 0 ; idx < nets.count() ; idx += 1) {
  2412 + unsigned wid = nets[idx]->vector_width();
  2413 + unsigned off = width - wid;
  2414 + NetPartSelect*ps = new NetPartSelect(osig, off, wid, part_dir);
  2415 + des->add_node(ps);
  2416 + ps->set_line(*this);
  2417 +
  2418 + connect(ps->pin(1), osig->pin(0));
  2419 + connect(ps->pin(0), nets[idx]->pin(0));
  2420 +
  2421 + assert(wid <= width);
  2422 + width -= wid;
  2423 + }
  2424 + assert(width == 0);
2399 2425 }
2400   - assert(width == 0);
2401 2426
2402 2427 osig->data_type(nets[0]->data_type());
2403 2428 osig->local_flag(true);
@@ -2751,11 +2776,6 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
2751 2776 /* If we are processing a tran or inout, then the
2752 2777 partselect is bi-directional. Otherwise, it is a
2753 2778 Part-to-Vector select. */
2754   - NetPartSelect::dir_t part_dir;
2755   - if (bidirectional_flag)
2756   - part_dir = NetPartSelect::BI;
2757   - else
2758   - part_dir = NetPartSelect::PV;
2759 2779
2760 2780 if (debug_elaborate)
2761 2781 cerr << get_fileline() << ": debug: "
@@ -2772,11 +2792,24 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
2772 2792 subsig->local_flag(true);
2773 2793 subsig->set_line(*this);
2774 2794
2775   - NetPartSelect*sub = new NetPartSelect(sig, lidx, subnet_wid,
2776   - part_dir);
2777   - des->add_node(sub);
2778   - connect(sub->pin(0), subsig->pin(0));
  2795 + if (bidirectional_flag) {
  2796 + // Make a tran(VP)
  2797 + NetTran*sub = new NetTran(scope, scope->local_symbol(),
  2798 + sig->vector_width(),
  2799 + subnet_wid, lidx);
  2800 + sub->set_line(*this);
  2801 + des->add_node(sub);
  2802 + connect(sub->pin(0), sig->pin(0));
  2803 + connect(sub->pin(1), subsig->pin(0));
  2804 + join_island(sub);
2779 2805
  2806 + } else {
  2807 + NetPartSelect*sub = new NetPartSelect(sig, lidx, subnet_wid,
  2808 + NetPartSelect::PV);
  2809 + des->add_node(sub);
  2810 + sub->set_line(*this);
  2811 + connect(sub->pin(0), subsig->pin(0));
  2812 + }
2780 2813 sig = subsig;
2781 2814 }
2782 2815
36 elaborate.cc
@@ -889,6 +889,32 @@ NetNet*PGModule::resize_net_to_port_(Design*des, NetScope*scope,
889 889 tmp->local_flag(true);
890 890 tmp->set_line(*sig);
891 891
  892 + // Handle the special case of a bi-directional part
  893 + // select. Create a NetTran(VP) instead of a uni-directional
  894 + // NetPartSelect node.
  895 + if (dir == NetNet::PINOUT) {
  896 + unsigned wida = sig->vector_width();
  897 + unsigned widb = tmp->vector_width();
  898 + bool part_b = widb < wida;
  899 + NetTran*node = new NetTran(scope, scope->local_symbol(),
  900 + part_b? wida : widb,
  901 + part_b? widb : wida,
  902 + 0);
  903 + if (part_b) {
  904 + connect(node->pin(0), tmp->pin(0));
  905 + connect(node->pin(1), sig->pin(0));
  906 + } else {
  907 + connect(node->pin(0), sig->pin(0));
  908 + connect(node->pin(1), tmp->pin(0));
  909 + }
  910 +
  911 + node->set_line(*this);
  912 + des->add_node(node);
  913 + join_island(node);
  914 +
  915 + return tmp;
  916 + }
  917 +
892 918 NetPartSelect*node = 0;
893 919
894 920 switch (dir) {
@@ -917,15 +943,7 @@ NetNet*PGModule::resize_net_to_port_(Design*des, NetScope*scope,
917 943 break;
918 944
919 945 case NetNet::PINOUT:
920   - if (sig->vector_width() > tmp->vector_width()) {
921   - node = new NetPartSelect(sig, 0, tmp->vector_width(),
922   - NetPartSelect::BI);
923   - connect(node->pin(0), tmp->pin(0));
924   - } else {
925   - node = new NetPartSelect(tmp, 0, sig->vector_width(),
926   - NetPartSelect::BI);
927   - connect(node->pin(0), sig->pin(0));
928   - }
  946 + ivl_assert(*this, 0);
929 947 break;
930 948
931 949 default:
3  ivl.def
@@ -226,8 +226,11 @@ ivl_switch_enable
226 226 ivl_switch_file
227 227 ivl_switch_island
228 228 ivl_switch_lineno
  229 +ivl_switch_offset
  230 +ivl_switch_part
229 231 ivl_switch_scope
230 232 ivl_switch_type
  233 +ivl_switch_width
231 234
232 235 ivl_udp_init
233 236 ivl_udp_name
20 ivl_target.h
@@ -245,7 +245,8 @@ typedef enum ivl_switch_type_e {
245 245 IVL_SW_TRANIF1 = 2,
246 246 IVL_SW_RTRAN = 3,
247 247 IVL_SW_RTRANIF0 = 4,
248   - IVL_SW_RTRANIF1 = 5
  248 + IVL_SW_RTRANIF1 = 5,
  249 + IVL_SW_TRAN_VP = 6
249 250 } ivl_switch_type_t;
250 251
251 252 /* This is the type of an LPM object. */
@@ -265,7 +266,7 @@ typedef enum ivl_lpm_type_e {
265 266 IVL_LPM_MOD = 13,
266 267 IVL_LPM_MULT = 4,
267 268 IVL_LPM_MUX = 5,
268   - IVL_LPM_PART_BI= 28, /* part select: bi-directional (part on 0) */
  269 + /* IVL_LPM_PART_BI= 28, / obsolete */
269 270 IVL_LPM_PART_VP= 15, /* part select: vector to part */
270 271 IVL_LPM_PART_PV= 17, /* part select: part written to vector */
271 272 IVL_LPM_POW = 31,
@@ -728,8 +729,8 @@ extern unsigned ivl_file_table_size(void);
728 729 * Allow the user to test or set a boolean flag associated with the
729 730 * island.
730 731 */
731   -extern int ivl_island_flag_set(ivl_island_t net, int flag, int value);
732   -extern int ivl_island_flag_test(ivl_island_t net, int flag);
  732 +extern int ivl_island_flag_set(ivl_island_t net, unsigned flag, int value);
  733 +extern int ivl_island_flag_test(ivl_island_t net, unsigned flag);
733 734
734 735 /* LOGIC
735 736 * These types and functions support manipulation of logic gates. The
@@ -1883,7 +1884,11 @@ extern ivl_statement_t ivl_stmt_sub_stmt(ivl_statement_t net);
1883 1884 *
1884 1885 * SEMANTIC NOTES
1885 1886 * The a/b ports can be any type, but the types must exactly
1886   - * match. The enable must be a scalar.
  1887 + * match, including vector widths. The enable must be a scalar.
  1888 + *
  1889 + * The IVL_SW_TRAN_VP is an exception to the above. In this case,
  1890 + * the B side may be a different size, and the a side will have a
  1891 + * a fixed width. The unused bits are padded to Z on the A side.
1887 1892 */
1888 1893 extern ivl_switch_type_t ivl_switch_type(ivl_switch_t net);
1889 1894 extern ivl_scope_t ivl_switch_scope(ivl_switch_t net);
@@ -1893,6 +1898,11 @@ extern ivl_nexus_t ivl_switch_b(ivl_switch_t net);
1893 1898 extern ivl_nexus_t ivl_switch_enable(ivl_switch_t net);
1894 1899 extern ivl_island_t ivl_switch_island(ivl_switch_t net);
1895 1900
  1901 + /* These are only support for IVL_SW_TRAN_VP switches. */
  1902 +extern unsigned ivl_switch_width(ivl_switch_t net);
  1903 +extern unsigned ivl_switch_part(ivl_switch_t net);
  1904 +extern unsigned ivl_switch_offset(ivl_switch_t net);
  1905 +
1896 1906 /* Not implemented yet
1897 1907 extern unsigned ivl_switch_attr_cnt(ivl_switch_t net);
1898 1908 extern ivl_attribute_t ivl_switch_attr_val(ivl_switch_t net, unsigned idx);
24 net_tran.cc
@@ -43,7 +43,7 @@ static bool has_enable(ivl_switch_type_t tt)
43 43 }
44 44
45 45 NetTran::NetTran(NetScope*scope, perm_string n, ivl_switch_type_t tt)
46   - : NetNode(scope, n, has_enable(tt)? 3 : 2), type_(tt)
  46 +: NetNode(scope, n, has_enable(tt)? 3 : 2), type_(tt)
47 47 {
48 48 pin(0).set_dir(Link::PASSIVE); pin(0).set_name(perm_string::literal("A"), 0);
49 49 pin(1).set_dir(Link::PASSIVE); pin(1).set_name(perm_string::literal("B"), 0);
@@ -53,10 +53,32 @@ NetTran::NetTran(NetScope*scope, perm_string n, ivl_switch_type_t tt)
53 53 }
54 54 }
55 55
  56 +NetTran::NetTran(NetScope*scope, perm_string n, unsigned wid, unsigned part, unsigned off)
  57 +: NetNode(scope, n, 2), type_(IVL_SW_TRAN_VP), wid_(wid), part_(part), off_(off)
  58 +{
  59 + pin(0).set_dir(Link::PASSIVE); pin(0).set_name(perm_string::literal("A"), 0);
  60 + pin(1).set_dir(Link::PASSIVE); pin(1).set_name(perm_string::literal("B"), 0);
  61 +}
  62 +
56 63 NetTran::~NetTran()
57 64 {
58 65 }
59 66
  67 +unsigned NetTran::vector_width() const
  68 +{
  69 + return wid_;
  70 +}
  71 +
  72 +unsigned NetTran::part_width() const
  73 +{
  74 + return part_;
  75 +}
  76 +
  77 +unsigned NetTran::part_offset() const
  78 +{
  79 + return off_;
  80 +}
  81 +
60 82 void join_island(NetObj*obj)
61 83 {
62 84 IslandBranch*branch = dynamic_cast<IslandBranch*> (obj);
22 netlist.h
@@ -1379,16 +1379,28 @@ class NetSysFunc : public NetNode {
1379 1379 class NetTran : public NetNode, public IslandBranch {
1380 1380
1381 1381 public:
  1382 + // Tran devices other then TRAN_VP
1382 1383 NetTran(NetScope*scope, perm_string n, ivl_switch_type_t type);
  1384 + // Create a TRAN_VP
  1385 + NetTran(NetScope*scope, perm_string n, unsigned wid,
  1386 + unsigned part, unsigned off);
1383 1387 ~NetTran();
1384 1388
1385 1389 ivl_switch_type_t type() const { return type_; }
1386 1390
  1391 + // These are only used for IVL_SW_TRAN_PV
  1392 + unsigned vector_width() const;
  1393 + unsigned part_width() const;
  1394 + unsigned part_offset() const;
  1395 +
1387 1396 virtual void dump_node(ostream&, unsigned ind) const;
1388 1397 virtual bool emit_node(struct target_t*) const;
1389 1398
1390 1399 private:
1391 1400 ivl_switch_type_t type_;
  1401 + unsigned wid_;
  1402 + unsigned part_;
  1403 + unsigned off_;
1392 1404 };
1393 1405
1394 1406 /* =========
@@ -1605,8 +1617,8 @@ class NetECRealParam : public NetECReal {
1605 1617 * selector as the input.
1606 1618 *
1607 1619 * The NetPartSelect can be output from the signal (i.e. reading a
1608   - * part), input into the signal, or bi-directional. The DIR method
1609   - * gives the type of the node.
  1620 + * part) or input into the signal. The DIR method gives the type of
  1621 + * the node.
1610 1622 *
1611 1623 * VP (Vector-to-Part)
1612 1624 * Output pin 0 is the part select, and input pin 1 is connected to
@@ -1616,10 +1628,6 @@ class NetECRealParam : public NetECReal {
1616 1628 * Output pin 1 is connected to the NetNet, and input pin 0 is the
1617 1629 * part select. In this case, the node is driving the NetNet.
1618 1630 *
1619   - * BI (BI-directional)
1620   - * Pin 0 is the part select and pin 1 is connected to the NetNet, but
1621   - * the ports are intended to be bi-directional.
1622   - *
1623 1631 * Note that whatever the direction that data is intended to flow,
1624 1632 * pin-0 is the part select and pin-1 is connected to the NetNet.
1625 1633 */
@@ -1627,7 +1635,7 @@ class NetPartSelect : public NetNode {
1627 1635
1628 1636 public:
1629 1637 // enum for the device direction
1630   - enum dir_t { VP, PV, BI };
  1638 + enum dir_t { VP, PV};
1631 1639
1632 1640 explicit NetPartSelect(NetNet*sig,
1633 1641 unsigned off, unsigned wid, dir_t dir);
23 t-dll-api.cc
@@ -555,7 +555,7 @@ extern "C" unsigned ivl_file_table_size()
555 555 return fn_vector.size();
556 556 }
557 557
558   -extern "C" int ivl_island_flag_set(ivl_island_t net, int flag, int value)
  558 +extern "C" int ivl_island_flag_set(ivl_island_t net, unsigned flag, int value)
559 559 {
560 560 if (flag >= net->flags.size()) {
561 561 if (value == 0)
@@ -569,7 +569,7 @@ extern "C" int ivl_island_flag_set(ivl_island_t net, int flag, int value)
569 569 return old_flag;
570 570 }
571 571
572   -extern "C" int ivl_island_flag_test(ivl_island_t net, int flag)
  572 +extern "C" int ivl_island_flag_test(ivl_island_t net, unsigned flag)
573 573 {
574 574 if (flag >= net->flags.size())
575 575 return 0;
@@ -804,7 +804,6 @@ extern "C" unsigned ivl_lpm_base(ivl_lpm_t net)
804 804 switch (net->type) {
805 805 case IVL_LPM_PART_VP:
806 806 case IVL_LPM_PART_PV:
807   - case IVL_LPM_PART_BI:
808 807 return net->u_.part.base;
809 808 default:
810 809 assert(0);
@@ -940,7 +939,6 @@ extern "C" ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx)
940 939
941 940 case IVL_LPM_PART_VP:
942 941 case IVL_LPM_PART_PV:
943   - case IVL_LPM_PART_BI:
944 942 assert(idx <= 1);
945 943 if (idx == 0)
946 944 return net->u_.part.a;
@@ -1083,7 +1081,6 @@ extern "C" ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx)
1083 1081
1084 1082 case IVL_LPM_PART_VP:
1085 1083 case IVL_LPM_PART_PV:
1086   - case IVL_LPM_PART_BI:
1087 1084 assert(idx == 0);
1088 1085 return net->u_.part.q;
1089 1086
@@ -1179,7 +1176,6 @@ extern "C" int ivl_lpm_signed(ivl_lpm_t net)
1179 1176 return 0;
1180 1177 case IVL_LPM_PART_VP:
1181 1178 case IVL_LPM_PART_PV:
1182   - case IVL_LPM_PART_BI:
1183 1179 return net->u_.part.signed_flag;
1184 1180 case IVL_LPM_REPEAT:
1185 1181 return 0;
@@ -2218,6 +2214,21 @@ extern "C" ivl_nexus_t ivl_switch_enable(ivl_switch_t net)
2218 2214 return net->pins[2];
2219 2215 }
2220 2216
  2217 +extern "C" unsigned ivl_switch_width(ivl_switch_t net)
  2218 +{
  2219 + return net->width;
  2220 +}
  2221 +
  2222 +extern "C" unsigned ivl_switch_part(ivl_switch_t net)
  2223 +{
  2224 + return net->part;
  2225 +}
  2226 +
  2227 +extern "C" unsigned ivl_switch_offset(ivl_switch_t net)
  2228 +{
  2229 + return net->offset;
  2230 +}
  2231 +
2221 2232 extern "C" const char* ivl_switch_file(ivl_switch_t net)
2222 2233 {
2223 2234 return net->file;
37 t-dll.cc
@@ -1037,6 +1037,9 @@ bool dll_target::tran(const NetTran*net)
1037 1037 {
1038 1038 struct ivl_switch_s*obj = new struct ivl_switch_s;
1039 1039 obj->type = net->type();
  1040 + obj->width = 0;
  1041 + obj->part = 0;
  1042 + obj->offset = 0;
1040 1043 obj->name = net->name();
1041 1044 obj->scope = find_scope(des_, net->scope());
1042 1045 obj->island = net->island;
@@ -1065,6 +1068,12 @@ bool dll_target::tran(const NetTran*net)
1065 1068 obj->pins[2] = 0;
1066 1069 }
1067 1070
  1071 + if (obj->type == IVL_SW_TRAN_VP) {
  1072 + obj->width = net->vector_width();
  1073 + obj->part = net->part_width();
  1074 + obj->offset= net->part_offset();
  1075 + }
  1076 +
1068 1077 obj->file = net->get_file();
1069 1078 obj->lineno = net->get_lineno();
1070 1079
@@ -1996,9 +2005,6 @@ bool dll_target::part_select(const NetPartSelect*net)
1996 2005 case NetPartSelect::PV:
1997 2006 obj->type = IVL_LPM_PART_PV;
1998 2007 break;
1999   - case NetPartSelect::BI:
2000   - obj->type = IVL_LPM_PART_BI;
2001   - break;
2002 2008 }
2003 2009 obj->name = net->name(); // NetPartSelect names are permallocated.
2004 2010 assert(net->scope());
@@ -2052,35 +2058,12 @@ bool dll_target::part_select(const NetPartSelect*net)
2052 2058 obj->u_.part.a = nex->t_cookie();
2053 2059 break;
2054 2060
2055   - case IVL_LPM_PART_BI:
2056   - /* For now, handle this exactly the same as a PV */
2057   -
2058   - /* NetPartSelect:pin(0) is the output pin. */
2059   - nex = net->pin(0).nexus();
2060   - assert(nex->t_cookie());
2061   -
2062   - obj->u_.part.q = nex->t_cookie();
2063   -
2064   - /* NetPartSelect:pin(1) is the input pin. */
2065   - nex = net->pin(1).nexus();
2066   - assert(nex->t_cookie());
2067   -
2068   - obj->u_.part.a = nex->t_cookie();
2069   - break;
2070   -
2071 2061 default:
2072 2062 assert(0);
2073 2063 }
2074 2064
2075 2065 nexus_lpm_add(obj->u_.part.q, obj, 0, IVL_DR_STRONG, IVL_DR_STRONG);
2076   -
2077   - /* If the device is a PART_BI, then the "input" is also a
2078   - strength aware output, so attach it to the nexus with
2079   - strong driver. */
2080   - if (obj->type == IVL_LPM_PART_BI)
2081   - nexus_lpm_add(obj->u_.part.a, obj, 0, IVL_DR_STRONG, IVL_DR_STRONG);
2082   - else
2083   - nexus_lpm_add(obj->u_.part.a, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
  2066 + nexus_lpm_add(obj->u_.part.a, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
2084 2067
2085 2068 /* The select input is optional. */
2086 2069 if (obj->u_.part.s)
3  t-dll.h
@@ -451,6 +451,9 @@ struct ivl_net_logic_s {
451 451
452 452 struct ivl_switch_s {
453 453 ivl_switch_type_t type;
  454 + unsigned width;
  455 + unsigned part;
  456 + unsigned offset;
454 457
455 458 perm_string name;
456 459 ivl_scope_t scope;
37 tgt-stub/stub.c
@@ -555,38 +555,6 @@ static void show_lpm_part(ivl_lpm_t net)
555 555 }
556 556 }
557 557
558   -static void show_lpm_part_bi(ivl_lpm_t net)
559   -{
560   - unsigned width = ivl_lpm_width(net);
561   - unsigned base = ivl_lpm_base(net);
562   - ivl_nexus_t port_p = ivl_lpm_q(net,0);
563   - ivl_nexus_t port_v = ivl_lpm_data(net,0);
564   -
565   - fprintf(out, " LPM_PART_BI %s: <width=%u, base=%u, signed=%d>\n",
566   - ivl_lpm_basename(net), width, base, ivl_lpm_signed(net));
567   - fprintf(out, " P: %s\n", ivl_nexus_name(port_p));
568   - fprintf(out, " V: %s <width=%u>\n", ivl_nexus_name(port_v),
569   - width_of_nexus(port_v));
570   -
571   -
572   - /* The data(0) port must be large enough for the part select. */
573   - if (width_of_nexus(ivl_lpm_data(net,0)) < (width+base)) {
574   - fprintf(out, " ERROR: Part select is out of range."
575   - " Data nexus width=%u, width+base=%u\n",
576   - width_of_nexus(ivl_lpm_data(net,0)), width+base);
577   - stub_errors += 1;
578   - }
579   -
580   - /* The Q vector must be exactly the width of the part select. */
581   - if (width_of_nexus(ivl_lpm_q(net,0)) != width) {
582   - fprintf(out, " ERROR: Part select input mismatch."
583   - " Nexus width=%u, expect width=%u\n",
584   - width_of_nexus(ivl_lpm_q(net,0)), width);
585   - stub_errors += 1;
586   - }
587   -}
588   -
589   -
590 558 /*
591 559 * The reduction operators have similar characteristics and are
592 560 * displayed here.
@@ -905,11 +873,6 @@ static void show_lpm(ivl_lpm_t net)
905 873 show_lpm_part(net);
906 874 break;
907 875
908   - /* The BI part select is slightly special. */
909   - case IVL_LPM_PART_BI:
910   - show_lpm_part_bi(net);
911   - break;
912   -
913 876 case IVL_LPM_REPEAT:
914 877 show_lpm_repeat(net);
915 878 break;
52 tgt-stub/switches.c
@@ -52,18 +52,23 @@ void show_switch(ivl_switch_t net)
52 52 fprintf(out, " rtranif1 %s", name);
53 53 has_enable = 1;
54 54 break;
  55 + case IVL_SW_TRAN_VP:
  56 + fprintf(out, " tran(PV wid=%u, part=%u, off=%u) %s",
  57 + ivl_switch_width(net), ivl_switch_part(net),
  58 + ivl_switch_offset(net), name);
  59 + break;
55 60 }
56 61
57 62 fprintf(out, " island=%p\n", ivl_switch_island(net));
58 63
59   - ivl_nexus_t nex = ivl_switch_a(net);
60   - const char*nex_name = nex? ivl_nexus_name(nex) : "";
61   - ivl_variable_type_t nex_type_a = nex? type_of_nexus(nex) : IVL_VT_NO_TYPE;
  64 + ivl_nexus_t nexa = ivl_switch_a(net);
  65 + const char*nex_name = nexa? ivl_nexus_name(nexa) : "";
  66 + ivl_variable_type_t nex_type_a = nexa? type_of_nexus(nexa) : IVL_VT_NO_TYPE;
62 67 fprintf(out, " A: %s <type=%s>\n", nex_name, data_type_string(nex_type_a));
63 68
64   - nex = ivl_switch_b(net);
65   - nex_name = nex? ivl_nexus_name(nex) : "";
66   - ivl_variable_type_t nex_type_b = nex? type_of_nexus(nex) : IVL_VT_NO_TYPE;
  69 + ivl_nexus_t nexb = ivl_switch_b(net);
  70 + nex_name = nexb? ivl_nexus_name(nexb) : "";
  71 + ivl_variable_type_t nex_type_b = nexb? type_of_nexus(nexb) : IVL_VT_NO_TYPE;
67 72 fprintf(out, " B: %s <type=%s>\n", nex_name, data_type_string(nex_type_b));
68 73
69 74 /* The A/B pins of the switch must be present, and must match. */
@@ -80,13 +85,40 @@ void show_switch(ivl_switch_t net)
80 85 stub_errors += 1;
81 86 }
82 87
  88 + if (ivl_switch_type(net) == IVL_SW_TRAN_VP) {
  89 + /* The TRAN_VP nodes are special in that the specific
  90 + width matters for each port and should be exactly
  91 + right for both. */
  92 + if (width_of_nexus(nexa) != ivl_switch_width(net)) {
  93 + fprintf(out, " A: ERROR: part vector nexus "
  94 + "width=%u, expecting width=%u\n",
  95 + width_of_nexus(nexa), ivl_switch_width(net));
  96 + stub_errors += 1;
  97 + }
  98 + if (width_of_nexus(nexb) != ivl_switch_part(net)) {
  99 + fprintf(out, " B: ERROR: part select nexus "
  100 + "width=%u, expecting width=%u\n",
  101 + width_of_nexus(nexb), ivl_switch_part(net));
  102 + stub_errors += 1;
  103 + }
  104 + } else {
  105 + /* All other TRAN nodes will have matching vector
  106 + widths, but the actual value doesn't matter. */
  107 + if (width_of_nexus(nexa) != width_of_nexus(nexb)) {
  108 + fprintf(out, " A/B: ERROR: Width of ports don't match"
  109 + ": A=%u, B=%u\n",
  110 + width_of_nexus(nexa), width_of_nexus(nexb));
  111 + stub_errors += 1;
  112 + }
  113 + }
  114 +
83 115 if (has_enable) {
84   - nex = ivl_switch_enable(net);
85   - nex_name = nex? ivl_nexus_name(nex) : "";
  116 + ivl_nexus_t nexe = ivl_switch_enable(net);
  117 + nex_name = nexe? ivl_nexus_name(nexe) : "";
86 118 fprintf(out, " E: %s\n", nex_name);
87   - if (width_of_nexus(nex) != 1) {
  119 + if (width_of_nexus(nexe) != 1) {
88 120 fprintf(out, " E: ERROR: Nexus width is %u\n",
89   - width_of_nexus(nex));
  121 + width_of_nexus(nexe));
90 122 }
91 123 }
92 124 }
25 tgt-vvp/draw_net_input.c
@@ -421,17 +421,6 @@ static char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr)
421 421 }
422 422 break;
423 423
424   - case IVL_LPM_PART_BI:
425   - if (ivl_lpm_q(lpm, 0) == nex) {
426   - char tmp[128];
427   - snprintf(tmp, sizeof tmp, "L_%p/P", lpm);
428   - return strdup(tmp);
429   - } else if (ivl_lpm_data(lpm,0) == nex) {
430   - char tmp[128];
431   - snprintf(tmp, sizeof tmp, "L_%p/V", lpm);
432   - return strdup(tmp);
433   - }
434   - break;
435 424 }
436 425
437 426 fprintf(stderr, "internal error: no input to nexus %s\n",
@@ -440,7 +429,8 @@ static char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr)
440 429 return strdup("C<z>");
441 430 }
442 431
443   -static char* draw_island_port(ivl_island_t island, ivl_nexus_t nex, const char*src)
  432 +static char* draw_island_port(ivl_island_t island,
  433 + ivl_nexus_t nex, const char*src)
444 434 {
445 435 char result[64];
446 436 if (ivl_island_flag_test(island,0) == 0) {
@@ -450,6 +440,7 @@ static char* draw_island_port(ivl_island_t island, ivl_nexus_t nex, const char*s
450 440
451 441 fprintf(vvp_out, "p%p .port I%p, %s;\n", nex, island, src);
452 442 snprintf(result, sizeof result, "p%p", nex);
  443 +
453 444 return strdup(result);
454 445 }
455 446
@@ -517,13 +508,14 @@ char* draw_net_input_x(ivl_nexus_t nex,
517 508
518 509 for (idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) {
519 510 ivl_lpm_t lpm_tmp;
520   - ivl_switch_t sw;
  511 + ivl_switch_t sw = 0;
521 512 ivl_nexus_ptr_t nptr = ivl_nexus_ptr(nex, idx);
522 513
523 514 /* If this object is part of an island, then we'll be
524 515 making a port. Save the island cookie. */
525   - if ( (sw = ivl_nexus_ptr_switch(nptr)) )
  516 + if ( (sw = ivl_nexus_ptr_switch(nptr)) ) {
526 517 island = ivl_switch_island(sw);
  518 + }
527 519
528 520 /* If we are supposed to skip LPM_PART_BI data pins,
529 521 check that this driver is that. */
@@ -589,6 +581,11 @@ char* draw_net_input_x(ivl_nexus_t nex,
589 581 }
590 582 *tmp++ = '>';
591 583 *tmp = 0;
  584 + if (island) {
  585 + char*tmp = draw_island_port(island, nex, nex_private);
  586 + free(nex_private);
  587 + nex_private = tmp;
  588 + }
592 589 return nex_private;
593 590 }
594 591
11 tgt-vvp/draw_switch.c
@@ -53,14 +53,19 @@ void draw_switch_in_scope(ivl_switch_t sw)
53 53
54 54 switch (ivl_switch_type(sw)) {
55 55 case IVL_SW_TRAN:
56   - fprintf(vvp_out, " .tran ");
  56 + fprintf(vvp_out, " .tran");
57 57 break;
58 58 case IVL_SW_TRANIF0:
59   - fprintf(vvp_out, " .tranif0 ");
  59 + fprintf(vvp_out, " .tranif0");
60 60 break;
61 61 case IVL_SW_TRANIF1:
62   - fprintf(vvp_out, " .tranif1 ");
  62 + fprintf(vvp_out, " .tranif1");
63 63 break;
  64 + case IVL_SW_TRAN_VP:
  65 + fprintf(vvp_out, " .tranvp %u %u %u,",
  66 + ivl_switch_width(sw), ivl_switch_part(sw), ivl_switch_offset(sw));
  67 + break;
  68 +
64 69 default:
65 70 fprintf(stderr, "%s:%u: sorry: vvp target does not support switch modeling.\n",
66 71 ivl_switch_file(sw), ivl_switch_lineno(sw));
92 tgt-vvp/vvp_scope.c
@@ -1612,94 +1612,6 @@ static void draw_lpm_part_pv(ivl_lpm_t net)
1612 1612 }
1613 1613
1614 1614 /*
1615   - * Handle the drawing of a bi-directional part select. The two ports
1616   - * are simultaneously input and output. A simple minded connect of the
1617   - * input to the output causes a functor cycle which will lock into an
1618   - * X value, so something special is needed.
1619   - *
1620   - * NOTE: The inputs of the tran device at this point need to be from
1621   - * all the drivers of the nexus *except* the tran itself. This
1622   - * function will draw three labels that can be linked:
1623   - *
1624   - * The ivl_lpm_q of a part(bi) may be a smaller vector then the
1625   - * ivl_lpm_data, the tran acts like a forward part select in that
1626   - * way.
1627   - *
1628   - * The device creates these nodes:
1629   - *
1630   - * - L_%p/i
1631   - * This is the Q port of the tran resolved and padded to the maximum
1632   - * width of the tran. The tran itself is not included in the
1633   - * resolution of this port.
1634   - *
1635   - * - L_%p/V
1636   - * This is the Q and D parts resolved together, still without the tran
1637   - * driving anything.
1638   - *
1639   - * - L_%p/P
1640   - * This is the /V node part-selected back to the dimensions of the Q
1641   - * side.
1642   - */
1643   -static void draw_lpm_part_bi(ivl_lpm_t net)
1644   -{
1645   - unsigned width = ivl_lpm_width(net);
1646   - unsigned base = ivl_lpm_base(net);
1647   - unsigned signal_width = width_of_nexus(ivl_lpm_data(net,0));
1648   -
1649   - unsigned idx;
1650   - ivl_nexus_t nex;
1651   - ivl_nexus_ptr_t ptr = 0;
1652   -
1653   - char*p_str;
1654   - char*v_str;
1655   -
1656   - /* It seems implausible that the two inputs of a tran will be
1657   - connected together. So assert that this is so to simplify
1658   - the code to look for the nexus_ptr_t objects. */
1659   - assert(ivl_lpm_q(net,0) != ivl_lpm_data(net,0));
1660   -
1661   - nex = ivl_lpm_q(net,0);
1662   - for (idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) {
1663   - ptr = ivl_nexus_ptr(nex, idx);
1664   - if (ivl_nexus_ptr_lpm(ptr) == net)
1665   - break;
1666   - }
1667   - assert(ptr != 0);
1668   - p_str = draw_net_input_x(nex, ptr, 0, 0);
1669   -
1670   - nex = ivl_lpm_data(net,0);
1671   - for (idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) {
1672   - ptr = ivl_nexus_ptr(nex, idx);
1673   - if (ivl_nexus_ptr_lpm(ptr) == net)
1674   - break;
1675   - }
1676   - v_str = draw_net_input_x(nex, ptr, OMIT_PART_BI_DATA, 0);
1677   -
1678   - /* Pad the part-sized input out to a common width...
1679   - The /i label is the Q side of the tran, resolved except for
1680   - the tran itself and padded (with z) to the larger width. */
1681   - fprintf(vvp_out, "L_%p/i .part/pv %s, %u, %u, %u;\n",
1682   - net, p_str, base, width, signal_width);
1683   -
1684   - /* Resolve together the two halves of the tran...
1685   - The /V label is the ports of the tran (now the same width)
1686   - resolved together. Neither input to this resolver includes
1687   - the tran itself. */
1688   - fprintf(vvp_out, "L_%p/V .resolv tri, L_%p/i, %s;\n",
1689   - net, net, v_str);
1690   -
1691   - /* The full-width side is created by the tran device, all we
1692   - have left to to is take a part select of that for the
1693   - smaller output, and this becomes the part select output of
1694   - the BI device. */
1695   - fprintf(vvp_out, "L_%p/P .part L_%p/V, %u, %u;\n", net,
1696   - net, base, width);
1697   -
1698   - free(p_str);
1699   - free(v_str);
1700   -}
1701   -
1702   -/*
1703 1615 * Draw unary reduction devices.
1704 1616 */
1705 1617 static void draw_lpm_re(ivl_lpm_t net, const char*type)
@@ -1745,10 +1657,6 @@ static void draw_lpm_in_scope(ivl_lpm_t net)
1745 1657 draw_lpm_array(net);
1746 1658 return;
1747 1659
1748   - case IVL_LPM_PART_BI:
1749   - draw_lpm_part_bi(net);
1750   - return;
1751   -
1752 1660 case IVL_LPM_PART_VP:
1753 1661 draw_lpm_part(net);
1754 1662 return;
2  vvp/compile.h
@@ -460,6 +460,8 @@ extern void compile_island_export(char*label, char*island);
460 460
461 461 extern void compile_island_tranif(int sense, char*island,
462 462 char*ba, char*bb, char*src);
  463 +extern void compile_island_tranvp(char*island, char*ba, char*bb,
  464 + unsigned width, unsigned part, unsigned off);
463 465
464 466 extern void compile_island_cleanup(void);
465 467
1  vvp/lexor.lex
@@ -160,6 +160,7 @@
160 160 ".tran" { return K_TRAN; }
161 161 ".tranif0" { return K_TRANIF0; }
162 162 ".tranif1" { return K_TRANIF1; }
  163 +".tranvp" { return K_TRANVP; }
163 164 ".ufunc" { return K_UFUNC; }
164 165 ".var" { return K_VAR; }
165 166 ".var/real" { return K_VAR_R; }
5 vvp/parse.y
@@ -81,7 +81,7 @@ static struct __vpiModPath*modpath_dst = 0;
81 81 %token K_PART_V K_PORT K_PV K_REDUCE_AND K_REDUCE_OR K_REDUCE_XOR
82 82 %token K_REDUCE_NAND K_REDUCE_NOR K_REDUCE_XNOR K_REPEAT
83 83 %token K_RESOLV K_SCOPE K_SFUNC K_SHIFTL K_SHIFTR K_SHIFTRS
84   -%token K_THREAD K_TIMESCALE K_TRAN K_TRANIF0 K_TRANIF1 K_UFUNC
  84 +%token K_THREAD K_TIMESCALE K_TRAN K_TRANIF0 K_TRANIF1 K_TRANVP K_UFUNC
85 85 %token K_UDP K_UDP_C K_UDP_S
86 86 %token K_VAR K_VAR_S K_VAR_I K_VAR_R K_vpi_call K_vpi_func K_vpi_func_r
87 87 %token K_disable K_fork
@@ -697,6 +697,9 @@ statement
697 697 | K_TRANIF1 T_SYMBOL ',' T_SYMBOL T_SYMBOL ',' T_SYMBOL ';'
698 698 { compile_island_tranif(1, $2, $4, $5, $7); }
699 699
  700 + | K_TRANVP T_NUMBER T_NUMBER T_NUMBER ',' T_SYMBOL ',' T_SYMBOL T_SYMBOL ';'
  701 + { compile_island_tranvp($6, $8, $9, $2, $3, $4); }
  702 +
700 703 /* Oh and by the way, empty statements are OK as well. */
701 704
702 705 | ';'
185 vvp/vvp_island.cc
@@ -166,6 +166,7 @@ struct vvp_island_branch {
166 166 bool enabled_flag;
167 167 vvp_net_t*en;
168 168 int flags;
  169 + unsigned width, part, offset;
169 170 };
170 171
171 172 /*
@@ -321,7 +322,7 @@ bool vvp_island_branch::run_test_enabled()
321 322 {
322 323 flags = 0;
323 324
324   - vvp_island_port*ep = dynamic_cast<vvp_island_port*> (en->fun);
  325 + vvp_island_port*ep = en? dynamic_cast<vvp_island_port*> (en->fun) : 0;
325 326
326 327 // If there is no ep port (no "enabled" input) then this is a
327 328 // tran branch. Assume it is always enabled.
@@ -343,63 +344,138 @@ bool vvp_island_branch::run_test_enabled()
343 344 return true;
344 345 }
345 346
346   -void collect_connections(list<vvp_net_t*>&connections, vvp_branch_ptr_t cur)
  347 +static vvp_branch_ptr_t next(vvp_branch_ptr_t cur)
347 348 {
348 349 vvp_island_branch*ptr = cur.ptr();
349 350 unsigned ab = cur.port();
350   - unsigned other_ab = ab^1;
  351 + return ptr->link[ab];
  352 +}
351 353
352   - int ab_mask = 1 << ab;
  354 +static void collect_node(list<vvp_branch_ptr_t>&conn, vvp_branch_ptr_t cur)
  355 +{
  356 + conn .push_back(cur);
  357 + for (vvp_branch_ptr_t idx = next(cur) ; idx != cur ; idx = next(idx))
  358 + conn.push_back(idx);
  359 +}
353 360
354   - if ( (ptr->flags&ab_mask) != 0)
355   - return;
  361 +static vvp_vector8_t get_value(vvp_net_t*net)
  362 +{
  363 + vvp_island_port*fun = dynamic_cast<vvp_island_port*>(net->fun);
  364 + return fun->invalue;
  365 +}
  366 +
  367 +static vvp_vector8_t get_value_from_branch(vvp_branch_ptr_t cur)
  368 +{
  369 + vvp_island_branch*ptr = cur.ptr();
  370 + unsigned ab = cur.port();
  371 + unsigned ab_other = ab^1;
  372 +
  373 + // If the branch link is disabled, return nil.
  374 + if (ptr->enabled_flag == false)
  375 + return vvp_vector8_t();
  376 +
  377 + // If the branch other side is already visited, return nil.
  378 + if (ptr->flags & (1<<ab_other))
  379 + return vvp_vector8_t();
356 380
357   - ptr->flags |= ab_mask;
358   - connections.push_back( ab? ptr->b : ptr->a );
  381 + vvp_branch_ptr_t other (ptr, ab_other);
359 382
360   - if (ptr->enabled_flag)
361   - collect_connections(connections, vvp_branch_ptr_t(ptr, other_ab));
362   - collect_connections(connections, ptr->link[ab]);
  383 + // Other side net, and port value.
  384 + vvp_net_t*net = ab? ptr->a : ptr->b;
  385 + vvp_vector8_t val_other = get_value(net);
  386 +
  387 + // Temporarily mark as visited.
  388 + ptr->flags |= 1<<ab_other;
  389 +
  390 + // recurse
  391 + list<vvp_branch_ptr_t> connections;
  392 + collect_node(connections, other);
  393 +
  394 + for (list<vvp_branch_ptr_t>::iterator idx = connections.begin()
  395 + ; idx != connections.end() ; idx ++ ) {
  396 + vvp_vector8_t tmp = get_value_from_branch(*idx);
  397 + if (val_other.size() == 0)
  398 + val_other = tmp;
  399 + else if (tmp.size() != 0)
  400 + val_other = resolve(val_other, tmp);
  401 + }
  402 +
  403 + // Remove visited flag
  404 + ptr->flags &= ~(1<<ab_other);
  405 +
  406 + if (val_other.size() == 0)
  407 + return val_other;
  408 +
  409 + if (ptr->width) {
  410 + if (ab == 0) {
  411 + val_other = part_expand(val_other, ptr->width, ptr->offset);
  412 + } else {
  413 + val_other = val_other.subvalue(ptr->offset, ptr->part);
  414 + }
  415 + }
  416 +
  417 + return val_other;
363 418 }
364   -
  419 +
365 420 void vvp_island_branch::run_resolution()
366 421 {
367   - if ( (flags&1) == 0) {
368   - list<vvp_net_t*>collection;
369   - collect_connections(collection, vvp_branch_ptr_t(this, 0));
370   - vvp_vector8_t tmp;
371   - for (list<vvp_net_t*>::iterator cur = collection.begin()
372   - ; cur != collection.end() ; cur ++ ) {
373   - vvp_island_port*fun = dynamic_cast<vvp_island_port*>((*cur)->fun);
374   - if (tmp.size() == 0)
375   - tmp = fun->invalue;
376   - else if (fun->invalue.size() != 0)
377   - tmp = resolve(tmp, fun->invalue);
378   - }
  422 + // Collect all the branch endpoints that are joined to my A
  423 + // side.
  424 + list<vvp_branch_ptr_t> connections;
  425 + collect_node(connections, vvp_branch_ptr_t(this, 0));
  426 +
  427 + // Mark my A side as done. Do this early to prevent recursing
  428 + // back.
  429 + flags |= 1;
  430 +
  431 + // Prime the resolution with the port value for this node.
  432 + vvp_vector8_t val = get_value(a);
  433 +
  434 + // Now scan the other sides of all the branches connected to
  435 + // my A side. The get_value_from_branch() will recurse as
  436 + // necessary to depth-first walk the graph.
  437 + for (list<vvp_branch_ptr_t>::iterator idx = connections.begin()
  438 + ; idx != connections.end() ; idx ++ ) {
  439 + vvp_vector8_t tmp = get_value_from_branch(*idx);
  440 + if (val.size() == 0)
  441 + val = tmp;
  442 + else if (tmp.size() != 0)
  443 + val = resolve(val, tmp);
  444 + }
  445 +
  446 + // A side is done.
  447 + vvp_send_vec8(a->out, val);
  448 +
  449 + flags &= ~1;
379 450
380   - for (list<vvp_net_t*>::iterator cur = collection.begin()
381   - ; cur != collection.end() ; cur ++ )
382   - vvp_send_vec8((*cur)->out, tmp);
  451 + // If this is a connected branch without a part select, then
  452 + // we know from the start that the other side has the same
  453 + // value as this. Mark it and finish.
  454 + if (enabled_flag && width==0) {
  455 + vvp_send_vec8(b->out, val);
  456 + return;
383 457 }
384 458
385   - if ( (flags&2) == 0) {
386   - list<vvp_net_t*>collection;
387   - collect_connections(collection, vvp_branch_ptr_t(this, 1));
388   - vvp_vector8_t tmp;
389   - for (list<vvp_net_t*>::iterator cur = collection.begin()
390   - ; cur != collection.end() ; cur ++ ) {
391   - vvp_island_port*fun = dynamic_cast<vvp_island_port*>((*cur)->fun);
392   - if (tmp.size() == 0)
393   - tmp = fun->invalue;
394   - else if (fun->invalue.size() != 0)
395   - tmp = resolve(tmp, fun->invalue);
396   - }
  459 + // Repeat the above for the B side.
  460 +
  461 + connections.clear();
  462 + collect_node(connections, vvp_branch_ptr_t(this, 1));
397 463
398   - for (list<vvp_net_t*>::iterator cur = collection.begin()
399   - ; cur != collection.end() ; cur ++ )
400   - vvp_send_vec8((*cur)->out, tmp);
  464 + flags |= 2;
  465 +
  466 + val = get_value(b);
  467 +
  468 + for (list<vvp_branch_ptr_t>::iterator idx = connections.begin()
  469 + ; idx != connections.end() ; idx ++ ) {
  470 + vvp_vector8_t tmp = get_value_from_branch(*idx);
  471 + if (val.size() == 0)
  472 + val = tmp;
  473 + else if (tmp.size() != 0)
  474 + val = resolve(val, tmp);
401 475 }
402 476
  477 + flags &= ~2;
  478 + vvp_send_vec8(b->out, val);
403 479 }
404 480
405 481 /* **** COMPILE/LINK SUPPORT **** */
@@ -502,6 +578,31 @@ void compile_island_tranif(int sense, char*island, char*pa, char*pb, char*pe)
502 578 free(pe);
503 579 }
504 580
  581 + br->width = 0;
  582 + br->part = 0;
  583 + br->offset = 0;
  584 +
  585 + use_island->add_branch(br, pa, pb);
  586 +
  587 + free(pa);
  588 + free(pb);
  589 +}
  590 +
  591 +void compile_island_tranvp(char*island, char*pa, char*pb,
  592 + unsigned wid, unsigned par, unsigned off)
  593 +{
  594 + assert(island_table);
  595 + vvp_island*use_island = island_table->sym_get_value(island);
  596 + assert(use_island);
  597 + free(island);
  598 +
  599 + vvp_island_branch*br = new vvp_island_branch;
  600 + br->active_high = false;
  601 + br->en = 0;
  602 + br->width = wid;
  603 + br->part = par;
  604 + br->offset = off;
  605 +
505 606 use_island->add_branch(br, pa, pb);
506 607
507 608 free(pa);
2  vvp/vvp_net.h
@@ -556,7 +556,7 @@ class vvp_vector8_t {
556 556
557 557 unsigned size() const { return size_; }
558 558 vvp_scalar_t value(unsigned idx) const;
559   - vvp_vector8_t subvalue(unsigned idx, unsigned size) const;
  559 + vvp_vector8_t subvalue(unsigned adr, unsigned width) const;
560 560 void set_bit(unsigned idx, vvp_scalar_t val);
561 561
562 562 // Test that the vectors are exactly equal

0 comments on commit 73e2b29

Please sign in to comment.
Something went wrong with that request. Please try again.