[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

gEDA: Verilog: ternary patch



I got tired of replacing ternary expressions with if statements---here
is an elaborator.  I've checked the 64-entry truth table, and it seems
okay, but some of the internals I don't quite understand (what does
local_flag mean?).  The aim was to do pretty much what the other functions
do; there may be some wrong guesses.

Also there is multibit ==, !=, ~, ~|, !, and reduction | and ^, mostly
untested.  It's against 19990903.

Cheers,
Peter Monta   pmonta@imedia.com
Imedia Corp.

--- verilog-19990903-orig/elaborate.cc	Thu Sep  2 21:28:38 1999
+++ verilog-19990903/elaborate.cc	Thu Sep  9 04:01:25 1999
@@ -640,6 +640,7 @@
 
       NetNet*osig;
       NetNode*gate;
+      NetNode*gate_t;
 
       switch (op_) {
 	  case '^': // XOR
@@ -653,6 +654,9 @@
 		  connect(gate->pin(1), lsig->pin(idx));
 		  connect(gate->pin(2), rsig->pin(idx));
 		  connect(gate->pin(0), osig->pin(idx));
+		  gate->rise_time(rise);
+		  gate->fall_time(fall);
+		  gate->decay_time(decay);
 		  des->add_node(gate);
 	    }
 	    des->add_signal(osig);
@@ -669,6 +673,9 @@
 		  connect(gate->pin(1), lsig->pin(idx));
 		  connect(gate->pin(2), rsig->pin(idx));
 		  connect(gate->pin(0), osig->pin(idx));
+		  gate->rise_time(rise);
+		  gate->fall_time(fall);
+		  gate->decay_time(decay);
 		  des->add_node(gate);
 	    }
 	    des->add_signal(osig);
@@ -685,34 +692,57 @@
 		  connect(gate->pin(1), lsig->pin(idx));
 		  connect(gate->pin(2), rsig->pin(idx));
 		  connect(gate->pin(0), osig->pin(idx));
+		  gate->rise_time(rise);
+		  gate->fall_time(fall);
+		  gate->decay_time(decay);
 		  des->add_node(gate);
 	    }
 	    des->add_signal(osig);
 	    break;
 
 	  case 'e': // ==
-	    assert(lsig->pin_count() == 1);
-	    assert(rsig->pin_count() == 1);
-	    gate = new NetLogic(des->local_symbol(path), 3, NetLogic::XNOR);
-	    connect(gate->pin(1), lsig->pin(0));
-	    connect(gate->pin(2), rsig->pin(0));
+	    assert(lsig->pin_count() == rsig->pin_count());
 	    osig = new NetNet(des->local_symbol(path), NetNet::WIRE);
 	    osig->local_flag(true);
+	    gate = new NetLogic(des->local_symbol(path),
+				1+lsig->pin_count(),
+				NetLogic::AND);
 	    connect(gate->pin(0), osig->pin(0));
+	    for (unsigned idx = 0 ;  idx < lsig->pin_count() ;  idx += 1) {
+		  gate_t = new NetLogic(des->local_symbol(path), 3,
+				        NetLogic::XNOR);
+		  connect(gate_t->pin(1), lsig->pin(idx));
+		  connect(gate_t->pin(2), rsig->pin(idx));
+		  connect(gate_t->pin(0), gate->pin(idx));
+		  des->add_node(gate_t);
+	    }
 	    des->add_signal(osig);
+	    gate->rise_time(rise);
+	    gate->fall_time(fall);
+	    gate->decay_time(decay);
 	    des->add_node(gate);
 	    break;
 
 	  case 'n': // !=
-	    assert(lsig->pin_count() == 1);
-	    assert(rsig->pin_count() == 1);
-	    gate = new NetLogic(des->local_symbol(path), 3, NetLogic::XOR);
-	    connect(gate->pin(1), lsig->pin(0));
-	    connect(gate->pin(2), rsig->pin(0));
+	    assert(lsig->pin_count() == rsig->pin_count());
 	    osig = new NetNet(des->local_symbol(path), NetNet::WIRE);
 	    osig->local_flag(true);
+	    gate = new NetLogic(des->local_symbol(path),
+				1+lsig->pin_count(),
+				NetLogic::OR);
 	    connect(gate->pin(0), osig->pin(0));
