More robust creation of nets.

Handle the case where the input to a net is a constant. Since nets
do not exist anymore as nodes in their own right, we need to create
a driver to drive a net from a constant.

Handle forward references of net inputs.
This commit is contained in:
Stephen Williams 2009-08-23 21:37:16 -07:00
parent dc47c2b6e4
commit 9f11a23611
4 changed files with 173 additions and 32 deletions

View File

@ -727,12 +727,27 @@ void compile_vpi_time_precision(long pre)
*
* The real value is sign * (mant ** exp).
*/
double crstring_to_double(char*label)
bool crstring_test(const char*str)
{
char*cp = label+3;
if (strncmp(str, "Cr<", 3) != 0) return false;
const char*tp = strchr(str, '>');
if (tp == 0) return false;
if (tp[1] != 0) return false;
if ((strspn(str+3, "0123456789abcdefmg")+3) != (tp - str))
return false;
return true;
}
double crstring_to_double(const char*label)
{
const char*cp = label+3;
assert(*cp == 'm');
cp += 1;
uint64_t mant = strtoull(cp, &cp, 16);
char*ep;
uint64_t mant = strtoull(cp, &ep, 16);
cp = ep;
assert(*cp == 'g');
cp += 1;
int exp = strtoul(cp, 0, 16);
@ -774,10 +789,7 @@ void input_connect(vvp_net_t*fdx, unsigned port, char*label)
char*tp;
/* Is this a vvp_vector4_t constant value? */
if ((strncmp(label, "C4<", 3) == 0)
&& ((tp = strchr(label,'>')))
&& (tp[1] == 0)
&& (strspn(label+3, "01xz")+3 == (unsigned)(tp-label))) {
if (c4string_test(label)) {
vvp_vector4_t tmp = c4string_to_vector4(label);
@ -837,10 +849,7 @@ void input_connect(vvp_net_t*fdx, unsigned port, char*label)
/* Handle the Cr<> constant driver, which is a real-value
driver. */
if ((strncmp(label, "Cr<", 3) == 0)
&& ((tp = strchr(label,'>')))
&& (tp[1] == 0)
&& (strspn(label+3, "0123456789abcdefmg")+3 == (unsigned)(tp-label))) {
if (crstring_test(label)) {
double tmp = crstring_to_double(label);

View File

@ -2370,6 +2370,19 @@ vvp_vector4_t vector2_to_vector4(const vvp_vector2_t&that, unsigned wid)
return res;
}
bool c4string_test(const char*str)
{
if (strncmp(str, "C4<", 3) != 0)
return false;
size_t value_size = strspn(str+3, "01xz");
if (str[3+value_size] != '>')
return false;
if (str[3+value_size+1] != 0)
return false;
return true;
}
vvp_vector4_t c4string_to_vector4(const char*str)
{
assert((str[0]=='C') && (str[1]=='4') && (str[2]=='<'));
@ -2519,6 +2532,24 @@ vvp_vector8_t part_expand(const vvp_vector8_t&that, unsigned wid, unsigned off)
return tmp;
}
bool c8string_test(const char*str)
{
const char*cp;
if (str[0] != 'C') return false;
if (str[1] != '8') return false;
if (str[2] != '<') return false;
cp = str+3;
for (;; cp += 1) {
if (cp[0] == '>' && cp[1] == 0) return true;
if (cp[0] >= '0' && cp[0] <= '9') continue;
if (cp[0] == 'x') continue;
if (cp[0] == 'z') continue;
return false;
}
return false;
}
ostream& operator<<(ostream&out, const vvp_vector8_t&that)
{
out << "C8<";

View File

@ -639,9 +639,15 @@ extern vvp_vector2_t operator % (const vvp_vector2_t&, const vvp_vector2_t&);
vvp_vector2_t pow(const vvp_vector2_t&, vvp_vector2_t&);
extern vvp_vector4_t vector2_to_vector4(const vvp_vector2_t&, unsigned wid);
/* A c4string is of the form C4<...> where ... are bits. */
extern bool c4string_test(const char*str);
extern vvp_vector4_t c4string_to_vector4(const char*str);
/* A crstring is of the form Cr<...> where ... defines are real. */
extern bool crstring_test(const char*str);
extern double crstring_to_double(const char*str);
extern ostream& operator<< (ostream&, const vvp_vector2_t&);
/* Inline some of the vector2_t methods. */
@ -830,6 +836,11 @@ extern vvp_vector8_t resistive_reduction(const vvp_vector8_t&a);
strength information in the process. */
extern vvp_vector4_t reduce4(const vvp_vector8_t&that);
extern vvp_vector8_t part_expand(const vvp_vector8_t&a, unsigned wid, unsigned off);
/* A c8string is of the form C8<...> where ... are bits. */
extern bool c8string_test(const char*str);
extern vvp_vector8_t c8string_to_vector8(const char*str);
/* Print a vector8 value to a stream. */
extern ostream& operator<< (ostream&, const vvp_vector8_t&);

View File

@ -21,6 +21,7 @@
# include "vpi_priv.h"
# include "array.h"
# include "vvp_net_sig.h"
# include "logic.h"
# include "schedule.h"
# include <stdio.h>
# include <stdlib.h>
@ -146,6 +147,58 @@ void compile_variablew(char*label, vvp_array_t array,
__compile_var(label, 0, array, array_addr, msb, lsb, signed_flag, false);
}
vvp_net_t* create_constant_node(const char*label, const char*val_str)
{
if (c4string_test(val_str)) {
vvp_net_t*net = new vvp_net_t;
net->fun = new vvp_fun_bufz;
schedule_init_vector(vvp_net_ptr_t(net,0), c4string_to_vector4(val_str));
return net;
}
if (c8string_test(val_str)) {
vvp_net_t*net = new vvp_net_t;
net->fun = new vvp_fun_bufz;
assert(0); // XXXX Don't know how to init a vvp_vector8_t? */
return net;
}
if (crstring_test(val_str)) {
vvp_net_t*net = new vvp_net_t;
net->fun = new vvp_fun_bufz;
schedule_init_vector(vvp_net_ptr_t(net,0), crstring_to_double(val_str));
return net;
}
return 0;
}
class __compile_net_resolv : public resolv_list_s {
public:
explicit __compile_net_resolv(char*ref_label, char*my_label, char*name,
int msb, int lsb,
bool signed_flag, bool net8_flag, bool local_flag)
: resolv_list_s(ref_label)
{ my_label_ = my_label;
name_ = name;
msb_ = msb;
lsb_ = lsb;
signed_flag_ = signed_flag;
local_flag_ = local_flag;
}
~__compile_net_resolv() { }
bool resolve(bool message_flag);
private:
char*my_label_;
char*name_;
int msb_, lsb_;
bool signed_flag_, net8_flag_, local_flag_;
};
/*
* Here we handle .net records from the vvp source:
*
@ -157,23 +210,12 @@ void compile_variablew(char*label, vvp_array_t array,
* Create a VPI handle to represent it, and fill that handle in with
* references into the net.
*/
static void __compile_net(char*label,
char*name, char*array_label, unsigned long array_addr,
int msb, int lsb,
bool signed_flag, bool net8_flag, bool local_flag,
unsigned argc, struct symb_s*argv)
static void __compile_net2(vvp_net_t*node, char*my_label, char*name,
int msb, int lsb,
bool signed_flag, bool net8_flag, bool local_flag)
{
unsigned wid = ((msb > lsb)? msb-lsb : lsb-msb) + 1;
// XXXX Forgot how to implement net arrays...
assert(array_label == 0);
assert(argc == 1);
vvp_net_t*node = vvp_net_lookup(argv[0].text);
if (node == 0) {
cerr << "Internal error: vvp_net_lookup fails: "
<< argv[0].text << endl;
}
assert(node);
vvp_wire_base*vsig = dynamic_cast<vvp_wire_base*>(node->fil);
@ -191,18 +233,66 @@ static void __compile_net(char*label,
/* Make the vpiHandle for the reg. */
obj = vpip_make_net(name, msb, lsb, signed_flag, node);
/* This attaches the label to the vpiHandle */
compile_vpi_symbol(label, obj);
compile_vpi_symbol(my_label, obj);
}
if (obj)
vpip_attach_to_current_scope(obj);
if (obj) vpip_attach_to_current_scope(obj);
free(my_label);
delete[] name;
}
static void __compile_net(char*label,
char*name, char*array_label, unsigned long array_addr,
int msb, int lsb,
bool signed_flag, bool net8_flag, bool local_flag,
unsigned argc, struct symb_s*argv)
{
// XXXX Forgot how to implement net arrays...
assert(array_label == 0);
assert(argc == 1);
vvp_net_t*node = vvp_net_lookup(argv[0].text);
if (node == 0) {
/* No existing net, but the string value may be a
constant. In that case, we will wind up generating a
bufz node that can carry the constant value. */
node = create_constant_node(label, argv[0].text);
}
if (node == 0) {
__compile_net_resolv*res = new __compile_net_resolv(argv[0].text,
label, name, msb, lsb,
signed_flag, net8_flag, local_flag);
resolv_submit(res);
return;
cerr << __FILE__ << ":" << __LINE__ << ": Internal error: "
<< "vvp_net_lookup fails: " << argv[0].text << endl;
}
assert(node);
if (name) {
__compile_net2(node, label, name, msb, lsb,
signed_flag, net8_flag, local_flag);
} else {
free(label);
if (name) delete[] name;
if (array_label) free(array_label);
}
free(label);
if (name) delete[] name;
if (array_label) free(array_label);
free(argv);
}
bool __compile_net_resolv::resolve(bool msg_flag)
{
vvp_net_t*node = vvp_net_lookup(label());
if (node == 0) {
return false;
}
__compile_net2(node, my_label_, name_, msb_, lsb_, signed_flag_, net8_flag_, local_flag_);
return true;
}
void compile_net(char*label, char*name, int msb, int lsb,
bool signed_flag, bool net8_flag, bool local_flag,
unsigned argc, struct symb_s*argv)