Add CA version of the <-> operator

This commit is contained in:
Cary R 2020-07-09 01:44:44 -07:00
parent c003bcc59a
commit dd80607ceb
11 changed files with 169 additions and 37 deletions

View File

@ -739,6 +739,12 @@ void NetLogic::dump_node(ostream&o, unsigned ind) const
case CMOS:
o << "cmos";
break;
case EQUIV:
o << "<->";
break;
case IMPL:
o << "->";
break;
case NAND:
o << "nand";
break;

View File

@ -545,13 +545,33 @@ NetNet* NetEBLogic::synthesize(Design*des, NetScope*scope, NetExpr*root)
return 0;
}
if ((op() == 'q') || (op() == 'Q')) {
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. */
switch (op()) {
case 'a':
olog = new NetLogic(scope, oname, 3, NetLogic::AND, 1, true);
break;
case 'o':
olog = new NetLogic(scope, oname, 3, NetLogic::OR, 1, true);
break;
case 'q':
olog = new NetLogic(scope, oname, 3, NetLogic::IMPL, 1, true);
break;
case 'Q':
olog = new NetLogic(scope, oname, 3, NetLogic::EQUIV, 1, true);
break;
default:
cerr << get_fileline() << ": sorry: "
<< human_readable_op(op_)
<< " is not currently supported in this context." << endl;
<< " is not currently supported." << endl;
des->errors += 1;
return 0;
}
olog->set_line(*this);
des->add_node(olog);
netvector_t*osig_tmp = new netvector_t(expr_type());
NetNet*osig = new NetNet(scope, scope->local_symbol(),
@ -559,21 +579,6 @@ NetNet* NetEBLogic::synthesize(Design*des, NetScope*scope, NetExpr*root)
osig->set_line(*this);
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') {
olog = new NetLogic(scope, oname, 3, NetLogic::OR, 1, true);
} else {
assert(op() == 'a');
olog = new NetLogic(scope, oname, 3, NetLogic::AND, 1, true);
}
olog->set_line(*this);
des->add_node(olog);
connect(osig->pin(0), olog->pin(0));
/* The left and right operands have already been reduced to a

View File

@ -265,6 +265,8 @@ typedef enum ivl_logic_e {
IVL_LO_BUFT = 24, /* transparent bufz. (NOT "tri-state") */
IVL_LO_BUFZ = 5,
IVL_LO_CMOS = 22,
IVL_LO_EQUIV = 25,
IVL_LO_IMPL = 26,
IVL_LO_NAND = 6,
IVL_LO_NMOS = 7,
IVL_LO_NOR = 8,
@ -280,7 +282,6 @@ typedef enum ivl_logic_e {
IVL_LO_RPMOS = 16,
IVL_LO_XNOR = 18,
IVL_LO_XOR = 19,
IVL_LO_UDP = 21
} ivl_logic_t;

View File

@ -2492,9 +2492,9 @@ class NetLiteral : public NetNode {
class NetLogic : public NetNode {
public:
enum TYPE { AND, BUF, BUFIF0, BUFIF1, CMOS, NAND, NMOS, NOR, NOT,
NOTIF0, NOTIF1, OR, PULLDOWN, PULLUP, RCMOS, RNMOS, RPMOS,
PMOS, XNOR, XOR };
enum TYPE { AND, BUF, BUFIF0, BUFIF1, CMOS, EQUIV, IMPL, NAND, NMOS,
NOR, NOT, NOTIF0, NOTIF1, OR, PULLDOWN, PULLUP, RCMOS,
RNMOS, RPMOS, PMOS, XNOR, XOR };
explicit NetLogic(NetScope*s, perm_string n, unsigned pins,
TYPE t, unsigned wid, bool is_cassign__=false);

View File

@ -971,6 +971,12 @@ void dll_target::logic(const NetLogic*net)
case NetLogic::CMOS:
obj->type_ = IVL_LO_CMOS;
break;
case NetLogic::EQUIV:
obj->type_ = IVL_LO_EQUIV;
break;
case NetLogic::IMPL:
obj->type_ = IVL_LO_IMPL;
break;
case NetLogic::NAND:
obj->type_ = IVL_LO_NAND;
break;

View File

@ -501,9 +501,9 @@ static void emit_expr_binary(ivl_scope_t scope, ivl_expr_t expr, unsigned wid,
emit_expr(scope, oper2, ivl_expr_width(oper2), 0, 1, 0);
break;
case 'q': // The arguments have already been reduced
fprintf(vlog_out, "!");
fprintf(vlog_out, "~");
emit_expr(scope, oper1, ivl_expr_width(oper1), 0, 1, 0);
fprintf(vlog_out, " || ");
fprintf(vlog_out, " | ");
emit_expr(scope, oper2, ivl_expr_width(oper2), 0, 1, 0);
break;
case 'Q': // The arguments have already been reduced

View File

@ -694,6 +694,22 @@ static void emit_logic_as_ca(ivl_scope_t scope, ivl_net_logic_t nlogic)
assert(inputs == 1);
emit_nexus_as_ca(scope, ivl_logic_pin(nlogic, 1), 0, 0);
break;
case IVL_LO_EQUIV:
assert(inputs == 2);
fprintf(vlog_out, "(");
emit_nexus_as_ca(scope, ivl_logic_pin(nlogic, 1), 0, 0);
fprintf(vlog_out, " ~^ ");
emit_nexus_as_ca(scope, ivl_logic_pin(nlogic, 2), 0, 0);
fprintf(vlog_out, ")");
break;
case IVL_LO_IMPL:
assert(inputs == 2);
fprintf(vlog_out, "(~");
emit_nexus_as_ca(scope, ivl_logic_pin(nlogic, 1), 0, 0);
fprintf(vlog_out, " | ");
emit_nexus_as_ca(scope, ivl_logic_pin(nlogic, 2), 0, 0);
fprintf(vlog_out, ")");
break;
case IVL_LO_NAND:
assert(inputs == 2);
fprintf(vlog_out, "~(");

View File

@ -421,22 +421,15 @@ static void draw_binary_vec4_lequiv(ivl_expr_t expr)
ivl_expr_t le = ivl_expr_oper1(expr);
ivl_expr_t re = ivl_expr_oper2(expr);
/* Push the left expression. Reduce it to a single bit if
necessary. */
/* The arguments should have already been reduced. */
assert(ivl_expr_width(le) == 1);
draw_eval_vec4(le);
if (ivl_expr_width(le) > 1)
fprintf(vvp_out, " %%or/r;\n");
/* Now push the right expression. Again, reduce to a single
bit if necessary. */
assert(ivl_expr_width(re) == 1);
draw_eval_vec4(re);
if (ivl_expr_width(re) > 1)
fprintf(vvp_out, " %%or/r;\n");
fprintf(vvp_out, " %%xnor;\n");
if (ivl_expr_width(expr) > 1)
fprintf(vvp_out, " %%pad/u %u;\n", ivl_expr_width(expr));
assert(ivl_expr_width(expr) == 1);
}
static void draw_binary_vec4_land(ivl_expr_t expr)

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2018 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2020 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
@ -907,6 +907,32 @@ static void draw_udp_in_scope(ivl_net_logic_t lptr)
if (need_delay_flag) draw_logic_delay(lptr);
}
static void draw_equiv_impl_in_scope(ivl_net_logic_t lptr)
{
unsigned ninp;
const char *lval;
const char *rval;
const char*ltype = "?";
assert(width_of_nexus(ivl_logic_pin(lptr, 0)) == 1);
assert(ivl_logic_pins(lptr) > 0);
ninp = ivl_logic_pins(lptr) - 1;
assert(ninp == 2);
lval = draw_net_input(ivl_logic_pin(lptr, 1));
rval = draw_net_input(ivl_logic_pin(lptr, 2));
if (ivl_logic_type(lptr) == IVL_LO_EQUIV) {
ltype = "EQUIV";
} else {
assert(ivl_logic_type(lptr) == IVL_LO_IMPL);
ltype = "IMPL";
}
fprintf(vvp_out, "L_%p .functor %s 1, %s, %s, C4<0>, C4<0>;\n", lptr, ltype, lval, rval);
}
static void draw_logic_in_scope(ivl_net_logic_t lptr)
{
unsigned pdx;
@ -984,6 +1010,11 @@ static void draw_logic_in_scope(ivl_net_logic_t lptr)
ltype = "BUFIF1";
break;
case IVL_LO_EQUIV:
case IVL_LO_IMPL:
draw_equiv_impl_in_scope(lptr);
return;
case IVL_LO_NAND:
ltype = "NAND";
lcasc = "AND";

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2020 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
@ -110,6 +110,54 @@ void vvp_fun_and::run_run()
ptr->send_vec4(result, 0);
}
vvp_fun_equiv::vvp_fun_equiv()
: vvp_fun_boolean_(1)
{
count_functors_logic += 1;
}
vvp_fun_equiv::~vvp_fun_equiv()
{
}
void vvp_fun_equiv::run_run()
{
vvp_net_t*ptr = net_;
net_ = 0;
assert(input_[0].size() == 1);
assert(input_[1].size() == 1);
vvp_bit4_t bit = ~(input_[0].value(0) ^ input_[1].value(0));
vvp_vector4_t result (1, bit);
ptr->send_vec4(result, 0);
}
vvp_fun_impl::vvp_fun_impl()
: vvp_fun_boolean_(1)
{
count_functors_logic += 1;
}
vvp_fun_impl::~vvp_fun_impl()
{
}
void vvp_fun_impl::run_run()
{
vvp_net_t*ptr = net_;
net_ = 0;
assert(input_[0].size() == 1);
assert(input_[1].size() == 1);
vvp_bit4_t bit = ~input_[0].value(0) | input_[1].value(0);
vvp_vector4_t result (1, bit);
ptr->send_vec4(result, 0);
}
vvp_fun_buf::vvp_fun_buf(unsigned wid)
: input_(wid, BIT4_Z)
{
@ -600,6 +648,12 @@ void compile_functor(char*label, char*type, unsigned width,
obj = new vvp_fun_bufif(false,false, ostr0, ostr1);
strength_aware = true;
} else if (strcmp(type, "EQUIV") == 0) {
obj = new vvp_fun_equiv();
} else if (strcmp(type, "IMPL") == 0) {
obj = new vvp_fun_impl();
} else if (strcmp(type, "NAND") == 0) {
obj = new vvp_fun_and(width, true);

View File

@ -1,7 +1,7 @@
#ifndef IVL_logic_H
#define IVL_logic_H
/*
* Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2020 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
@ -54,6 +54,26 @@ class vvp_fun_and : public vvp_fun_boolean_ {
bool invert_;
};
class vvp_fun_equiv : public vvp_fun_boolean_ {
public:
explicit vvp_fun_equiv();
~vvp_fun_equiv();
private:
void run_run();
};
class vvp_fun_impl : public vvp_fun_boolean_ {
public:
explicit vvp_fun_impl();
~vvp_fun_impl();
private:
void run_run();
};
/*
* The buffer functor is a very primitive functor that takes the input
* from port-0 (and only port-0) and retransmits it as a vvp_vector4_t.