Continuous assignments have their own driver

Elaborate conditional assignments with BUFZ devices that do *NOT*
preserve strengths. Add a BUFT (transparent) device that can be
used in those cases where I really need a transparent buffer.
This commit is contained in:
Stephen Williams 2010-07-11 17:16:15 -07:00
parent 4dcebe4024
commit fb1853144b
12 changed files with 62 additions and 21 deletions

View File

@ -128,7 +128,7 @@ void cprop_functor::lpm_mux(Design*des, NetMux*obj)
// The Select input must be a defined constant value, so we
// can replace the device with a BUFZ.
NetBUFZ*tmp = new NetBUFZ(obj->scope(), obj->name(), obj->width());
NetBUFZ*tmp = new NetBUFZ(obj->scope(), obj->name(), obj->width(), true);
tmp->set_line(*obj);
if (debug_optimizer)

View File

@ -427,7 +427,8 @@ void NetBUFZ::dump_node(ostream&o, unsigned ind) const
o << setw(ind) << "" << "NetBUFZ: " << name()
<< " scope=" << scope_path(scope())
<< " delay=(" << rise_time() << "," << fall_time() << "," <<
decay_time() << ") width=" << width() << endl;
decay_time() << ") width=" << width()
<< (transparent()? " " : " non-") << "transparent" << endl;
dump_node_pins(o, ind+4);
}

View File

@ -179,7 +179,7 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
if (need_driver_flag) {
NetBUFZ*driver = new NetBUFZ(scope, scope->local_symbol(),
rval->vector_width());
rval->vector_width(), false);
driver->set_line(*this);
des->add_node(driver);
@ -1257,7 +1257,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
if (need_bufz_for_input_port(prts)) {
NetBUFZ*tmp = new NetBUFZ(scope, scope->local_symbol(),
sig->vector_width());
sig->vector_width(), true);
des->add_node(tmp);
connect(tmp->pin(1), sig->pin(0));

View File

