Permalink
Browse files

Add a routine to say if a logical came from a CA and some other fixes.

This patch adds code that allows the targets to determine if a logical
gate came from a continuous assignment. This helps some of the targets
generate code that more closely matches the input.

It also reworks/simplifies the synthesis of && and || since the
compiler has already converted the two operands to single bit form
and fixes a mismatched delete from a previous patch.
  • Loading branch information...
caryr authored and steveicarus committed Mar 22, 2011
1 parent ceaa79e commit eb0df40a7327f8183a7d7d7d24109bec29acb95c
Showing with 54 additions and 62 deletions.
  1. +29 −58 expr_synth.cc
  2. +1 −0 ivl.def
  3. +1 −0 ivl_target.h
  4. +7 −2 netlist.cc
  5. +3 −1 netlist.h
  6. +6 −0 t-dll-api.cc
  7. +6 −1 t-dll.cc
  8. +1 −0 t-dll.h
View
@@ -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');
+ olog = new NetLogic(scope, oname, 3, NetLogic::AND, 1, true);
+ }
- /* 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. */
-
+ olog->set_line(*this);
+ des->add_node(olog);
- /* 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));
+ connect(osig->pin(0), olog->pin(0));
- assert(rsig->pin_count() == 1);
- connect(rsig->pin(0), olog->pin(2));
- }
+ /* 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:
View
@@ -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
View
@@ -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);
View
@@ -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)
View
@@ -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_;
};
/*
View
@@ -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);
View
@@ -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<perm_string,ivl_udp_t> 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;
}
}
View
@@ -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_;

0 comments on commit eb0df40

Please sign in to comment.