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:
parent
4dcebe4024
commit
fb1853144b
2
cprop.cc
2
cprop.cc
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
|||
2
t-dll.cc
2
t-dll.cc
|
|
@ -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];
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
19
vvp/logic.cc
19
vvp/logic.cc
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
13
vvp/logic.h
13
vvp/logic.h
|
|
@ -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};
|
||||
|
||||
/*
|
||||
|
|
|
|||
Loading…
Reference in New Issue