diff --git a/expr_synth.cc b/expr_synth.cc index 37946f60a..ba5562017 100644 --- a/expr_synth.cc +++ b/expr_synth.cc @@ -184,22 +184,22 @@ NetNet* NetEBBits::synthesize(Design*des, NetScope*scope, NetExpr*root) switch (op()) { case '&': - gate = new NetLogic(scope, oname, 3, NetLogic::AND, width); + gate = new NetLogic(scope, oname, 3, NetLogic::AND, width, true); break; case 'A': - gate = new NetLogic(scope, oname, 3, NetLogic::NAND, width); + gate = new NetLogic(scope, oname, 3, NetLogic::NAND, width, true); break; case '|': - gate = new NetLogic(scope, oname, 3, NetLogic::OR, width); + gate = new NetLogic(scope, oname, 3, NetLogic::OR, width, true); break; case '^': - gate = new NetLogic(scope, oname, 3, NetLogic::XOR, width); + gate = new NetLogic(scope, oname, 3, NetLogic::XOR, width, true); break; case 'O': - gate = new NetLogic(scope, oname, 3, NetLogic::NOR, width); + gate = new NetLogic(scope, oname, 3, NetLogic::NOR, width, true); break; case 'X': - gate = new NetLogic(scope, oname, 3, NetLogic::XNOR, width); + gate = new NetLogic(scope, oname, 3, NetLogic::XNOR, width, true); break; default: gate = NULL; @@ -286,7 +286,7 @@ NetNet* NetEBComp::synthesize(Design*des, NetScope*scope, NetExpr*root) operation. Make an XNOR gate instead of a comparator. */ if ((width == 1) && (op_ == 'e') && !real_args) { NetLogic*gate = new NetLogic(scope, scope->local_symbol(), - 3, NetLogic::XNOR, 1); + 3, NetLogic::XNOR, 1, true); gate->set_line(*this); connect(gate->pin(0), osig->pin(0)); connect(gate->pin(1), lsig->pin(0)); @@ -300,7 +300,7 @@ NetNet* NetEBComp::synthesize(Design*des, NetScope*scope, NetExpr*root) an XOR instead of an XNOR gate. */ if ((width == 1) && (op_ == 'n') && !real_args) { NetLogic*gate = new NetLogic(scope, scope->local_symbol(), - 3, NetLogic::XOR, 1); + 3, NetLogic::XOR, 1, true); gate->set_line(*this); connect(gate->pin(0), osig->pin(0)); connect(gate->pin(1), lsig->pin(0)); @@ -520,11 +520,12 @@ NetNet* NetEBLogic::synthesize(Design*des, NetScope*scope, NetExpr*root) if (lsig == 0 || rsig == 0) return 0; - /* You cannot currently do logical operations on real values. */ + /* Any real value should have already been converted to a bit value. */ if (lsig->data_type() == IVL_VT_REAL || rsig->data_type() == IVL_VT_REAL) { - cerr << get_fileline() << ": sorry: " << human_readable_op(op_) - << " is currently unsupported for real values." << endl; + cerr << get_fileline() << ": internal error: " + << human_readable_op(op_) + << " is missing real to bit conversion." << endl; des->errors += 1; return 0; } @@ -535,60 +536,30 @@ NetNet* NetEBLogic::synthesize(Design*des, NetScope*scope, NetExpr*root) osig->data_type(expr_type()); osig->local_flag(true); + NetLogic*olog; + perm_string oname = scope->local_symbol(); + /* Create the logic OR/AND gate. This has a single bit output, + * with single bit inputs for the two operands. */ if (op() == 'o') { - - /* Logic OR can handle the reduction *and* the logical - comparison with a single wide OR gate. So handle this - magically. */ - - perm_string oname = scope->local_symbol(); - - NetLogic*olog = new NetLogic(scope, oname, - lsig->pin_count()+rsig->pin_count()+1, - NetLogic::OR, 1); - olog->set_line(*this); - - connect(osig->pin(0), olog->pin(0)); - - unsigned pin = 1; - for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx = 1) - connect(olog->pin(pin+idx), lsig->pin(idx)); - - pin += lsig->pin_count(); - for (unsigned idx = 0 ; idx < rsig->pin_count() ; idx = 1) - connect(olog->pin(pin+idx), rsig->pin(idx)); - - des->add_node(olog); - + olog = new NetLogic(scope, oname, 3, NetLogic::OR, 1, true); } else { assert(op() == 'a'); - - /* Create the logic AND gate. This is a single bit - output, with inputs for each of the operands. */ - NetLogic*olog; - perm_string oname = scope->local_symbol(); - - olog = new NetLogic(scope, oname, 3, NetLogic::AND, 1); - olog->set_line(*this); - - connect(osig->pin(0), olog->pin(0)); - des->add_node(olog); - - /* XXXX Here, I need to reduce the parameters with - reduction or. */ - - - /* By this point, the left and right parameters have been - reduced to single bit values. Now we just connect them to - the logic gate. */ - assert(lsig->pin_count() == 1); - connect(lsig->pin(0), olog->pin(1)); - - assert(rsig->pin_count() == 1); - connect(rsig->pin(0), olog->pin(2)); + olog = new NetLogic(scope, oname, 3, NetLogic::AND, 1, true); } + olog->set_line(*this); + des->add_node(olog); + + connect(osig->pin(0), olog->pin(0)); + + /* The left and right operands have already been reduced to a + * single bit value, so just connect then to the logic gate. */ + assert(lsig->pin_count() == 1); + connect(lsig->pin(0), olog->pin(1)); + + assert(rsig->pin_count() == 1); + connect(rsig->pin(0), olog->pin(2)); return osig; } @@ -879,7 +850,7 @@ NetNet* NetEUBits::synthesize(Design*des, NetScope*scope, NetExpr*root) switch (op()) { case '~': - gate = new NetLogic(scope, oname, 2, NetLogic::NOT, width); + gate = new NetLogic(scope, oname, 2, NetLogic::NOT, width, true); gate->set_line(*this); break; default: diff --git a/ivl.def b/ivl.def index d44386270..311569ce5 100644 --- a/ivl.def +++ b/ivl.def @@ -92,6 +92,7 @@ ivl_logic_delay ivl_logic_drive0 ivl_logic_drive1 ivl_logic_file +ivl_logic_is_cassign ivl_logic_lineno ivl_logic_name ivl_logic_pin diff --git a/ivl_target.h b/ivl_target.h index cba9aa05a..ee339b64e 100644 --- a/ivl_target.h +++ b/ivl_target.h @@ -996,6 +996,7 @@ extern ivl_expr_t ivl_logic_delay(ivl_net_logic_t net, unsigned transition); extern ivl_drive_t ivl_logic_drive0(ivl_net_logic_t net); extern ivl_drive_t ivl_logic_drive1(ivl_net_logic_t net); extern unsigned ivl_logic_width(ivl_net_logic_t net); +extern unsigned ivl_logic_is_cassign(ivl_net_logic_t net); /* DEPRECATED */ extern const char* ivl_logic_attr(ivl_net_logic_t net, const char*key); diff --git a/netlist.cc b/netlist.cc index 6af72c71d..9adca5dcc 100644 --- a/netlist.cc +++ b/netlist.cc @@ -2441,8 +2441,8 @@ ivl_variable_type_t NetECast::expr_type() const } NetLogic::NetLogic(NetScope*s, perm_string n, unsigned pins, - TYPE t, unsigned wid) -: NetNode(s, n, pins), type_(t), width_(wid) + TYPE t, unsigned wid, bool is_cassign__) +: NetNode(s, n, pins), type_(t), width_(wid), is_cassign_(is_cassign__) { pin(0).set_dir(Link::OUTPUT); for (unsigned idx = 1 ; idx < pins ; idx += 1) { @@ -2460,6 +2460,11 @@ unsigned NetLogic::width() const return width_; } +bool NetLogic::is_cassign() const +{ + return is_cassign_; +} + NetUReduce::NetUReduce(NetScope*scope__, perm_string n, NetUReduce::TYPE t, unsigned wid) : NetNode(scope__, n, 2), type_(t), width_(wid) diff --git a/netlist.h b/netlist.h index a182f6bbd..d10469d8c 100644 --- a/netlist.h +++ b/netlist.h @@ -2008,10 +2008,11 @@ class NetLogic : public NetNode { PMOS, XNOR, XOR }; explicit NetLogic(NetScope*s, perm_string n, unsigned pins, - TYPE t, unsigned wid); + TYPE t, unsigned wid, bool is_cassign__=false); TYPE type() const; unsigned width() const; + bool is_cassign() const; virtual void dump_node(ostream&, unsigned ind) const; virtual bool emit_node(struct target_t*) const; @@ -2020,6 +2021,7 @@ class NetLogic : public NetNode { private: TYPE type_; unsigned width_; + bool is_cassign_; }; /* diff --git a/t-dll-api.cc b/t-dll-api.cc index c04be3e66..206943f1a 100644 --- a/t-dll-api.cc +++ b/t-dll-api.cc @@ -747,6 +747,12 @@ extern "C" unsigned ivl_logic_lineno(ivl_net_logic_t net) return net->lineno; } +extern "C" unsigned ivl_logic_is_cassign(ivl_net_logic_t net) +{ + assert(net); + return net->is_cassign; +} + extern "C" const char* ivl_logic_attr(ivl_net_logic_t net, const char*key) { assert(net); diff --git a/t-dll.cc b/t-dll.cc index 1378539c8..e45c70d20 100644 --- a/t-dll.cc +++ b/t-dll.cc @@ -759,6 +759,7 @@ bool dll_target::bufz(const NetBUFZ*net) obj->type_ = net->transparent()? IVL_LO_BUFT : IVL_LO_BUFZ; obj->width_= net->width(); + obj->is_cassign = 0; obj->npins_= 2; obj->pins_ = new ivl_nexus_t[2]; FILE_NAME(obj, net); @@ -920,6 +921,9 @@ void dll_target::logic(const NetLogic*net) obj->type_ = IVL_LO_NONE; break; } + /* Some of the logical gates are used to represent operators in a + * continuous assignment, so set a flag if that is the case. */ + obj->is_cassign = net->is_cassign(); /* Connect all the ivl_nexus_t objects to the pins of the device. */ @@ -1273,6 +1277,7 @@ void dll_target::udp(const NetUDP*net) /* The NetUDP class hasn't learned about width yet, so we assume a width of 1. */ obj->width_ = 1; + obj->is_cassign = 0; static map udps; ivl_udp_t u; @@ -2352,7 +2357,7 @@ void dll_target::convert_module_ports(const NetScope*net) ivl_signal_t sig = find_signal(des_, nets[idx]); scop->u_.nex[idx] = nexus_sig_make(sig, 0); } - delete nets; + delete [] nets; } } diff --git a/t-dll.h b/t-dll.h index 6bd4448d4..f447acd6a 100644 --- a/t-dll.h +++ b/t-dll.h @@ -476,6 +476,7 @@ struct ivl_net_const_s { struct ivl_net_logic_s { ivl_logic_t type_; unsigned width_; + unsigned is_cassign; ivl_udp_t udp; perm_string name_;