Add support for passing a real input to logic, mos and if gates

This commit is contained in:
Cary R 2025-06-21 10:02:45 -07:00
parent 26c01e7f0a
commit adcb9f4e0d
12 changed files with 438 additions and 107 deletions

View File

@ -0,0 +1,115 @@
module top;
reg passed;
real inr;
wire out_buf, out_not, out_and, out_nand, out_or, out_nor, out_xor, out_xnor;
buf(out_buf, inr);
not(out_not, inr);
and(out_and, inr, 1'b1);
nand(out_nand, inr, 1'b1);
or(out_or, inr, 1'b0);
nor(out_nor, inr, 1'b0);
xor(out_xor, inr, 1'b1);
xnor(out_xnor, inr, 1'b1);
always @(out_not) begin
int inr_int;
inr_int = inr;
if (out_not !== !inr_int[0]) begin
$display("not of %f not equal to %b", inr, !inr_int[0]);
passed = 1'b0;
end
end
always @(out_buf) begin
int inr_int;
inr_int = inr;
if (out_buf !== inr_int[0]) begin
$display("buf of %f not equal to %b", inr, inr_int[0]);
passed = 1'b0;
end
end
always @(out_and) begin
int inr_int;
inr_int = inr;
if (out_and !== inr_int[0]) begin
$display("and of %f not equal to %b", inr, inr_int[0]);
passed = 1'b0;
end
end
always @(out_nand) begin
int inr_int;
inr_int = inr;
if (out_nand !== !inr_int[0]) begin
$display("nand of %f not equal to %b", inr, !inr_int[0]);
passed = 1'b0;
end
end
always @(out_or) begin
int inr_int;
inr_int = inr;
if (out_or !== inr_int[0]) begin
$display("or of %f not equal to %b", inr, inr_int[0]);
passed = 1'b0;
end
end
always @(out_nor) begin
int inr_int;
inr_int = inr;
if (out_nor !== !inr_int[0]) begin
$display("nor of %f not equal to %b", inr, !inr_int[0]);
passed = 1'b0;
end
end
always @(out_xor) begin
int inr_int;
inr_int = inr;
if (out_xor !== !inr_int[0]) begin
$display("xor of %f not equal to %b", inr, !inr_int[0]);
passed = 1'b0;
end
end
always @(out_xnor) begin
int inr_int;
inr_int = inr;
if (out_xnor !== inr_int[0]) begin
$display("xnor of %f not equal to %b", inr, inr_int[0]);
passed = 1'b0;
end
end
initial begin
$display("bf nt an na or no xo xn in");
$monitor(out_buf,,,out_not,,,out_and,,,out_nand,,,out_or,,,out_nor,,,out_xor,,,out_xnor,,,inr);
#1;
if (passed === 1'bx) passed = 1'b1;
inr = 1.0;
#1;
inr = 0.0;
#1
inr = 3.0;
#1;
inr = 2.0;
#1;
inr = 4.0;
#1;
inr = 2.5;
#1;
inr = 2.49;
#1;
inr = -1.0;
#1;
inr = 1.0/0.0;
#1;
if (passed) $display("PASSED");
end
endmodule

View File

@ -0,0 +1,76 @@
module top;
reg passed;
real inr, ctrl;
wire out_bf0, out_bf1, out_nt0, out_nt1;
bufif0(out_bf0, inr, ctrl);
bufif1(out_bf1, inr, 1'b1);
notif0(out_nt0, inr, ctrl);
notif1(out_nt1, inr, 1'b1);
always @(out_bf0) begin
int inr_int;
inr_int = inr;
if (out_bf0 !== inr_int[0]) begin
$display("bufif0 of %f not equal to %b", inr, inr_int[0]);
passed = 1'b0;
end
end
always @(out_bf1) begin
int inr_int;
inr_int = inr;
if (out_bf1 !== inr_int[0]) begin
$display("bufif1 of %f not equal to %b", inr, inr_int[0]);
passed = 1'b0;
end
end
always @(out_nt0) begin
int inr_int;
inr_int = inr;
if (out_nt0 !== !inr_int[0]) begin
$display("bufif0 of %f not equal to %b", inr, !inr_int[0]);
passed = 1'b0;
end
end
always @(out_nt1) begin
int inr_int;
inr_int = inr;
if (out_nt1 !== !inr_int[0]) begin
$display("bufif1 of %f not equal to %b", inr, !inr_int[0]);
passed = 1'b0;
end
end
initial begin
$display("b0 b1 n0 n1 in");
$monitor(out_bf0,,,out_bf1,,,out_nt0,,,out_nt1,,,inr);
#1;
if (passed === 1'bx) passed = 1'b1;
ctrl = 2.49;
inr = 1.0;
#1;
inr = 0.0;
#1
inr = 3.0;
#1;
inr = 2.0;
#1;
inr = 4.0;
#1;
inr = 2.5;
#1;
inr = 2.49;
#1;
inr = -1.0;
#1;
inr = 1.0/0.0;
#1;
if (passed) $display("PASSED");
end
endmodule

View File

@ -0,0 +1,118 @@
module top;
reg passed;
real inr, ctrl;
wire out_nm, out_rnm, out_pm, out_rpm;
wire out_cm_n, out_cm_p, out_rcm_n, out_rcm_p;
pmos(out_pm, inr, ctrl);
rpmos(out_rpm, inr, ctrl);
nmos(out_nm, inr, 1'b1);
rnmos(out_rnm, inr, 1'b1);
cmos(out_cm_n, inr, 1'b1, 1'b1);
cmos(out_cm_p, inr, ctrl, ctrl);
cmos(out_rcm_n, inr, 1'b1, 1'b1);
cmos(out_rcm_p, inr, ctrl, ctrl);
always @(out_pm) begin
int inr_int;
inr_int = inr;
if (out_pm !== inr_int[0]) begin
$display("pmos of %f not equal to %b", inr, inr_int[0]);
passed = 1'b0;
end
end
always @(out_rpm) begin
int inr_int;
inr_int = inr;
if (out_rpm !== inr_int[0]) begin
$display("rpmos of %f not equal to %b", inr, inr_int[0]);
passed = 1'b0;
end
end
always @(out_nm) begin
int inr_int;
inr_int = inr;
if (out_nm !== inr_int[0]) begin
$display("nmos of %f not equal to %b", inr, inr_int[0]);
passed = 1'b0;
end
end
always @(out_rnm) begin
int inr_int;
inr_int = inr;
if (out_rnm !== inr_int[0]) begin
$display("rnmos of %f not equal to %b", inr, inr_int[0]);
passed = 1'b0;
end
end
always @(out_cm_n) begin
int inr_int;
inr_int = inr;
if (out_cm_n !== inr_int[0]) begin
$display("cmos(N) of %f not equal to %b", inr, inr_int[0]);
passed = 1'b0;
end
end
always @(out_cm_p) begin
int inr_int;
inr_int = inr;
if (out_cm_p !== inr_int[0]) begin
$display("cmos(P) of %f not equal to %b", inr, inr_int[0]);
passed = 1'b0;
end
end
always @(out_rcm_n) begin
int inr_int;
inr_int = inr;
if (out_rcm_n !== inr_int[0]) begin
$display("rcmos(N) of %f not equal to %b", inr, inr_int[0]);
passed = 1'b0;
end
end
always @(out_rcm_p) begin
int inr_int;
inr_int = inr;
if (out_rcm_p !== inr_int[0]) begin
$display("rcmos(P) of %f not equal to %b", inr, inr_int[0]);
passed = 1'b0;
end
end
initial begin
$display("n rn p rp cn rcn cp rcp in");
$monitor(out_nm,,,out_rnm,,,out_pm,,,out_rpm,,,out_cm_n,,,out_rcm_n,,,,out_cm_p,,,out_rcm_p,,,,inr);
#1;
if (passed === 1'bx) passed = 1'b1;
ctrl = 2.49;
inr = 1.0;
#1;
inr = 0.0;
#1
inr = 3.0;
#1;
inr = 2.0;
#1;
inr = 4.0;
#1;
inr = 2.5;
#1;
inr = 2.49;
#1;
inr = -1.0;
#1;
inr = 1.0/0.0;
#1;
if (passed) $display("PASSED");
end
endmodule

View File

@ -364,6 +364,9 @@ br_gh1178a CE ivltests gold=br_gh1178a.gold
br_gh1178b normal ivltests
br_gh1178c normal ivltests
br_gh1182 CE ivltests gold=br_gh1182.gold
br_gh1223a normal,-g2009 ivltests
br_gh1223b normal,-g2009 ivltests
br_gh1223c normal,-g2009 ivltests
br_ml20150315 normal ivltests gold=br_ml_20150315.gold
br_ml20150321 CE ivltests
br_mw20171108 normal ivltests

View File

@ -859,6 +859,9 @@ br_gh386d normal,-g2009,-pallowsigned=1 ivltests
br_gh477 normal,-g2009,-pallowsigned=1 ivltests
br_gh540 normal,-g2009,-pallowsigned=1 ivltests
br_gh793 normal,-pallowsigned=1 ivltests
br_gh1223a normal,-g2009,-pallowsigned=1 ivltests
br_gh1223b normal,-g2009,-pallowsigned=1 ivltests
br_gh1223c normal,-g2009,-pallowsigned=1 ivltests
ca_mult normal,-pallowsigned=1 ivltests gold=ca_mult.gold
cast_int normal,-pallowsigned=1 ivltests
cfunc_assign_op_vec normal,-g2009,-pallowsigned=1 ivltests

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2016 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2025 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
@ -87,3 +87,9 @@ void vvp_fun_bufif::recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
{
recv_vec4_pv_(ptr, bit, base, vwid, ctx);
}
void vvp_fun_bufif::recv_real(vvp_net_ptr_t ptr, double real,
vvp_context_t ctx)
{
recv_vec4(ptr, double_to_vector4_LSB(real), ctx);
}

View File

@ -1,7 +1,7 @@
#ifndef IVL_bufif_H
#define IVL_bufif_H
/*
* Copyright (c) 2001-2016 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2025 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
@ -39,9 +39,10 @@ class vvp_fun_bufif : public vvp_net_fun_t {
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
vvp_context_t);
void recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
unsigned base, unsigned vwid, vvp_context_t ctx);
void recv_real(vvp_net_ptr_t port, double real,
vvp_context_t ctx);
private:
vvp_vector4_t bit_;

View File

@ -44,8 +44,7 @@ void vvp_fun_boolean_::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
vvp_context_t)
{
unsigned port = ptr.port();
if (input_[port] .eeq( bit ))
return;
if (input_[port] .eeq( bit )) return;
input_[port] = bit;
if (net_ == 0) {
@ -72,6 +71,12 @@ void vvp_fun_boolean_::recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
}
}
void vvp_fun_boolean_::recv_real(vvp_net_ptr_t ptr, double real,
vvp_context_t ctx)
{
recv_vec4(ptr, double_to_vector4_LSB(real), ctx);
}
vvp_fun_and::vvp_fun_and(unsigned wid, bool invert)
: vvp_fun_boolean_(wid), invert_(invert)
{
@ -156,10 +161,58 @@ void vvp_fun_impl::run_run()
ptr->send_vec4(result, 0);
}
vvp_fun_buf::vvp_fun_buf(unsigned wid)
vvp_fun_buf_not_::vvp_fun_buf_not_(unsigned wid)
: input_(wid, BIT4_Z)
{
net_ = 0;
}
vvp_fun_buf_not_::~vvp_fun_buf_not_()
{
}
void vvp_fun_buf_not_::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
vvp_context_t)
{
if (ptr.port() != 0) return;
if (input_ .eeq( bit )) return;
input_ = bit;
if (net_ == 0) {
net_ = ptr.ptr();
schedule_functor(this);
}
}
void vvp_fun_buf_not_::recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
unsigned base, unsigned vwid, vvp_context_t)
{
if (ptr.port() != 0) return;
assert(base + bit.size() <= vwid);
// Set the input part. If nothing changes, then break.
bool flag = input_.set_vec(base, bit);
if (flag == false) return;
if (net_ == 0) {
net_ = ptr.ptr();
schedule_functor(this);
}
}
void vvp_fun_buf_not_::recv_real(vvp_net_ptr_t ptr, double real,
vvp_context_t ctx)
{
if (ptr.port() != 0) return;
recv_vec4(ptr, double_to_vector4_LSB(real), ctx);
}
vvp_fun_buf::vvp_fun_buf(unsigned wid)
: vvp_fun_buf_not_(wid)
{
count_functors_logic += 1;
}
@ -171,42 +224,6 @@ vvp_fun_buf::~vvp_fun_buf()
* The buf functor is very simple--change the z bits to x bits in the
* vector it passes, and propagate the result.
*/
void vvp_fun_buf::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
vvp_context_t)
{
if (ptr.port() != 0)
return;
if (input_ .eeq( bit ))
return;
input_ = bit;
if (net_ == 0) {
net_ = ptr.ptr();
schedule_functor(this);
}
}
void vvp_fun_buf::recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
unsigned base, unsigned vwid, vvp_context_t)
{
if (ptr.port() != 0)
return;
assert(base + bit.size() <= vwid);
// Set the input part. If nothing changes, then break.
bool flag = input_.set_vec(base, bit);
if (flag == false)
return;
if (net_ == 0) {
net_ = ptr.ptr();
schedule_functor(this);
}
}
void vvp_fun_buf::run_run()
{
vvp_net_t*ptr = net_;
@ -479,9 +496,8 @@ void vvp_fun_muxz::run_run()
}
vvp_fun_not::vvp_fun_not(unsigned wid)
: input_(wid, BIT4_Z)
: vvp_fun_buf_not_(wid)
{
net_ = 0;
count_functors_logic += 1;
}
@ -493,41 +509,6 @@ vvp_fun_not::~vvp_fun_not()
* The not functor is very simple--change the z bits to x bits in the
* vector it passes, and propagate the inverted result.
*/
void vvp_fun_not::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
vvp_context_t)
{
if (ptr.port() != 0)
return;
if (input_ .eeq( bit ))
return;
input_ = bit;
if (net_ == 0) {
net_ = ptr.ptr();
schedule_functor(this);
}
}
void vvp_fun_not::recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
unsigned base, unsigned vwid, vvp_context_t)
{
if (ptr.port() != 0)
return;
assert(base + bit.size() <= vwid);
// Set the part value. If nothing changes, then break.
bool flag = input_.set_vec(base, bit);
if (flag == false)
return;
if (net_ == 0) {
net_ = ptr.ptr();
schedule_functor(this);
}
}
void vvp_fun_not::run_run()
{
vvp_net_t*ptr = net_;

View File

@ -1,7 +1,7 @@
#ifndef IVL_logic_H
#define IVL_logic_H
/*
* Copyright (c) 2000-2020 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2025 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
@ -36,6 +36,8 @@ class vvp_fun_boolean_ : public vvp_net_fun_t, protected vvp_gen_event_s {
vvp_context_t);
void recv_vec4_pv(vvp_net_ptr_t p, const vvp_vector4_t&bit,
unsigned base, unsigned vwid, vvp_context_t);
void recv_real(vvp_net_ptr_t p, double real,
vvp_context_t);
protected:
vvp_vector4_t input_[4];
@ -74,28 +76,40 @@ class vvp_fun_impl : public vvp_fun_boolean_ {
};
/*
* 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.
* The retransmitted vector has all Z values changed to X, just like
* the buf(Q,D) gate in Verilog.
* vvp_fun_buf_not_ is just a common hook for holding operands.
*/
class vvp_fun_buf: public vvp_net_fun_t, private vvp_gen_event_s {
class vvp_fun_buf_not_ : public vvp_net_fun_t, protected vvp_gen_event_s {
public:
explicit vvp_fun_buf(unsigned wid);
virtual ~vvp_fun_buf();
explicit vvp_fun_buf_not_(unsigned wid);
~vvp_fun_buf_not_();
void recv_vec4(vvp_net_ptr_t p, const vvp_vector4_t&bit,
vvp_context_t);
void recv_vec4_pv(vvp_net_ptr_t p, const vvp_vector4_t&bit,
unsigned base, unsigned vwid, vvp_context_t);
void recv_real(vvp_net_ptr_t p, double real,
vvp_context_t ctx);
protected:
vvp_vector4_t input_;
vvp_net_t*net_;
};
/*
* 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.
* The retransmitted vector has all Z values changed to X, just like
* the buf(Q,D) gate in Verilog.
*/
class vvp_fun_buf: public vvp_fun_buf_not_ {
public:
explicit vvp_fun_buf(unsigned wid);
virtual ~vvp_fun_buf();
private:
void run_run();
private:
vvp_vector4_t input_;
vvp_net_t*net_;
};
/*
@ -186,23 +200,14 @@ class vvp_fun_muxr : public vvp_net_fun_t, private vvp_gen_event_s {
sel_type select_;
};
class vvp_fun_not: public vvp_net_fun_t, private vvp_gen_event_s {
class vvp_fun_not: public vvp_fun_buf_not_ {
public:
explicit vvp_fun_not(unsigned wid);
virtual ~vvp_fun_not();
void recv_vec4(vvp_net_ptr_t p, const vvp_vector4_t&bit,
vvp_context_t);
void recv_vec4_pv(vvp_net_ptr_t p, const vvp_vector4_t&bit,
unsigned base, unsigned vwid, vvp_context_t);
private:
void run_run();
private:
vvp_vector4_t input_;
vvp_net_t*net_;
};
class vvp_fun_or : public vvp_fun_boolean_ {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005-2018 Stephen Williams (steve@icarus.com)
* Copyright (c) 2005-2025 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
@ -56,6 +56,12 @@ void vvp_fun_pmos_::recv_vec8_pv(vvp_net_ptr_t ptr, const vvp_vector8_t&bit,
recv_vec8_pv_(ptr, bit, base, vwid);
}
void vvp_fun_pmos_::recv_real(vvp_net_ptr_t ptr, double real,
vvp_context_t ctx)
{
recv_vec4(ptr, double_to_vector4_LSB(real), ctx);
}
void vvp_fun_pmos_::generate_output_(vvp_net_ptr_t ptr)
{
const unsigned*strength_map = vvp_switch_strength_map[resistive_];
@ -179,6 +185,12 @@ void vvp_fun_cmos_::recv_vec8_pv(vvp_net_ptr_t ptr, const vvp_vector8_t&bit,
recv_vec8_pv_(ptr, bit, base, vwid);
}
void vvp_fun_cmos_::recv_real(vvp_net_ptr_t ptr, double real,
vvp_context_t ctx)
{
recv_vec4(ptr, double_to_vector4_LSB(real), ctx);
}
void vvp_fun_cmos_::generate_output_(vvp_net_ptr_t ptr)
{
const unsigned*strength_map = vvp_switch_strength_map[resistive_];

View File

@ -1,7 +1,7 @@
#ifndef IVL_npmos_H
#define IVL_npmos_H
/*
* Copyright (c) 2005-2018 Stephen Williams (steve@icarus.com)
* Copyright (c) 2005-2025 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
@ -50,11 +50,12 @@ class vvp_fun_pmos_ : public vvp_net_fun_t {
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
vvp_context_t);
void recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
unsigned base, unsigned vwid, vvp_context_t ctx);
void recv_vec8_pv(vvp_net_ptr_t ptr, const vvp_vector8_t&bit,
unsigned base, unsigned vwid);
void recv_real(vvp_net_ptr_t port, double real,
vvp_context_t ctx);
protected:
void generate_output_(vvp_net_ptr_t port);
@ -110,13 +111,14 @@ class vvp_fun_cmos_ : public vvp_net_fun_t {
public:
explicit vvp_fun_cmos_(bool resistive);
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t &bit,
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
vvp_context_t);
void recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
unsigned base, unsigned vwid, vvp_context_t ctx);
void recv_vec8_pv(vvp_net_ptr_t ptr, const vvp_vector8_t&bit,
unsigned base, unsigned vwid);
void recv_real(vvp_net_ptr_t port, double real,
vvp_context_t);
protected:
void generate_output_(vvp_net_ptr_t port);

View File

@ -1,7 +1,7 @@
#ifndef IVL_vvp_net_H
#define IVL_vvp_net_H
/*
* Copyright (c) 2004-2021 Stephen Williams (steve@icarus.com)
* Copyright (c) 2004-2025 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
@ -572,6 +572,15 @@ extern bool vector2_to_value(const vvp_vector2_t&a, int32_t&val, bool is_signed)
extern vvp_vector4_t vector4_from_text(const char*bits, unsigned wid);
inline vvp_vector4_t double_to_vector4_LSB(double real)
{
// Convert the double to a bit vector and then use the LSB.
// You can use very large real values and break the 64-bit
// size, but that's really horrible code so don't do that!
vvp_vector4_t bit = vvp_vector4_t(64, real);
bit.resize(1);
return bit;
}
/*
* vvp_vector4array_t