+	    for (unsigned idx = 0 ;  idx < lsig->pin_count() ;  idx += 1) {
+		  gate_t = new NetLogic(des->local_symbol(path), 3,
+				        NetLogic::XOR);
+		  connect(gate_t->pin(1), lsig->pin(idx));
+		  connect(gate_t->pin(2), rsig->pin(idx));
+		  connect(gate_t->pin(0), gate->pin(idx));
+		  des->add_node(gate_t);
+	    }
 	    des->add_signal(osig);
+	    gate->rise_time(rise);
+	    gate->fall_time(fall);
+	    gate->decay_time(decay);
 	    des->add_node(gate);
 	    break;
 
@@ -733,6 +763,9 @@
 		}
 		gate = adder;
 		des->add_signal(osig);
+		gate->rise_time(rise);
+		gate->fall_time(fall);
+		gate->decay_time(decay);
 		des->add_node(gate);
 		break;
 	  }
@@ -742,10 +775,6 @@
 	    osig = 0;
       }
 
-      gate->rise_time(rise);
-      gate->fall_time(fall);
-      gate->decay_time(decay);
-
       if (NetTmp*tmp = dynamic_cast<NetTmp*>(lsig))
 	    delete tmp;
       if (NetTmp*tmp = dynamic_cast<NetTmp*>(rsig))
@@ -928,13 +957,67 @@
       return net;
 }
 
