Skip to content
Browse files

Collapse concatenation of constants into concatenated constant.

  • Loading branch information...
1 parent 367d7bf commit 679ef3a38018319c59aa2d7c4a4692eb0e1e9151 @steveicarus committed
Showing with 119 additions and 33 deletions.
  1. +45 −3 cprop.cc
  2. +1 −3 design_dump.cc
  3. +9 −0 functor.cc
  4. +3 −0 functor.h
  5. +44 −0 link_const.cc
  6. +3 −22 netlist.cc
  7. +6 −5 netlist.h
  8. +7 −0 verinum.cc
  9. +1 −0 verinum.h
View
48 cprop.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998-2010 Stephen Williams (steve@icarus.com)
+ * Copyright (c) 1998-2010,2012 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -43,12 +43,14 @@ struct cprop_functor : public functor_t {
virtual void signal(Design*des, NetNet*obj);
virtual void lpm_add_sub(Design*des, NetAddSub*obj);
virtual void lpm_compare(Design*des, NetCompare*obj);
- virtual void lpm_compare_eq_(Design*des, NetCompare*obj);
+ virtual void lpm_concat(Design*des, NetConcat*obj);
virtual void lpm_ff(Design*des, NetFF*obj);
virtual void lpm_logic(Design*des, NetLogic*obj);
virtual void lpm_mux(Design*des, NetMux*obj);
virtual void lpm_part_select(Design*des, NetPartSelect*obj);
-};
+
+ void lpm_compare_eq_(Design*des, NetCompare*obj);
+ };
void cprop_functor::signal(Design*, NetNet*)
{
@@ -76,6 +78,45 @@ void cprop_functor::lpm_compare_eq_(Design*, NetCompare*)
{
}
+void cprop_functor::lpm_concat(Design*des, NetConcat*obj)
+{
+ verinum result (verinum::Vz, obj->width());
+ unsigned off = 0;
+
+ for (unsigned idx = 1 ; idx < obj->pin_count() ; idx += 1) {
+ Nexus*nex = obj->pin(idx).nexus();
+ // If there are non-constant drivers, then give up.
+ if (! nex->drivers_constant())
+ return;
+
+ verinum tmp = nex->driven_vector();
+ result.set(off, tmp);
+ off += tmp.len();
+ }
+
+ if (debug_optimizer)
+ cerr << obj->get_fileline() << ": cprop_functor::lpm_concat: "
+ << "Replace NetConcat with " << result << "." << endl;
+
+
+ NetScope*scope = obj->scope();
+
+ // Create a NetConst object to carry the result. Give it the
+ // same name as the Concat object that we are replacing, and
+ // link the NetConst to the NetConcat object. Then delete the
+ // concat that is now replaced.
+ NetConst*result_obj = new NetConst(scope, obj->name(), result);
+ result_obj->set_line(*obj);
+ des->add_node(result_obj);
+ connect(obj->pin(0), result_obj->pin(0));
+
+ // Note that this will leave the const inputs to dangle. They
+ // will be reaped by other passes of cprop_functor.
+ delete obj;
+
+ count += 1;
+}
+
void cprop_functor::lpm_ff(Design*, NetFF*obj)
{
// Look for and count unlinked FF outputs. Note that if the
@@ -256,6 +297,7 @@ void cprop_functor::lpm_part_select(Design*des, NetPartSelect*obj)
NetConcat*concat = new NetConcat(scope, scope->local_symbol(),
sig_width, part_count);
+ concat->set_line(*obj);
des->add_node(concat);
connect(concat->pin(0), obj->pin(1));
View
4 design_dump.cc
@@ -519,9 +519,7 @@ void NetCaseCmp::dump_node(ostream&o, unsigned ind) const
void NetConst::dump_node(ostream&o, unsigned ind) const
{
- o << setw(ind) << "" << "constant " << width_ << "'b";
- for (unsigned idx = width_ ; idx > 0 ; idx -= 1)
- o << value_[idx-1];
+ o << setw(ind) << "" << "constant " << value_;
o << ": " << name();
if (rise_time())
o << " #(" << *rise_time()
View
9 functor.cc
@@ -54,6 +54,10 @@ void functor_t::lpm_compare(Design*, NetCompare*)
{
}
+void functor_t::lpm_concat(Design*, NetConcat*)
+{
+}
+
void functor_t::lpm_const(Design*, NetConst*)
{
}
@@ -191,6 +195,11 @@ void NetCompare::functor_node(Design*des, functor_t*fun)
fun->lpm_compare(des, this);
}
+void NetConcat::functor_node(Design*des, functor_t*fun)
+{
+ fun->lpm_concat(des, this);
+}
+
void NetConst::functor_node(Design*des, functor_t*fun)
{
fun->lpm_const(des, this);
View
3 functor.h
@@ -57,6 +57,9 @@ struct functor_t {
/* This method is called for each structural comparator. */
virtual void lpm_compare(class Design*des, class NetCompare*);
+ /* This method is called for each structural concatenation. */
+ virtual void lpm_concat(class Design*des, class NetConcat*);
+
/* This method is called for each structural constant. */
virtual void lpm_const(class Design*des, class NetConst*);
View
44 link_const.cc
@@ -21,6 +21,7 @@
# include "netlist.h"
# include "netmisc.h"
+# include "ivl_assert.h"
/*
* Scan the link for drivers. If there are only constant drivers, then
@@ -172,3 +173,46 @@ verinum::V Nexus::driven_value() const
return val;
}
+
+verinum Nexus::driven_vector() const
+{
+ const Link*cur = list_;
+
+ verinum val;
+
+ for (cur = first_nlink() ; cur ; cur = cur->next_nlink()) {
+
+ const NetConst*obj;
+ const NetNet*sig;
+ if ((obj = dynamic_cast<const NetConst*>(cur->get_obj()))) {
+ ivl_assert(*obj, cur->get_pin() == 0);
+ val = obj->value();
+
+ } else if ((sig = dynamic_cast<const NetNet*>(cur->get_obj()))) {
+
+ // If we find an attached SUPPLY0/1, the we know
+ // from that what the driven value is. Stop now.
+ if (sig->type() == NetNet::SUPPLY0) {
+ driven_ = V0;
+ return verinum(verinum::V0, sig->vector_width());
+ }
+ if (sig->type() == NetNet::SUPPLY1) {
+ driven_ = V1;
+ return verinum(verinum::V1, sig->vector_width());
+ }
+
+ // If we find an attached TRI0/1, then this is a
+ // good guess for the driven value, but keep
+ // looking for something better.
+ if (sig->type() == NetNet::TRI0) {
+ val = verinum(verinum::V0, sig->vector_width());
+ }
+ if (sig->type() == NetNet::TRI1) {
+ val = verinum(verinum::V1, sig->vector_width());
+ }
+ }
+ }
+
+ return val;
+}
+
View
25 netlist.cc
@@ -2008,46 +2008,27 @@ NetProc* NetCondit::else_clause()
}
NetConst::NetConst(NetScope*s, perm_string n, verinum::V v)
-: NetNode(s, n, 1), width_(1)
+: NetNode(s, n, 1), value_(v, 1)
{
pin(0).set_dir(Link::OUTPUT);
- value_ = new verinum::V[1];
- value_[0] = v;
- is_string_ = false;
}
NetConst::NetConst(NetScope*s, perm_string n, const verinum&val)
-: NetNode(s, n, 1), width_(val.len())
+: NetNode(s, n, 1), value_(val)
{
pin(0).set_dir(Link::OUTPUT);
- value_ = new verinum::V[width_];
- for (unsigned idx = 0 ; idx < width_ ; idx += 1) {
- value_[idx] = val.get(idx);
- }
- is_string_ = val.is_string();
}
NetConst::~NetConst()
{
- delete[]value_;
}
verinum::V NetConst::value(unsigned idx) const
{
- assert(idx < width_);
+ assert(idx < width());
return value_[idx];
}
-unsigned NetConst::width() const
-{
- return width_;
-}
-
-bool NetConst::is_string() const
-{
- return is_string_;
-}
-
NetFuncDef::NetFuncDef(NetScope*s, NetNet*result, const vector<NetNet*>&po)
: scope_(s), statement_(0), result_sig_(result), ports_(po)
{
View
11 netlist.h
@@ -379,6 +379,7 @@ class Nexus {
/* Given the nexus has constant drivers, this method returns
the value that has been driven. */
verinum::V driven_value() const;
+ verinum driven_vector() const;
/* The code generator sets an ivl_nexus_t to attach code
generation details to the nexus. */
@@ -1350,6 +1351,7 @@ class NetConcat : public NetNode {
void dump_node(ostream&, unsigned ind) const;
bool emit_node(struct target_t*) const;
+ void functor_node(Design*des, functor_t*fun);
private:
unsigned width_;
@@ -2095,18 +2097,17 @@ class NetConst : public NetNode {
explicit NetConst(NetScope*s, perm_string n, const verinum&val);
~NetConst();
+ inline const verinum&value(void) const { return value_; }
verinum::V value(unsigned idx) const;
- unsigned width() const;
- bool is_string() const;
+ inline unsigned width() const { return value_.len(); }
+ inline bool is_string() const { return value_.is_string(); }
virtual bool emit_node(struct target_t*) const;
virtual void functor_node(Design*, functor_t*);
virtual void dump_node(ostream&, unsigned ind) const;
private:
- unsigned width_;
- verinum::V*value_;
- bool is_string_;
+ verinum value_;
};
/*
View
7 verinum.cc
@@ -367,6 +367,13 @@ verinum::V verinum::set(unsigned idx, verinum::V val)
return bits_[idx] = val;
}
+void verinum::set(unsigned off, const verinum&val)
+{
+ assert(off + val.len() <= nbits_);
+ for (unsigned idx = 0 ; idx < val.len() ; idx += 1)
+ bits_[off+idx] = val[idx];
+}
+
unsigned long verinum::as_ulong() const
{
if (nbits_ == 0)
View
1 verinum.h
@@ -90,6 +90,7 @@ class verinum {
// methods.
V get(unsigned idx) const;
V set(unsigned idx, V val);
+ void set(unsigned idx, const verinum&val);
V operator[] (unsigned idx) const { return get(idx); }

0 comments on commit 679ef3a

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