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:
parent
dc47c2b6e4
commit
9f11a23611
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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<";
|
||||
|
|
|
|||
|
|
@ -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&);
|
||||
|
||||
|
|
|
|||
132
vvp/words.cc
132
vvp/words.cc
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Reference in New Issue