-NetNet* PETernary::elaborate_net(Design*des, const string&, unsigned long,
-				 unsigned long, unsigned long) const
-{
-      cerr << get_line() << ": Sorry, I cannot elaborate ?: as a net."
-	   << endl;
-      des->errors += 1;
-      return 0;
+NetNet* PETernary::elaborate_net(Design*des, const string&path,
+				 unsigned long rise,
+				 unsigned long fall,
+				 unsigned long decay) const
+{
+      NetNet* expr_sig = expr_->elaborate_net(des, path);
+      NetNet* tru_sig = tru_->elaborate_net(des, path);
+      NetNet* fal_sig = fal_->elaborate_net(des, path);
+      if (expr_sig == 0 || tru_sig == 0 || fal_sig == 0) {
+	    des->errors += 1;
+	    return 0;
+      }
+
+      NetNet* sig;
+      NetLogic*exprinv;
+      NetLogic*and_tru;
+      NetLogic*and_fal;
+      NetLogic*gate;
+
+      assert(tru_sig->pin_count() == fal_sig->pin_count());
+      assert(expr_sig->pin_count() == fal_sig->pin_count());
+
+      sig = new NetNet(des->local_symbol(path), NetNet::WIRE,
+		       tru_sig->pin_count());
+      sig->local_flag(true);
+
+      for (unsigned idx = 0 ;  idx < tru_sig->pin_count() ;  idx += 1) {
+	    exprinv = new NetLogic(des->local_symbol(path), 2, NetLogic::NOT);
+	    and_tru = new NetLogic(des->local_symbol(path), 3, NetLogic::AND);
+	    and_fal = new NetLogic(des->local_symbol(path), 3, NetLogic::AND);
+	    gate = new NetLogic(des->local_symbol(path), 3, NetLogic::OR);
+
+	    connect(exprinv->pin(1), expr_sig->pin(idx));
+	    connect(and_tru->pin(1), expr_sig->pin(idx));
+	    connect(and_fal->pin(1), exprinv->pin(0));
+	    connect(and_tru->pin(2), tru_sig->pin(idx));
+	    connect(and_fal->pin(2), fal_sig->pin(idx));
+	    connect(gate->pin(1), and_tru->pin(0));
+	    connect(gate->pin(2), and_fal->pin(0));
+	    connect(gate->pin(0), sig->pin(idx));
+
+	    des->add_node(exprinv);
+	    des->add_node(and_tru);
+	    des->add_node(and_fal);
+	    des->add_node(gate);
+
+	    gate->rise_time(rise);
+	    gate->fall_time(fall);
+	    gate->decay_time(decay);
+      }
+
+      des->add_signal(sig);
+
+      if (NetTmp*tmp = dynamic_cast<NetTmp*>(expr_sig))
+	    delete tmp;
+      if (NetTmp*tmp = dynamic_cast<NetTmp*>(tru_sig))
+	    delete tmp;
+      if (NetTmp*tmp = dynamic_cast<NetTmp*>(fal_sig))
+	    delete tmp;
+
+      return sig;
 }
 
 NetExpr*PETernary::elaborate_expr(Design*des, const string&path) const
@@ -963,14 +1046,38 @@
       NetLogic*gate;
       switch (op_) {
 	  case '~': // Bitwise NOT
-	    assert(sub_sig->pin_count() == 1);
+	    sig = new NetNet(des->local_symbol(path), NetNet::WIRE,
+			     sub_sig->pin_count());
+	    sig->local_flag(true);
+	    for (unsigned idx = 0 ;  idx < sub_sig->pin_count() ;  idx += 1) {
+		  gate = new NetLogic(des->local_symbol(path), 2,
+				      NetLogic::NOT);
+		  connect(gate->pin(1), sub_sig->pin(idx));
+		  connect(gate->pin(0), sig->pin(idx));
+		  des->add_node(gate);
+		  gate->rise_time(rise);
+		  gate->fall_time(fall);
+		  gate->decay_time(decay);
+	    }
+	    des->add_signal(sig);
+	    break;
+
+	  case 'N': // Reduction NOR
+	  case '!': // Reduction NOT
 	    sig = new NetNet(des->local_symbol(path), NetNet::WIRE);
 	    sig->local_flag(true);
-	    gate = new NetLogic(des->local_symbol(path), 2, NetLogic::NOT);
+	    gate = new NetLogic(des->local_symbol(path),
+				1+sub_sig->pin_count(),
+				NetLogic::NOR);
 	    connect(gate->pin(0), sig->pin(0));
-	    connect(gate->pin(1), sub_sig->pin(0));
+	    for (unsigned idx = 0 ;  idx < sub_sig->pin_count() ;  idx += 1)
+		  connect(gate->pin(idx+1), sub_sig->pin(idx));
+
 	    des->add_signal(sig);
 	    des->add_node(gate);
+	    gate->rise_time(rise);
+	    gate->fall_time(fall);
+	    gate->decay_time(decay);
 	    break;
 
 	  case '&': // Reduction AND
@@ -985,6 +1092,43 @@
 
 	    des->add_signal(sig);
 	    des->add_node(gate);
+	    gate->rise_time(rise);
+	    gate->fall_time(fall);
+	    gate->decay_time(decay);
+	    break;
+
+	  case '|': // Reduction OR
+	    sig = new NetNet(des->local_symbol(path), NetNet::WIRE);
+	    sig->local_flag(true);
+	    gate = new NetLogic(des->local_symbol(path),
+				1+sub_sig->pin_count(),
+				NetLogic::OR);
+	    connect(gate->pin(0), sig->pin(0));
+	    for (unsigned idx = 0 ;  idx < sub_sig->pin_count() ;  idx += 1)
+		  connect(gate->pin(idx+1), sub_sig->pin(idx));
+
+	    des->add_signal(sig);
+	    des->add_node(gate);
+	    gate->rise_time(rise);
+	    gate->fall_time(fall);
+	    gate->decay_time(decay);
+	    break;
+
+	  case '^': // Reduction XOR
+	    sig = new NetNet(des->local_symbol(path), NetNet::WIRE);
+	    sig->local_flag(true);
+	    gate = new NetLogic(des->local_symbol(path),
+				1+sub_sig->pin_count(),
+				NetLogic::XOR);
+	    connect(gate->pin(0), sig->pin(0));
+	    for (unsigned idx = 0 ;  idx < sub_sig->pin_count() ;  idx += 1)
+		  connect(gate->pin(idx+1), sub_sig->pin(idx));
+
+	    des->add_signal(sig);
+	    des->add_node(gate);
+	    gate->rise_time(rise);
+	    gate->fall_time(fall);
+	    gate->decay_time(decay);
 	    break;
 
 	  default:
@@ -992,10 +1136,6 @@
 	    sig = 0;
       }
 
-      gate->rise_time(rise);
-      gate->fall_time(fall);
-      gate->decay_time(decay);
-
       if (NetTmp*tmp = dynamic_cast<NetTmp*>(sub_sig))
 	    delete tmp;
 
@@ -1645,7 +1785,7 @@
 
 	// Well, I actually need to generate code to handle the
 	// conditional, so elaborate.
-      NetProc*i = if_->elaborate(des, path);
+      NetProc*i = if_? if_->elaborate(des, path) : 0;
       NetProc*e = else_? else_->elaborate(des, path) : 0;
 
       NetCondit*res = new NetCondit(expr, i, e);