@ -234,6 +234,7 @@ typedef enum ivl_logic_e {
IVL_LO_BUF = 2,
IVL_LO_BUFIF0 = 3,
IVL_LO_BUFIF1 = 4,
IVL_LO_BUFT = 24, /* transparent bufz. (NOT "tri-state") */
IVL_LO_BUFZ = 5,
IVL_LO_CMOS = 22,
IVL_LO_NAND = 6,

View File

@ -1775,8 +1775,8 @@ unsigned NetSignExtend::width() const
return width_;
}
NetBUFZ::NetBUFZ(NetScope*s, perm_string n, unsigned w)
: NetNode(s, n, 2), width_(w)
NetBUFZ::NetBUFZ(NetScope*s, perm_string n, unsigned w, bool trans)
: NetNode(s, n, 2), width_(w), transparent_(trans)
{
pin(0).set_dir(Link::OUTPUT);
pin(1).set_dir(Link::INPUT);

View File

@ -1827,20 +1827,26 @@ class NetPartSelect : public NetNode {
* the logic that feeds it. The netlist preserves the directional
* nature of that assignment with the BUFZ. The target may elide it if
* that makes sense for the technology.
*
* A NetBUFZ is transparent if strengths are passed through it without
* change. A NetBUFZ is non-transparent if values other then HiZ are
* converted to the strength of the output.
*/
class NetBUFZ : public NetNode {
public:
explicit NetBUFZ(NetScope*s, perm_string n, unsigned wid);
explicit NetBUFZ(NetScope*s, perm_string n, unsigned wid, bool transp);
~NetBUFZ();
unsigned width() const;
bool transparent() const { return transparent_; }
virtual void dump_node(ostream&, unsigned ind) const;
virtual bool emit_node(struct target_t*) const;
private:
unsigned width_;
bool transparent_;
};
/*

View File

@ -795,7 +795,7 @@ bool dll_target::bufz(const NetBUFZ*net)
assert(net->pin_count() == 2);
obj->type_ = IVL_LO_BUFZ;
obj->type_ = net->transparent()? IVL_LO_BUFT : IVL_LO_BUFZ;
obj->width_= net->width();
obj->npins_= 2;
obj->pins_ = new ivl_nexus_t[2];

View File

@ -1385,6 +1385,9 @@ static void show_logic(ivl_net_logic_t net)
case IVL_LO_BUFIF1:
fprintf(out, " bufif1 %s", name);
break;
case IVL_LO_BUFT:
fprintf(out, " buft %s", name);
break;
case IVL_LO_BUFZ:
fprintf(out, " bufz %s", name);
break;

View File

@ -233,7 +233,9 @@ static char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr)
ivl_lpm_t lpm;
lptr = ivl_nexus_ptr_log(nptr);
if (lptr && (ivl_logic_type(lptr) == IVL_LO_BUFZ) && (nptr_pin == 0))
if (lptr
&& ((ivl_logic_type(lptr)==IVL_LO_BUFZ)||(ivl_logic_type(lptr)==IVL_LO_BUFT))
&& (nptr_pin == 0))
do {
if (! can_elide_bufz(lptr, nptr))
break;
@ -319,7 +321,7 @@ static char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr)
/* Make the constant an argument to a BUFZ, which is
what we use to drive the PULLed value. */
fprintf(vvp_out, "L_%p .functor BUFZ 1, %s, C4<0>, C4<0>, C4<0>;\n",
fprintf(vvp_out, "L_%p .functor BUFT 1, %s, C4<0>, C4<0>, C4<0>;\n",
lptr, result);
snprintf(tmp, sizeof tmp, "L_%p", lptr);
result = realloc(result, strlen(tmp)+1);
@ -390,7 +392,7 @@ static char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr)
/* We have a delayed constant, so we need to build some code. */
if (d_rise != 0) {
char tmp[128];
fprintf(vvp_out, "L_%p/d .functor BUFZ 1, %s, "
fprintf(vvp_out, "L_%p/d .functor BUFT 1, %s, "
"C4<0>, C4<0>, C4<0>;\n", cptr, result);
free(result);
@ -440,7 +442,7 @@ static char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr)
} else {
char tmp[64];
fprintf(vvp_out, "L_%p .functor BUFZ 1, %s, "
fprintf(vvp_out, "L_%p .functor BUFT 1, %s, "
"C4<0>, C4<0>, C4<0>;\n", cptr, result);
free(result);

View File

@ -722,6 +722,20 @@ static void draw_logic_in_scope(ivl_net_logic_t lptr)
break;
}
case IVL_LO_BUFT: {
/* Draw bufz objects, but only if the gate cannot
be elided. If I can elide it, then the
draw_nex_input will take care of it for me. */
ivl_nexus_ptr_t nptr = ivl_logic_pin_ptr(lptr,0);
ltype = "BUFT";
if (can_elide_bufz(lptr, nptr))
return;
break;
}
case IVL_LO_PULLDOWN:
case IVL_LO_PULLUP:
/* Skip pullup and pulldown objects. Things that have

View File

@ -202,14 +202,6 @@ void vvp_fun_bufz::recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
ptr.ptr()->send_vec4_pv(bit, base, wid, vwid, 0);
}
void vvp_fun_bufz::recv_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&bit)
{
if (ptr.port() != 0)
return;
ptr.ptr()->send_vec8(bit);
}
void vvp_fun_bufz::recv_real(vvp_net_ptr_t ptr, double bit,
vvp_context_t)
{
@ -219,6 +211,14 @@ void vvp_fun_bufz::recv_real(vvp_net_ptr_t ptr, double bit,
ptr.ptr()->send_real(bit, 0);
}
void vvp_fun_buft::recv_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&bit)
{
if (ptr.port() != 0)
return;
ptr.ptr()->send_vec8(bit);
}
vvp_fun_muxr::vvp_fun_muxr()
: a_(0.0), b_(0.0)
{
@ -609,6 +609,9 @@ void compile_functor(char*label, char*type, unsigned width,
obj = new vvp_fun_bufif(false,true, ostr0, ostr1);
strength_aware = true;
} else if (strcmp(type, "BUFT") == 0) {
obj = new vvp_fun_buft();
} else if (strcmp(type, "BUFZ") == 0) {
obj = new vvp_fun_bufz();

View File

@ -95,13 +95,24 @@ class vvp_fun_bufz: public vvp_net_fun_t {
void recv_vec4_pv(vvp_net_ptr_t p, const vvp_vector4_t&bit,
unsigned base, unsigned wid, unsigned vwid,
vvp_context_t);
void recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit);
//void recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit);
void recv_real(vvp_net_ptr_t p, double bit,
vvp_context_t);
private:
};
/*
* The vp_fun_buft is like the vvp_fun_bufz, but is completely
* transparent to strengths.
*/
class vvp_fun_buft: public vvp_fun_bufz {
public:
void recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit);
private:
};
enum sel_type {SEL_PORT0, SEL_PORT1, SEL_BOTH};
/*