Skip to content
Browse files

Blend NetPartSelect(PV) objects into NetConcat

If a signal s driven by multiple non-overlapping NetPartSelect(PV)
objects, then combine them into a single NetConcat object. This
eliminates the need for resolvers in the target.
  • Loading branch information...
1 parent a90e264 commit 367d7bf94bb0a098812317e95d88f9979c9ff9b5 @steveicarus committed Dec 19, 2012
Showing with 170 additions and 9 deletions.
  1. +138 −1 cprop.cc
  2. +11 −0 functor.cc
  3. +3 −1 functor.h
  4. +0 −5 netlist.cc
  5. +3 −2 netlist.h
  6. +14 −0 netmisc.cc
  7. +1 −0 netmisc.h
View
139 cprop.cc
@@ -19,13 +19,14 @@
# include "config.h"
+# include <algorithm>
+# include <vector>
# include <cstdlib>
# include "netlist.h"
# include "netmisc.h"
# include "functor.h"
# include "compiler.h"
# include "ivl_assert.h"
-# include <vector>
/*
@@ -46,6 +47,7 @@ struct cprop_functor : public functor_t {
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 cprop_functor::signal(Design*, NetNet*)
@@ -150,6 +152,141 @@ void cprop_functor::lpm_mux(Design*des, NetMux*obj)
count += 1;
}
+static bool compare_base(NetPartSelect*a, NetPartSelect*b)
+{
+ return a->base() < b->base();
+}
+
+/*
+ * This optimization searches for Nexa that are driven only by
+ * NetPartSelect(PV) outputs. These might turn from Verilog input that
+ * looks like this:
+ * wire [7:0] foo
+ * assign foo[7:4] = a;
+ * assign foo[3:0] = b;
+ * The idea is to convert the part selects of the above to a single
+ * concatenation that looks like this:
+ * assign foo = {a, b};
+ */
+void cprop_functor::lpm_part_select(Design*des, NetPartSelect*obj)
+{
+ if (obj->dir() != NetPartSelect::PV)
+ return;
+
+ NetScope*scope = obj->scope();
+ Nexus*nex = obj->pin(1).nexus();
+ vector<NetPartSelect*> obj_set;
+
+ for (Link*cur = nex->first_nlink() ; cur ; cur = cur->next_nlink()) {
+
+ // If this is an input (or passive) then ignore it.
+ if (cur->get_dir() != Link::OUTPUT)
+ continue;
+
+ // Check to see if this is the output of a
+ // NetPartSelect::PV. If not, then give up on the blend.
+ NetPins*tmp_obj = cur->get_obj();
+ unsigned tmp_pin = cur->get_pin();
+
+ NetPartSelect*cur_obj = dynamic_cast<NetPartSelect*> (tmp_obj);
+ if (cur_obj == 0)
+ return;
+
+ if (cur_obj->dir() != NetPartSelect::PV)
+ return;
+
+ if (tmp_pin != 1)
+ return;
+
+ obj_set.push_back(cur_obj);
+ }
+
+ if (obj_set.size() < 2)
+ return;
+
+ if (debug_optimizer)
+ cerr << obj->get_fileline() << ": cprop::lpm_part_select: "
+ << "Found " << obj_set.size() << " NetPartSelect(PV) objects."
+ << endl;
+
+ // Sort by increasing base offset.
+ sort(obj_set.begin(), obj_set.end(), compare_base);
+
+ // Check and make sure there are no overlaps. If there are,
+ // then give up on this optimization.
+ for (size_t idx = 1 ; idx < obj_set.size() ; idx += 1) {
+ unsigned top = obj_set[idx-1]->base() + obj_set[idx-1]->width();
+ if (top > obj_set[idx]->base()) {
+ if (debug_optimizer)
+ cerr << obj->get_fileline() << ": cprop::lpm_part_select: "
+ << "Range [" << obj_set[idx-1]->base()
+ << " " << top << ") overlaps PV starting at "
+ << obj_set[idx]->base() << ". Give up." << endl;
+ return;
+ }
+ }
+
+ // Check if the tail runs off the end of the target. If so it
+ // should be possible to replace it with a bit select to
+ // shorten the object for the target, but for now just give up.
+ unsigned sig_width = nex->vector_width();
+ if (obj_set.back()->base() + obj_set.back()->width() > sig_width) {
+ if (debug_optimizer)
+ cerr << obj->get_fileline() << ": cprop::lpm_part_select: "
+ << "Range [" << obj_set.back()->base()
+ << ":" << (obj_set.back()->base() + obj_set.back()->width() - 1)
+ << "] runs off the end of target." << endl;
+ return;
+ }
+
+ // Figure out how many components we are going to need.
+ unsigned part_count = 0;
+ unsigned off = 0;
+ for (size_t idx = 0 ; idx < obj_set.size() ; idx += 1) {
+ if (obj_set[idx]->base() > off) {
+ off = obj_set[idx]->base();
+ part_count += 1;
+ }
+ off += obj_set[idx]->width();
+ part_count += 1;
+ }
+
+ if (off < sig_width)
+ part_count += 1;
+
+ NetConcat*concat = new NetConcat(scope, scope->local_symbol(),
+ sig_width, part_count);
+ des->add_node(concat);
+ connect(concat->pin(0), obj->pin(1));
+
+ off = 0;
+ size_t concat_pin = 1;
+ for (size_t idx = 0 ; idx < obj_set.size() ; idx += 1) {
+ NetPartSelect*cobj = obj_set[idx];
+ if (cobj->base() > off) {
+ NetNet*zzz = make_const_z(des, scope, cobj->base()-off);
+ connect(concat->pin(concat_pin), zzz->pin(0));
+ concat_pin += 1;
+ off = cobj->base();
+ }
+ connect(concat->pin(concat_pin), cobj->pin(0));
+ concat_pin += 1;
+ off += cobj->width();
+ }
+ if (off < sig_width) {
+ NetNet*zzz = make_const_z(des, scope, sig_width-off);
+ connect(concat->pin(concat_pin), zzz->pin(0));
+ concat_pin += 1;
+ }
+ ivl_assert(*obj, concat_pin == concat->pin_count());
+
+ for (size_t idx = 0 ; idx < obj_set.size() ; idx += 1) {
+ delete obj_set[idx];
+ }
+
+ count += 1;
+}
+
/*
* This functor looks to see if the constant is connected to nothing
* but signals. If that is the case, delete the dangling constant and
View
11 functor.cc
@@ -24,6 +24,8 @@
# include "functor.h"
# include "netlist.h"
+using namespace std;
+
functor_t::~functor_t()
{
}
@@ -84,6 +86,10 @@ void functor_t::lpm_mux(Design*, NetMux*)
{
}
+void functor_t::lpm_part_select(Design*, NetPartSelect*)
+{
+}
+
void functor_t::lpm_pow(Design*, NetPow*)
{
}
@@ -225,6 +231,11 @@ void NetMux::functor_node(Design*des, functor_t*fun)
fun->lpm_mux(des, this);
}
+void NetPartSelect::functor_node(Design*des, functor_t*fun)
+{
+ fun->lpm_part_select(des, this);
+}
+
void NetPow::functor_node(Design*des, functor_t*fun)
{
fun->lpm_pow(des, this);
View
4 functor.h
@@ -1,7 +1,7 @@
#ifndef __functor_H
#define __functor_H
/*
- * Copyright (c) 1999-2008 Stephen Williams (steve@icarus.com)
+ * Copyright (c) 1999-2008,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
@@ -81,6 +81,8 @@ struct functor_t {
/* This method is called for each MUX. */
virtual void lpm_mux(class Design*des, class NetMux*);
+ virtual void lpm_part_select(class Design*des, class NetPartSelect*);
+
/* This method is called for each power. */
virtual void lpm_pow(class Design*des, class NetPow*);
View
5 netlist.cc
@@ -1031,11 +1031,6 @@ unsigned NetPartSelect::base() const
return off_;
}
-NetPartSelect::dir_t NetPartSelect::dir() const
-{
- return dir_;
-}
-
NetProc::NetProc()
: next_(0)
{
View
5 netlist.h
@@ -2002,12 +2002,13 @@ class NetPartSelect : public NetNode {
unsigned base() const;
unsigned width() const;
- dir_t dir() const;
+ inline dir_t dir() const { return dir_; }
/* Is the select signal signed? */
- bool signed_flag() const { return signed_flag_; }
+ inline bool signed_flag() const { return signed_flag_; }
virtual void dump_node(ostream&, unsigned ind) const;
bool emit_node(struct target_t*tgt) const;
+ virtual void functor_node(Design*des, functor_t*fun);
private:
unsigned off_;
View
14 netmisc.cc
@@ -660,6 +660,20 @@ NetNet* make_const_x(Design*des, NetScope*scope, unsigned long wid)
return sig;
}
+NetNet* make_const_z(Design*des, NetScope*scope, unsigned long wid)
+{
+ verinum xxx (verinum::Vz, wid);
+ NetConst*res = new NetConst(scope, scope->local_symbol(), xxx);
+ des->add_node(res);
+
+ netvector_t*sig_vec = new netvector_t(IVL_VT_LOGIC, wid-1, 0);
+ NetNet*sig = new NetNet(scope, scope->local_symbol(), NetNet::WIRE, sig_vec);
+ sig->local_flag(true);
+
+ connect(sig->pin(0), res->pin(0));
+ return sig;
+}
+
NetExpr* condition_reduce(NetExpr*expr)
{
if (expr->expr_type() == IVL_VT_REAL) {
View
1 netmisc.h
@@ -202,6 +202,7 @@ extern NetEConst*make_const_val(unsigned long val);
* Make A const net
*/
extern NetNet* make_const_x(Design*des, NetScope*scope, unsigned long wid);
+extern NetNet* make_const_z(Design*des, NetScope*scope, unsigned long wid);
/*
* In some cases the lval is accessible as a pointer to the head of

0 comments on commit 367d7bf

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