Merge branch 'master' of git://icarus.com/~steve-icarus/verilog into vhdl
This commit is contained in:
commit
f1a2e71aab
|
|
@ -21,10 +21,6 @@
|
||||||
|
|
||||||
# include "AStatement.h"
|
# include "AStatement.h"
|
||||||
|
|
||||||
AStatement::~AStatement()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
AContrib::AContrib(PExpr*lv, PExpr*rv)
|
AContrib::AContrib(PExpr*lv, PExpr*rv)
|
||||||
: lval_(lv), rval_(rv)
|
: lval_(lv), rval_(rv)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
34
AStatement.h
34
AStatement.h
|
|
@ -20,37 +20,30 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
# include <map>
|
# include <map>
|
||||||
|
# include "ivl_target.h"
|
||||||
# include "StringHeap.h"
|
# include "StringHeap.h"
|
||||||
# include "LineInfo.h"
|
# include "LineInfo.h"
|
||||||
|
# include "Statement.h"
|
||||||
# include "PExpr.h"
|
# include "PExpr.h"
|
||||||
|
|
||||||
class PExpr;
|
class PExpr;
|
||||||
|
class NetAnalog;
|
||||||
class AStatement : public LineInfo {
|
class NetScope;
|
||||||
|
class Design;
|
||||||
public:
|
|
||||||
AStatement() { }
|
|
||||||
virtual ~AStatement() =0;
|
|
||||||
|
|
||||||
virtual void dump(ostream&out, unsigned ind) const;
|
|
||||||
|
|
||||||
private: // not implemented
|
|
||||||
AStatement(const AStatement&);
|
|
||||||
AStatement& operator= (const AStatement&);
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A contribution statement is like an assignment: there is an l-value
|
* A contribution statement is like an assignment: there is an l-value
|
||||||
* expression and an r-value expression. The l-value is a branch probe
|
* expression and an r-value expression. The l-value is a branch probe
|
||||||
* expression.
|
* expression.
|
||||||
*/
|
*/
|
||||||
class AContrib : public AStatement {
|
class AContrib : public Statement {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AContrib(PExpr*lval, PExpr*rval);
|
AContrib(PExpr*lval, PExpr*rval);
|
||||||
~AContrib();
|
~AContrib();
|
||||||
|
|
||||||
virtual void dump(ostream&out, unsigned ind) const;
|
virtual void dump(ostream&out, unsigned ind) const;
|
||||||
|
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PExpr*lval_;
|
PExpr*lval_;
|
||||||
|
|
@ -65,21 +58,24 @@ class AContrib : public AStatement {
|
||||||
class AProcess : public LineInfo {
|
class AProcess : public LineInfo {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum Type { PR_INITIAL, PR_ALWAYS };
|
AProcess(ivl_process_type_t t, Statement*st)
|
||||||
|
|
||||||
AProcess(Type t, AStatement*st)
|
|
||||||
: type_(t), statement_(st) { }
|
: type_(t), statement_(st) { }
|
||||||
|
|
||||||
~AProcess();
|
~AProcess();
|
||||||
|
|
||||||
|
bool elaborate(Design*des, NetScope*scope) const;
|
||||||
|
|
||||||
|
ivl_process_type_t type() const { return type_; }
|
||||||
|
Statement*statement() { return statement_; }
|
||||||
|
|
||||||
map<perm_string,PExpr*> attributes;
|
map<perm_string,PExpr*> attributes;
|
||||||
|
|
||||||
// Dump the analog process
|
// Dump the analog process
|
||||||
void dump(ostream&out, unsigned ind) const;
|
void dump(ostream&out, unsigned ind) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Type type_;
|
ivl_process_type_t type_;
|
||||||
AStatement*statement_;
|
Statement*statement_;
|
||||||
|
|
||||||
private: // not implemented
|
private: // not implemented
|
||||||
AProcess(const AProcess&);
|
AProcess(const AProcess&);
|
||||||
|
|
|
||||||
|
|
@ -116,11 +116,12 @@ distclean: clean
|
||||||
TT = t-dll.o t-dll-api.o t-dll-expr.o t-dll-proc.o
|
TT = t-dll.o t-dll-api.o t-dll-expr.o t-dll-proc.o
|
||||||
FF = cprop.o nodangle.o synth.o synth2.o syn-rules.o
|
FF = cprop.o nodangle.o synth.o synth2.o syn-rules.o
|
||||||
|
|
||||||
O = main.o async.o design_dump.o discipline.o dup_expr.o elaborate.o elab_expr.o \
|
O = main.o async.o design_dump.o discipline.o dup_expr.o \
|
||||||
|
elaborate.o elab_expr.o elaborate_analog.o \
|
||||||
elab_lval.o elab_net.o elab_pexpr.o elab_scope.o \
|
elab_lval.o elab_net.o elab_pexpr.o elab_scope.o \
|
||||||
elab_sig.o emit.o eval.o eval_attrib.o \
|
elab_sig.o elab_sig_analog.o emit.o eval.o eval_attrib.o \
|
||||||
eval_tree.o expr_synth.o functor.o lexor.o lexor_keyword.o link_const.o \
|
eval_tree.o expr_synth.o functor.o lexor.o lexor_keyword.o link_const.o \
|
||||||
load_module.o netlist.o netmisc.o net_assign.o \
|
load_module.o netlist.o netmisc.o net_analog.o net_assign.o \
|
||||||
net_design.o net_event.o net_expr.o net_func.o \
|
net_design.o net_event.o net_expr.o net_func.o \
|
||||||
net_link.o net_modulo.o net_nex_input.o net_nex_output.o \
|
net_link.o net_modulo.o net_nex_input.o net_nex_output.o \
|
||||||
net_proc.o net_scope.o net_tran.o net_udp.o pad_to_width.o \
|
net_proc.o net_scope.o net_tran.o net_udp.o pad_to_width.o \
|
||||||
|
|
|
||||||
12
Module.cc
12
Module.cc
|
|
@ -43,7 +43,7 @@ void Module::add_gate(PGate*gate)
|
||||||
|
|
||||||
unsigned Module::port_count() const
|
unsigned Module::port_count() const
|
||||||
{
|
{
|
||||||
return ports.count();
|
return ports.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -51,10 +51,10 @@ unsigned Module::port_count() const
|
||||||
* module. If the port is internally unconnected, return an empty
|
* module. If the port is internally unconnected, return an empty
|
||||||
* array.
|
* array.
|
||||||
*/
|
*/
|
||||||
const svector<PEIdent*>& Module::get_port(unsigned idx) const
|
const vector<PEIdent*>& Module::get_port(unsigned idx) const
|
||||||
{
|
{
|
||||||
assert(idx < ports.count());
|
assert(idx < ports.size());
|
||||||
static svector<PEIdent*> zero;
|
static const vector<PEIdent*> zero;
|
||||||
|
|
||||||
if (ports[idx])
|
if (ports[idx])
|
||||||
return ports[idx]->expr;
|
return ports[idx]->expr;
|
||||||
|
|
@ -65,7 +65,7 @@ const svector<PEIdent*>& Module::get_port(unsigned idx) const
|
||||||
unsigned Module::find_port(const char*name) const
|
unsigned Module::find_port(const char*name) const
|
||||||
{
|
{
|
||||||
assert(name != 0);
|
assert(name != 0);
|
||||||
for (unsigned idx = 0 ; idx < ports.count() ; idx += 1) {
|
for (unsigned idx = 0 ; idx < ports.size() ; idx += 1) {
|
||||||
if (ports[idx] == 0) {
|
if (ports[idx] == 0) {
|
||||||
/* It is possible to have undeclared ports. These
|
/* It is possible to have undeclared ports. These
|
||||||
are ports that are skipped in the declaration,
|
are ports that are skipped in the declaration,
|
||||||
|
|
@ -79,7 +79,7 @@ unsigned Module::find_port(const char*name) const
|
||||||
return idx;
|
return idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ports.count();
|
return ports.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
8
Module.h
8
Module.h
|
|
@ -22,8 +22,8 @@
|
||||||
|
|
||||||
# include <list>
|
# include <list>
|
||||||
# include <map>
|
# include <map>
|
||||||
|
# include <vector>
|
||||||
# include <utility>
|
# include <utility>
|
||||||
# include "svector.h"
|
|
||||||
# include "StringHeap.h"
|
# include "StringHeap.h"
|
||||||
# include "HName.h"
|
# include "HName.h"
|
||||||
# include "named.h"
|
# include "named.h"
|
||||||
|
|
@ -59,7 +59,7 @@ class Module : public PScope, public LineInfo {
|
||||||
public:
|
public:
|
||||||
struct port_t {
|
struct port_t {
|
||||||
perm_string name;
|
perm_string name;
|
||||||
svector<PEIdent*> expr;
|
vector<PEIdent*> expr;
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
@ -98,7 +98,7 @@ class Module : public PScope, public LineInfo {
|
||||||
|
|
||||||
/* This is an array of port descriptors, which is in turn a
|
/* This is an array of port descriptors, which is in turn a
|
||||||
named array of PEident pointers. */
|
named array of PEident pointers. */
|
||||||
svector<port_t*> ports;
|
vector<port_t*> ports;
|
||||||
|
|
||||||
map<perm_string,PExpr*> attributes;
|
map<perm_string,PExpr*> attributes;
|
||||||
|
|
||||||
|
|
@ -126,7 +126,7 @@ class Module : public PScope, public LineInfo {
|
||||||
void add_gate(PGate*gate);
|
void add_gate(PGate*gate);
|
||||||
|
|
||||||
unsigned port_count() const;
|
unsigned port_count() const;
|
||||||
const svector<PEIdent*>& get_port(unsigned idx) const;
|
const vector<PEIdent*>& get_port(unsigned idx) const;
|
||||||
unsigned find_port(const char*name) const;
|
unsigned find_port(const char*name) const;
|
||||||
|
|
||||||
PGate* get_gate(perm_string name);
|
PGate* get_gate(perm_string name);
|
||||||
|
|
|
||||||
69
PExpr.cc
69
PExpr.cc
|
|
@ -24,6 +24,7 @@
|
||||||
# include "compiler.h"
|
# include "compiler.h"
|
||||||
# include "PExpr.h"
|
# include "PExpr.h"
|
||||||
# include "Module.h"
|
# include "Module.h"
|
||||||
|
# include "netmisc.h"
|
||||||
# include <typeinfo>
|
# include <typeinfo>
|
||||||
|
|
||||||
PExpr::PExpr()
|
PExpr::PExpr()
|
||||||
|
|
@ -35,6 +36,11 @@ PExpr::~PExpr()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PExpr::has_aa_term(Design*, NetScope*) const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool PExpr::is_the_same(const PExpr*that) const
|
bool PExpr::is_the_same(const PExpr*that) const
|
||||||
{
|
{
|
||||||
return typeid(this) == typeid(that);
|
return typeid(this) == typeid(that);
|
||||||
|
|
@ -64,6 +70,12 @@ PEBinary::~PEBinary()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PEBinary::has_aa_term(Design*des, NetScope*scope) const
|
||||||
|
{
|
||||||
|
assert(left_ && right_);
|
||||||
|
return left_->has_aa_term(des, scope) || right_->has_aa_term(des, scope);
|
||||||
|
}
|
||||||
|
|
||||||
PEBComp::PEBComp(char op, PExpr*l, PExpr*r)
|
PEBComp::PEBComp(char op, PExpr*l, PExpr*r)
|
||||||
: PEBinary(op, l, r)
|
: PEBinary(op, l, r)
|
||||||
{
|
{
|
||||||
|
|
@ -130,6 +142,15 @@ PECallFunction::~PECallFunction()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PECallFunction::has_aa_term(Design*des, NetScope*scope) const
|
||||||
|
{
|
||||||
|
bool flag = false;
|
||||||
|
for (unsigned idx = 0 ; idx < parms_.size() ; idx += 1) {
|
||||||
|
flag = parms_[idx]->has_aa_term(des, scope) || flag;
|
||||||
|
}
|
||||||
|
return flag;
|
||||||
|
}
|
||||||
|
|
||||||
PEConcat::PEConcat(const svector<PExpr*>&p, PExpr*r)
|
PEConcat::PEConcat(const svector<PExpr*>&p, PExpr*r)
|
||||||
: parms_(p), repeat_(r)
|
: parms_(p), repeat_(r)
|
||||||
{
|
{
|
||||||
|
|
@ -140,6 +161,18 @@ PEConcat::~PEConcat()
|
||||||
delete repeat_;
|
delete repeat_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PEConcat::has_aa_term(Design*des, NetScope*scope) const
|
||||||
|
{
|
||||||
|
bool flag = false;
|
||||||
|
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
|
||||||
|
flag = parms_[idx]->has_aa_term(des, scope) || flag;
|
||||||
|
}
|
||||||
|
if (repeat_)
|
||||||
|
flag = repeat_->has_aa_term(des, scope) || flag;
|
||||||
|
|
||||||
|
return flag;
|
||||||
|
}
|
||||||
|
|
||||||
PEEvent::PEEvent(PEEvent::edge_t t, PExpr*e)
|
PEEvent::PEEvent(PEEvent::edge_t t, PExpr*e)
|
||||||
: type_(t), expr_(e)
|
: type_(t), expr_(e)
|
||||||
{
|
{
|
||||||
|
|
@ -154,6 +187,12 @@ PEEvent::edge_t PEEvent::type() const
|
||||||
return type_;
|
return type_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PEEvent::has_aa_term(Design*des, NetScope*scope) const
|
||||||
|
{
|
||||||
|
assert(expr_);
|
||||||
|
return expr_->has_aa_term(des, scope);
|
||||||
|
}
|
||||||
|
|
||||||
PExpr* PEEvent::expr() const
|
PExpr* PEEvent::expr() const
|
||||||
{
|
{
|
||||||
return expr_;
|
return expr_;
|
||||||
|
|
@ -188,6 +227,22 @@ PEIdent::~PEIdent()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PEIdent::has_aa_term(Design*des, NetScope*scope) const
|
||||||
|
{
|
||||||
|
NetNet* net = 0;
|
||||||
|
const NetExpr*par = 0;
|
||||||
|
NetEvent* eve = 0;
|
||||||
|
|
||||||
|
const NetExpr*ex1, *ex2;
|
||||||
|
|
||||||
|
scope = symbol_search(0, des, scope, path_, net, par, eve, ex1, ex2);
|
||||||
|
|
||||||
|
if (scope)
|
||||||
|
return scope->is_auto();
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
PENumber::PENumber(verinum*vp)
|
PENumber::PENumber(verinum*vp)
|
||||||
: value_(vp)
|
: value_(vp)
|
||||||
{
|
{
|
||||||
|
|
@ -237,6 +292,14 @@ PETernary::~PETernary()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PETernary::has_aa_term(Design*des, NetScope*scope) const
|
||||||
|
{
|
||||||
|
assert(expr_ && tru_ && fal_);
|
||||||
|
return expr_->has_aa_term(des, scope)
|
||||||
|
|| tru_->has_aa_term(des, scope)
|
||||||
|
|| fal_->has_aa_term(des, scope);
|
||||||
|
}
|
||||||
|
|
||||||
PEUnary::PEUnary(char op, PExpr*ex)
|
PEUnary::PEUnary(char op, PExpr*ex)
|
||||||
: op_(op), expr_(ex)
|
: op_(op), expr_(ex)
|
||||||
{
|
{
|
||||||
|
|
@ -245,3 +308,9 @@ PEUnary::PEUnary(char op, PExpr*ex)
|
||||||
PEUnary::~PEUnary()
|
PEUnary::~PEUnary()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PEUnary::has_aa_term(Design*des, NetScope*scope) const
|
||||||
|
{
|
||||||
|
assert(expr_);
|
||||||
|
return expr_->has_aa_term(des, scope);
|
||||||
|
}
|
||||||
|
|
|
||||||
20
PExpr.h
20
PExpr.h
|
|
@ -46,6 +46,10 @@ class PExpr : public LineInfo {
|
||||||
|
|
||||||
virtual void dump(ostream&) const;
|
virtual void dump(ostream&) const;
|
||||||
|
|
||||||
|
// This method tests whether the expression contains any
|
||||||
|
// references to automatically allocated variables.
|
||||||
|
virtual bool has_aa_term(Design*des, NetScope*scope) const;
|
||||||
|
|
||||||
// This method tests the width that the expression wants to
|
// This method tests the width that the expression wants to
|
||||||
// be. It is used by elaboration of assignments to figure out
|
// be. It is used by elaboration of assignments to figure out
|
||||||
// the width of the expression.
|
// the width of the expression.
|
||||||
|
|
@ -156,6 +160,8 @@ class PEConcat : public PExpr {
|
||||||
virtual verinum* eval_const(Design*des, NetScope*sc) const;
|
virtual verinum* eval_const(Design*des, NetScope*sc) const;
|
||||||
virtual void dump(ostream&) const;
|
virtual void dump(ostream&) const;
|
||||||
|
|
||||||
|
virtual bool has_aa_term(Design*des, NetScope*scope) const;
|
||||||
|
|
||||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||||
unsigned min, unsigned lval,
|
unsigned min, unsigned lval,
|
||||||
ivl_variable_type_t&expr_type,
|
ivl_variable_type_t&expr_type,
|
||||||
|
|
@ -200,6 +206,8 @@ class PEEvent : public PExpr {
|
||||||
|
|
||||||
virtual void dump(ostream&) const;
|
virtual void dump(ostream&) const;
|
||||||
|
|
||||||
|
virtual bool has_aa_term(Design*des, NetScope*scope) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
edge_t type_;
|
edge_t type_;
|
||||||
PExpr *expr_;
|
PExpr *expr_;
|
||||||
|
|
@ -247,6 +255,9 @@ class PEIdent : public PExpr {
|
||||||
void append_name(perm_string);
|
void append_name(perm_string);
|
||||||
|
|
||||||
virtual void dump(ostream&) const;
|
virtual void dump(ostream&) const;
|
||||||
|
|
||||||
|
virtual bool has_aa_term(Design*des, NetScope*scope) const;
|
||||||
|
|
||||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||||
unsigned min, unsigned lval,
|
unsigned min, unsigned lval,
|
||||||
ivl_variable_type_t&expr_type,
|
ivl_variable_type_t&expr_type,
|
||||||
|
|
@ -420,6 +431,8 @@ class PEUnary : public PExpr {
|
||||||
|
|
||||||
virtual void dump(ostream&out) const;
|
virtual void dump(ostream&out) const;
|
||||||
|
|
||||||
|
virtual bool has_aa_term(Design*des, NetScope*scope) const;
|
||||||
|
|
||||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||||
unsigned min, unsigned lval,
|
unsigned min, unsigned lval,
|
||||||
ivl_variable_type_t&expr_type,
|
ivl_variable_type_t&expr_type,
|
||||||
|
|
@ -448,6 +461,8 @@ class PEBinary : public PExpr {
|
||||||
|
|
||||||
virtual void dump(ostream&out) const;
|
virtual void dump(ostream&out) const;
|
||||||
|
|
||||||
|
virtual bool has_aa_term(Design*des, NetScope*scope) const;
|
||||||
|
|
||||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||||
unsigned min, unsigned lval,
|
unsigned min, unsigned lval,
|
||||||
ivl_variable_type_t&expr_type,
|
ivl_variable_type_t&expr_type,
|
||||||
|
|
@ -541,6 +556,9 @@ class PETernary : public PExpr {
|
||||||
~PETernary();
|
~PETernary();
|
||||||
|
|
||||||
virtual void dump(ostream&out) const;
|
virtual void dump(ostream&out) const;
|
||||||
|
|
||||||
|
virtual bool has_aa_term(Design*des, NetScope*scope) const;
|
||||||
|
|
||||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||||
unsigned min, unsigned lval,
|
unsigned min, unsigned lval,
|
||||||
ivl_variable_type_t&expr_type,
|
ivl_variable_type_t&expr_type,
|
||||||
|
|
@ -579,6 +597,8 @@ class PECallFunction : public PExpr {
|
||||||
|
|
||||||
virtual void dump(ostream &) const;
|
virtual void dump(ostream &) const;
|
||||||
|
|
||||||
|
virtual bool has_aa_term(Design*des, NetScope*scope) const;
|
||||||
|
|
||||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
|
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
|
||||||
int expr_wid, bool sys_task_arg) const;
|
int expr_wid, bool sys_task_arg) const;
|
||||||
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
|
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||||
|
|
|
||||||
4
PWire.cc
4
PWire.cc
|
|
@ -198,13 +198,13 @@ void PWire::set_memory_idx(PExpr*ldx, PExpr*rdx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PWire::set_discipline(discipline_t*d)
|
void PWire::set_discipline(ivl_discipline_t d)
|
||||||
{
|
{
|
||||||
assert(discipline_ == 0);
|
assert(discipline_ == 0);
|
||||||
discipline_ = d;
|
discipline_ = d;
|
||||||
}
|
}
|
||||||
|
|
||||||
discipline_t* PWire::get_discipline(void) const
|
ivl_discipline_t PWire::get_discipline(void) const
|
||||||
{
|
{
|
||||||
return discipline_;
|
return discipline_;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
10
PWire.h
10
PWire.h
|
|
@ -18,9 +18,6 @@
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
#ifdef HAVE_CVS_IDENT
|
|
||||||
#ident "$Id: PWire.h,v 1.21 2007/05/24 04:07:11 steve Exp $"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
# include "netlist.h"
|
# include "netlist.h"
|
||||||
# include "LineInfo.h"
|
# include "LineInfo.h"
|
||||||
|
|
@ -36,7 +33,6 @@ class ostream;
|
||||||
|
|
||||||
class PExpr;
|
class PExpr;
|
||||||
class Design;
|
class Design;
|
||||||
class discipline_t;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The different type of PWire::set_range() calls.
|
* The different type of PWire::set_range() calls.
|
||||||
|
|
@ -82,8 +78,8 @@ class PWire : public LineInfo {
|
||||||
|
|
||||||
void set_memory_idx(PExpr*ldx, PExpr*rdx);
|
void set_memory_idx(PExpr*ldx, PExpr*rdx);
|
||||||
|
|
||||||
void set_discipline(discipline_t*);
|
void set_discipline(ivl_discipline_t);
|
||||||
discipline_t* get_discipline(void) const;
|
ivl_discipline_t get_discipline(void) const;
|
||||||
|
|
||||||
map<perm_string,PExpr*> attributes;
|
map<perm_string,PExpr*> attributes;
|
||||||
|
|
||||||
|
|
@ -115,7 +111,7 @@ class PWire : public LineInfo {
|
||||||
PExpr*lidx_;
|
PExpr*lidx_;
|
||||||
PExpr*ridx_;
|
PExpr*ridx_;
|
||||||
|
|
||||||
discipline_t*discipline_;
|
ivl_discipline_t discipline_;
|
||||||
|
|
||||||
private: // not implemented
|
private: // not implemented
|
||||||
PWire(const PWire&);
|
PWire(const PWire&);
|
||||||
|
|
|
||||||
|
|
@ -228,6 +228,15 @@ void PEventStatement::set_statement(Statement*st)
|
||||||
statement_ = st;
|
statement_ = st;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PEventStatement::has_aa_term(Design*des, NetScope*scope)
|
||||||
|
{
|
||||||
|
bool flag = false;
|
||||||
|
for (unsigned idx = 0 ; idx < expr_.count() ; idx += 1) {
|
||||||
|
flag = expr_[idx]->has_aa_term(des, scope) || flag;
|
||||||
|
}
|
||||||
|
return flag;
|
||||||
|
}
|
||||||
|
|
||||||
PForce::PForce(PExpr*l, PExpr*r)
|
PForce::PForce(PExpr*l, PExpr*r)
|
||||||
: lval_(l), expr_(r)
|
: lval_(l), expr_(r)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
11
Statement.h
11
Statement.h
|
|
@ -20,6 +20,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
# include <string>
|
# include <string>
|
||||||
|
# include "ivl_target.h"
|
||||||
# include "svector.h"
|
# include "svector.h"
|
||||||
# include "StringHeap.h"
|
# include "StringHeap.h"
|
||||||
# include "PDelays.h"
|
# include "PDelays.h"
|
||||||
|
|
@ -46,16 +47,14 @@ class NetScope;
|
||||||
class PProcess : public LineInfo {
|
class PProcess : public LineInfo {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum Type { PR_INITIAL, PR_ALWAYS };
|
PProcess(ivl_process_type_t t, Statement*st)
|
||||||
|
|
||||||
PProcess(Type t, Statement*st)
|
|
||||||
: type_(t), statement_(st) { }
|
: type_(t), statement_(st) { }
|
||||||
|
|
||||||
virtual ~PProcess();
|
virtual ~PProcess();
|
||||||
|
|
||||||
bool elaborate(Design*des, NetScope*scope) const;
|
bool elaborate(Design*des, NetScope*scope) const;
|
||||||
|
|
||||||
Type type() const { return type_; }
|
ivl_process_type_t type() const { return type_; }
|
||||||
Statement*statement() { return statement_; }
|
Statement*statement() { return statement_; }
|
||||||
|
|
||||||
map<perm_string,PExpr*> attributes;
|
map<perm_string,PExpr*> attributes;
|
||||||
|
|
@ -63,7 +62,7 @@ class PProcess : public LineInfo {
|
||||||
virtual void dump(ostream&out, unsigned ind) const;
|
virtual void dump(ostream&out, unsigned ind) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Type type_;
|
ivl_process_type_t type_;
|
||||||
Statement*statement_;
|
Statement*statement_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -348,6 +347,8 @@ class PEventStatement : public Statement {
|
||||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||||
virtual void elaborate_sig(Design*des, NetScope*scope) const;
|
virtual void elaborate_sig(Design*des, NetScope*scope) const;
|
||||||
|
|
||||||
|
bool has_aa_term(Design*des, NetScope*scope);
|
||||||
|
|
||||||
// This method is used to elaborate, but attach a previously
|
// This method is used to elaborate, but attach a previously
|
||||||
// elaborated statement to the event.
|
// elaborated statement to the event.
|
||||||
NetProc* elaborate_st(Design*des, NetScope*scope, NetProc*st) const;
|
NetProc* elaborate_st(Design*des, NetScope*scope, NetProc*st) const;
|
||||||
|
|
|
||||||
33
async.cc
33
async.cc
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2002 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2002-2008 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -16,9 +16,6 @@
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
#ifdef HAVE_CVS_IDENT
|
|
||||||
#ident "$Id: async.cc,v 1.7 2004/01/18 23:26:54 steve Exp $"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
# include "config.h"
|
# include "config.h"
|
||||||
|
|
||||||
|
|
@ -87,34 +84,8 @@ bool NetProc::is_asynchronous()
|
||||||
|
|
||||||
bool NetProcTop::is_asynchronous()
|
bool NetProcTop::is_asynchronous()
|
||||||
{
|
{
|
||||||
if (type_ == NetProcTop::KINITIAL)
|
if (type_ == IVL_PR_INITIAL)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return statement_->is_asynchronous();
|
return statement_->is_asynchronous();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* $Log: async.cc,v $
|
|
||||||
* Revision 1.7 2004/01/18 23:26:54 steve
|
|
||||||
* The is_combinational function really need not recurse.
|
|
||||||
*
|
|
||||||
* Revision 1.6 2003/12/20 00:33:39 steve
|
|
||||||
* More thorough check that NetEvWait is asynchronous.
|
|
||||||
*
|
|
||||||
* Revision 1.5 2003/09/04 20:28:05 steve
|
|
||||||
* Support time0 resolution of combinational threads.
|
|
||||||
*
|
|
||||||
* Revision 1.4 2002/08/18 22:07:16 steve
|
|
||||||
* Detect temporaries in sequential block synthesis.
|
|
||||||
*
|
|
||||||
* Revision 1.3 2002/08/12 01:34:58 steve
|
|
||||||
* conditional ident string using autoconfig.
|
|
||||||
*
|
|
||||||
* Revision 1.2 2002/07/04 00:24:16 steve
|
|
||||||
* initial statements are not asynchronous.
|
|
||||||
*
|
|
||||||
* Revision 1.1 2002/06/30 02:21:31 steve
|
|
||||||
* Add structure for asynchronous logic synthesis.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -189,7 +189,7 @@ void NetNet::dump_net(ostream&o, unsigned ind) const
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (discipline_t*dis = get_discipline())
|
if (ivl_discipline_t dis = get_discipline())
|
||||||
o << " discipline=" << dis->name();
|
o << " discipline=" << dis->name();
|
||||||
|
|
||||||
o << " (eref=" << peek_eref() << ", lref=" << peek_lref() << ")";
|
o << " (eref=" << peek_eref() << ", lref=" << peek_lref() << ")";
|
||||||
|
|
@ -702,11 +702,11 @@ void NetUDP::dump_node(ostream&o, unsigned ind) const
|
||||||
void NetProcTop::dump(ostream&o, unsigned ind) const
|
void NetProcTop::dump(ostream&o, unsigned ind) const
|
||||||
{
|
{
|
||||||
switch (type_) {
|
switch (type_) {
|
||||||
case NetProcTop::KINITIAL:
|
case IVL_PR_INITIAL:
|
||||||
o << "initial /* " << get_fileline() << " in "
|
o << "initial /* " << get_fileline() << " in "
|
||||||
<< scope_path(scope_) << " */" << endl;
|
<< scope_path(scope_) << " */" << endl;
|
||||||
break;
|
break;
|
||||||
case NetProcTop::KALWAYS:
|
case IVL_PR_ALWAYS:
|
||||||
o << "always /* " << get_fileline() << " in "
|
o << "always /* " << get_fileline() << " in "
|
||||||
<< scope_path(scope_) << " */" << endl;
|
<< scope_path(scope_) << " */" << endl;
|
||||||
break;
|
break;
|
||||||
|
|
@ -720,6 +720,23 @@ void NetProcTop::dump(ostream&o, unsigned ind) const
|
||||||
statement_->dump(o, ind+2);
|
statement_->dump(o, ind+2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NetAnalogTop::dump(ostream&o, unsigned ind) const
|
||||||
|
{
|
||||||
|
switch (type_) {
|
||||||
|
case IVL_PR_INITIAL:
|
||||||
|
o << "analog initial /* " << get_fileline() << " in "
|
||||||
|
<< scope_path(scope_) << " */" << endl;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IVL_PR_ALWAYS:
|
||||||
|
o << "analog /* " << get_fileline() << " in "
|
||||||
|
<< scope_path(scope_) << " */" << endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
statement_->dump(o, ind+2);
|
||||||
|
}
|
||||||
|
|
||||||
void NetAlloc::dump(ostream&o, unsigned ind) const
|
void NetAlloc::dump(ostream&o, unsigned ind) const
|
||||||
{
|
{
|
||||||
o << setw(ind) << "// allocate storage : " << scope_path(scope_) << endl;
|
o << setw(ind) << "// allocate storage : " << scope_path(scope_) << endl;
|
||||||
|
|
@ -868,6 +885,15 @@ void NetCondit::dump(ostream&o, unsigned ind) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NetContribution::dump(ostream&o, unsigned ind) const
|
||||||
|
{
|
||||||
|
o << setw(ind) << "";
|
||||||
|
lval_->dump(o);
|
||||||
|
o << " <+ ";
|
||||||
|
rval_->dump(o);
|
||||||
|
o << ";" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
void NetDeassign::dump(ostream&o, unsigned ind) const
|
void NetDeassign::dump(ostream&o, unsigned ind) const
|
||||||
{
|
{
|
||||||
o << setw(ind) << "" << "deassign ";
|
o << setw(ind) << "" << "deassign ";
|
||||||
|
|
@ -1491,4 +1517,6 @@ void Design::dump(ostream&o) const
|
||||||
for (const NetProcTop*idx = procs_ ; idx ; idx = idx->next_)
|
for (const NetProcTop*idx = procs_ ; idx ; idx = idx->next_)
|
||||||
idx->dump(o, 0);
|
idx->dump(o, 0);
|
||||||
|
|
||||||
|
for (const NetAnalogTop*idx = aprocs_ ; idx ; idx = idx->next_)
|
||||||
|
idx->dump(o, 0);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ participating in the Icarus Verilog development process. That
|
||||||
information will not be repeated here.
|
information will not be repeated here.
|
||||||
|
|
||||||
What this documentation *will* cover is the gross structure of the
|
What this documentation *will* cover is the gross structure of the
|
||||||
Icarus Verilog core compiler source. This will help orient you to the
|
Icarus Verilog compiler source. This will help orient you to the
|
||||||
source code itself, so that you can find the global parts where you
|
source code itself, so that you can find the global parts where you
|
||||||
can look for even better detail.
|
can look for even better detail.
|
||||||
|
|
||||||
|
|
@ -40,7 +40,7 @@ on the core itself.
|
||||||
- The loadable code generators (tgt-*/)
|
- The loadable code generators (tgt-*/)
|
||||||
|
|
||||||
This core compiler, after it is finished with parsing and semantic
|
This core compiler, after it is finished with parsing and semantic
|
||||||
analysis, uses loadable code generators to emit code for suppoted
|
analysis, uses loadable code generators to emit code for supported
|
||||||
targets. The tgt-*/ directories contains the source for the target
|
targets. The tgt-*/ directories contains the source for the target
|
||||||
code generators that are bundled with Icarus Verilog. The tgt-vvp/
|
code generators that are bundled with Icarus Verilog. The tgt-vvp/
|
||||||
directory in particular contains the code generator for the vvp
|
directory in particular contains the code generator for the vvp
|
||||||
|
|
@ -65,20 +65,20 @@ and the source is in this subdirectory.
|
||||||
|
|
||||||
The Icarus Verilog support for the deprecated PLI-1 is in this
|
The Icarus Verilog support for the deprecated PLI-1 is in this
|
||||||
subdirectory. The vvp runtime does not directly support the
|
subdirectory. The vvp runtime does not directly support the
|
||||||
PLI-1. Insead, the libveriuser library emulates it using the builtin
|
PLI-1. Instead, the libveriuser library emulates it using the builtin
|
||||||
PLI-2 support.
|
PLI-2 support.
|
||||||
|
|
||||||
- The Cadence PLI module compatibility module (cadpli/)
|
- The Cadence PLI module compatibility module (cadpli/)
|
||||||
|
|
||||||
It is possible in some specialized situations to load and execute
|
It is possible in some specialized situations to load and execute
|
||||||
PLI-1 code writen for Verilog-XL. This directory contains the source
|
PLI-1 code written for Verilog-XL. This directory contains the source
|
||||||
for the module that provides the Cadence PLI interface.
|
for the module that provides the Cadence PLI interface.
|
||||||
|
|
||||||
|
|
||||||
* The Core Compiler
|
* The Core Compiler
|
||||||
|
|
||||||
The "ivl" binary is the core compiler that does the heavy lifting of
|
The "ivl" binary is the core compiler that does the heavy lifting of
|
||||||
compiling the Veriog source (including libraries) and generating the
|
compiling the Verilog source (including libraries) and generating the
|
||||||
output. This is the most complex component of the Icarus Verilog
|
output. This is the most complex component of the Icarus Verilog
|
||||||
compilation system.
|
compilation system.
|
||||||
|
|
||||||
|
|
@ -86,8 +86,8 @@ The process in the abstract starts with the Verilog lexical analysis
|
||||||
and parsing to generate an internal "pform". The pform is then
|
and parsing to generate an internal "pform". The pform is then
|
||||||
translated by elaboration into the "netlist" form. The netlist is
|
translated by elaboration into the "netlist" form. The netlist is
|
||||||
processed by some functors (which include some optimizations and
|
processed by some functors (which include some optimizations and
|
||||||
optional synthesys) then is translated into the ivl_target internal
|
optional synthesis) then is translated into the ivl_target internal
|
||||||
form. And finallly, the ivl_target form is passed via the ivl_target.h
|
form. And finally, the ivl_target form is passed via the ivl_target.h
|
||||||
API to the code generators.
|
API to the code generators.
|
||||||
|
|
||||||
- Lexical Analysis
|
- Lexical Analysis
|
||||||
|
|
@ -105,9 +105,9 @@ large set of potential keywords.
|
||||||
- Parsing
|
- Parsing
|
||||||
|
|
||||||
The parser input file "parse.y" is passed to the "bison" program to
|
The parser input file "parse.y" is passed to the "bison" program to
|
||||||
generate the parser. The parser uses the functions in parse*.,
|
generate the parser. The parser uses the functions in parse*.h,
|
||||||
parse*.cc, pform*.h and pform*.cc to generate the pform from the
|
parse*.cc, pform.h, and pform*.cc to generate the pform from the
|
||||||
stream of input tokens. The pfrom is what compiler writers call a
|
stream of input tokens. The pform is what compiler writers call a
|
||||||
"decorated parse tree".
|
"decorated parse tree".
|
||||||
|
|
||||||
The pform itself is described by the classes in the header files
|
The pform itself is described by the classes in the header files
|
||||||
|
|
|
||||||
|
|
@ -28,12 +28,12 @@ nature_t::~nature_t()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
discipline_t::discipline_t(perm_string name__, ddomain_t domain__,
|
ivl_discipline_s::ivl_discipline_s(perm_string name__, ivl_dis_domain_t domain__,
|
||||||
nature_t*pot, nature_t*flow__)
|
nature_t*pot, nature_t*flow__)
|
||||||
: name_(name__), domain_(domain__), potential_(pot), flow_(flow__)
|
: name_(name__), domain_(domain__), potential_(pot), flow_(flow__)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
discipline_t::~discipline_t()
|
ivl_discipline_s::~ivl_discipline_s()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
||||||
20
discipline.h
20
discipline.h
|
|
@ -28,10 +28,10 @@
|
||||||
# include "StringHeap.h"
|
# include "StringHeap.h"
|
||||||
# include <iostream>
|
# include <iostream>
|
||||||
# include <map>
|
# include <map>
|
||||||
|
# include "ivl_target.h"
|
||||||
# include "LineInfo.h"
|
# include "LineInfo.h"
|
||||||
|
|
||||||
typedef enum { DD_NONE, DD_DISCRETE, DD_CONTINUOUS } ddomain_t;
|
extern std::ostream& operator << (std::ostream&, ivl_dis_domain_t);
|
||||||
extern std::ostream& operator << (std::ostream&, ddomain_t);
|
|
||||||
|
|
||||||
class nature_t : public LineInfo {
|
class nature_t : public LineInfo {
|
||||||
public:
|
public:
|
||||||
|
|
@ -47,30 +47,30 @@ class nature_t : public LineInfo {
|
||||||
perm_string access_;
|
perm_string access_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class discipline_t : public LineInfo {
|
class ivl_discipline_s : public LineInfo {
|
||||||
public:
|
public:
|
||||||
explicit discipline_t (perm_string name, ddomain_t dom,
|
explicit ivl_discipline_s (perm_string name, ivl_dis_domain_t dom,
|
||||||
nature_t*pot, nature_t*flow);
|
nature_t*pot, nature_t*flow);
|
||||||
~discipline_t();
|
~ivl_discipline_s();
|
||||||
|
|
||||||
perm_string name() const { return name_; }
|
perm_string name() const { return name_; }
|
||||||
ddomain_t domain() const { return domain_; }
|
ivl_dis_domain_t domain() const { return domain_; }
|
||||||
const nature_t*potential() const { return potential_; }
|
const nature_t*potential() const { return potential_; }
|
||||||
const nature_t*flow() const { return flow_; }
|
const nature_t*flow() const { return flow_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
perm_string name_;
|
perm_string name_;
|
||||||
ddomain_t domain_;
|
ivl_dis_domain_t domain_;
|
||||||
nature_t*potential_;
|
nature_t*potential_;
|
||||||
nature_t*flow_;
|
nature_t*flow_;
|
||||||
|
|
||||||
private: // not implemented
|
private: // not implemented
|
||||||
discipline_t(const discipline_t&);
|
ivl_discipline_s(const ivl_discipline_s&);
|
||||||
discipline_t& operator = (const discipline_t&);
|
ivl_discipline_s& operator = (const ivl_discipline_s&);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern map<perm_string,nature_t*> natures;
|
extern map<perm_string,nature_t*> natures;
|
||||||
extern map<perm_string,discipline_t*> disciplines;
|
extern map<perm_string,ivl_discipline_t> disciplines;
|
||||||
// Map access function name to the nature that it accesses.
|
// Map access function name to the nature that it accesses.
|
||||||
extern map<perm_string,nature_t*> access_function_nature;
|
extern map<perm_string,nature_t*> access_function_nature;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -263,6 +263,7 @@ static const char*my_tempfile(const char*str, FILE**fout)
|
||||||
static int t_version_only(void)
|
static int t_version_only(void)
|
||||||
{
|
{
|
||||||
remove(source_path);
|
remove(source_path);
|
||||||
|
free(source_path);
|
||||||
|
|
||||||
fflush(0);
|
fflush(0);
|
||||||
snprintf(tmp, sizeof tmp, "%s%civlpp -V", pbase, sep);
|
snprintf(tmp, sizeof tmp, "%s%civlpp -V", pbase, sep);
|
||||||
|
|
@ -275,8 +276,11 @@ static int t_version_only(void)
|
||||||
|
|
||||||
if ( ! getenv("IVERILOG_ICONFIG")) {
|
if ( ! getenv("IVERILOG_ICONFIG")) {
|
||||||
remove(iconfig_path);
|
remove(iconfig_path);
|
||||||
|
free(iconfig_path);
|
||||||
remove(defines_path);
|
remove(defines_path);
|
||||||
|
free(defines_path);
|
||||||
remove(compiled_defines_path);
|
remove(compiled_defines_path);
|
||||||
|
free(compiled_defines_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -314,11 +318,15 @@ static int t_preprocess_only(void)
|
||||||
|
|
||||||
rc = system(cmd);
|
rc = system(cmd);
|
||||||
remove(source_path);
|
remove(source_path);
|
||||||
|
free(source_path);
|
||||||
|
|
||||||
if ( ! getenv("IVERILOG_ICONFIG")) {
|
if ( ! getenv("IVERILOG_ICONFIG")) {
|
||||||
remove(iconfig_path);
|
remove(iconfig_path);
|
||||||
|
free(iconfig_path);
|
||||||
remove(defines_path);
|
remove(defines_path);
|
||||||
|
free(defines_path);
|
||||||
remove(compiled_defines_path);
|
remove(compiled_defines_path);
|
||||||
|
free(compiled_defines_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
|
|
@ -332,6 +340,7 @@ static int t_preprocess_only(void)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(cmd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -410,9 +419,13 @@ static int t_compile()
|
||||||
rc = system(cmd);
|
rc = system(cmd);
|
||||||
if ( ! getenv("IVERILOG_ICONFIG")) {
|
if ( ! getenv("IVERILOG_ICONFIG")) {
|
||||||
remove(source_path);
|
remove(source_path);
|
||||||
|
free(source_path);
|
||||||
remove(iconfig_path);
|
remove(iconfig_path);
|
||||||
|
free(iconfig_path);
|
||||||
remove(defines_path);
|
remove(defines_path);
|
||||||
|
free(defines_path);
|
||||||
remove(compiled_defines_path);
|
remove(compiled_defines_path);
|
||||||
|
free(compiled_defines_path);
|
||||||
}
|
}
|
||||||
#ifdef __MINGW32__ /* MinGW just returns the exit status, so return it! */
|
#ifdef __MINGW32__ /* MinGW just returns the exit status, so return it! */
|
||||||
free(cmd);
|
free(cmd);
|
||||||
|
|
|
||||||
|
|
@ -138,6 +138,14 @@ NetEUFunc* NetEUFunc::dup_expr() const
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NetEUBits* NetEUBits::dup_expr() const
|
||||||
|
{
|
||||||
|
NetEUBits*tmp = new NetEUBits(op_, expr_->dup_expr());
|
||||||
|
assert(tmp);
|
||||||
|
tmp->set_line(*this);
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
NetEUnary* NetEUnary::dup_expr() const
|
NetEUnary* NetEUnary::dup_expr() const
|
||||||
{
|
{
|
||||||
NetEUnary*tmp = new NetEUnary(op_, expr_->dup_expr());
|
NetEUnary*tmp = new NetEUnary(op_, expr_->dup_expr());
|
||||||
|
|
|
||||||
30
elab_expr.cc
30
elab_expr.cc
|
|
@ -404,6 +404,16 @@ NetExpr* PEBinary::elaborate_expr_base_div_(Design*des,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The original elaboration of the left and right expressions
|
||||||
|
already tried to elaborate to the expr_wid. If the
|
||||||
|
expressions are not that width by now, then they need to be
|
||||||
|
padded. The divide expression operands must be the width
|
||||||
|
of the output. */
|
||||||
|
if (expr_wid > 0) {
|
||||||
|
lp = pad_to_width(lp, expr_wid);
|
||||||
|
rp = pad_to_width(rp, expr_wid);
|
||||||
|
}
|
||||||
|
|
||||||
NetEBDiv*tmp = new NetEBDiv(op_, lp, rp);
|
NetEBDiv*tmp = new NetEBDiv(op_, lp, rp);
|
||||||
tmp->set_line(*this);
|
tmp->set_line(*this);
|
||||||
|
|
||||||
|
|
@ -1231,7 +1241,7 @@ NetExpr* PECallFunction::elaborate_access_func_(Design*des, NetScope*scope,
|
||||||
NetNet*sig = scope->find_signal(name);
|
NetNet*sig = scope->find_signal(name);
|
||||||
ivl_assert(*this, sig);
|
ivl_assert(*this, sig);
|
||||||
|
|
||||||
discipline_t*dis = sig->get_discipline();
|
ivl_discipline_t dis = sig->get_discipline();
|
||||||
ivl_assert(*this, dis);
|
ivl_assert(*this, dis);
|
||||||
ivl_assert(*this, nature == dis->potential() || nature == dis->flow());
|
ivl_assert(*this, nature == dis->potential() || nature == dis->flow());
|
||||||
|
|
||||||
|
|
@ -1349,12 +1359,26 @@ unsigned PEConcat::test_width(Design*des, NetScope*scope,
|
||||||
{
|
{
|
||||||
expr_type_ = IVL_VT_LOGIC;
|
expr_type_ = IVL_VT_LOGIC;
|
||||||
|
|
||||||
|
unsigned count_width = 0;
|
||||||
|
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1)
|
||||||
|
count_width += parms_[idx]->test_width(des, scope, 0, 0, expr_type__, unsized_flag);
|
||||||
|
|
||||||
|
if (repeat_) {
|
||||||
|
// The repeat expression is self-determined and its own type.
|
||||||
|
ivl_variable_type_t tmp_type = IVL_VT_NO_TYPE;
|
||||||
|
bool tmp_flag = false;
|
||||||
|
repeat_->test_width(des, scope, 0, 0, tmp_type, tmp_flag);
|
||||||
|
|
||||||
|
count_width = 0;
|
||||||
if (debug_elaborate)
|
if (debug_elaborate)
|
||||||
cerr << get_fileline() << ": debug: CONCAT MISSING TEST_WIDTH!" << endl;
|
cerr << get_fileline() << ": debug: "
|
||||||
|
<< "CONCAT MISSING TEST_WIDTH WHEN REPEAT IS PRESENT!"
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
|
||||||
expr_type__ = expr_type_;
|
expr_type__ = expr_type_;
|
||||||
unsized_flag = false;
|
unsized_flag = false;
|
||||||
return 0;
|
return count_width;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Keep track of the concatenation/repeat depth.
|
// Keep track of the concatenation/repeat depth.
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@
|
||||||
# include "PTask.h"
|
# include "PTask.h"
|
||||||
# include "PWire.h"
|
# include "PWire.h"
|
||||||
# include "Statement.h"
|
# include "Statement.h"
|
||||||
|
# include "AStatement.h"
|
||||||
# include "netlist.h"
|
# include "netlist.h"
|
||||||
# include "util.h"
|
# include "util.h"
|
||||||
# include <typeinfo>
|
# include <typeinfo>
|
||||||
|
|
@ -1122,8 +1123,9 @@ void PBlock::elaborate_scope(Design*des, NetScope*scope) const
|
||||||
? NetScope::FORK_JOIN
|
? NetScope::FORK_JOIN
|
||||||
: NetScope::BEGIN_END);
|
: NetScope::BEGIN_END);
|
||||||
my_scope->set_line(get_file(), get_lineno());
|
my_scope->set_line(get_file(), get_lineno());
|
||||||
|
my_scope->is_auto(scope->is_auto());
|
||||||
|
|
||||||
// Scan the parameters in the module, and create stub parameter
|
// Scan the parameters in the scope, and create stub parameter
|
||||||
// entries in the scope for the parameter names.
|
// entries in the scope for the parameter names.
|
||||||
|
|
||||||
collect_scope_parameters_(my_scope, parameters);
|
collect_scope_parameters_(my_scope, parameters);
|
||||||
|
|
|
||||||
|
|
@ -150,7 +150,7 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
|
||||||
|
|
||||||
// Scan all the ports of the module, and make sure that each
|
// Scan all the ports of the module, and make sure that each
|
||||||
// is connected to wires that have port declarations.
|
// is connected to wires that have port declarations.
|
||||||
for (unsigned idx = 0 ; idx < ports.count() ; idx += 1) {
|
for (unsigned idx = 0 ; idx < ports.size() ; idx += 1) {
|
||||||
Module::port_t*pp = ports[idx];
|
Module::port_t*pp = ports[idx];
|
||||||
if (pp == 0)
|
if (pp == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -159,7 +159,7 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
|
||||||
// expression are all identifiers that should reference
|
// expression are all identifiers that should reference
|
||||||
// wires within the scope.
|
// wires within the scope.
|
||||||
map<perm_string,PWire*>::const_iterator wt;
|
map<perm_string,PWire*>::const_iterator wt;
|
||||||
for (unsigned cc = 0 ; cc < pp->expr.count() ; cc += 1) {
|
for (unsigned cc = 0 ; cc < pp->expr.size() ; cc += 1) {
|
||||||
pform_name_t port_path (pp->expr[cc]->path());
|
pform_name_t port_path (pp->expr[cc]->path());
|
||||||
// A concatenated wire of a port really should not
|
// A concatenated wire of a port really should not
|
||||||
// have any hierarchy.
|
// have any hierarchy.
|
||||||
|
|
@ -365,7 +365,7 @@ bool PGModule::elaborate_sig_mod_(Design*des, NetScope*scope,
|
||||||
|
|
||||||
NetScope::scope_vec_t instance = scope->instance_arrays[get_name()];
|
NetScope::scope_vec_t instance = scope->instance_arrays[get_name()];
|
||||||
|
|
||||||
for (unsigned idx = 0 ; idx < instance.count() ; idx += 1) {
|
for (unsigned idx = 0 ; idx < instance.size() ; idx += 1) {
|
||||||
// I know a priori that the elaborate_scope created the scope
|
// I know a priori that the elaborate_scope created the scope
|
||||||
// already, so just look it up as a child of the current scope.
|
// already, so just look it up as a child of the current scope.
|
||||||
NetScope*my_scope = instance[idx];
|
NetScope*my_scope = instance[idx];
|
||||||
|
|
@ -1055,7 +1055,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||||
sig->set_signed(get_signed());
|
sig->set_signed(get_signed());
|
||||||
sig->set_isint(get_isint());
|
sig->set_isint(get_isint());
|
||||||
|
|
||||||
if (discipline_t*dis = get_discipline()) {
|
if (ivl_discipline_t dis = get_discipline()) {
|
||||||
sig->set_discipline(dis);
|
sig->set_discipline(dis);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2008 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
|
||||||
|
* General Public License as published by the Free Software
|
||||||
|
* Foundation; either version 2 of the License, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
# include "config.h"
|
||||||
|
|
||||||
|
# include "AStatement.h"
|
||||||
|
|
||||||
|
# include <cstdlib>
|
||||||
|
# include <iostream>
|
||||||
|
|
||||||
169
elaborate.cc
169
elaborate.cc
|
|
@ -938,7 +938,7 @@ NetNet*PGModule::resize_net_to_port_(Design*des, NetScope*scope,
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool need_bufz_for_input_port(const svector<NetNet*>&prts)
|
static bool need_bufz_for_input_port(const vector<NetNet*>&prts)
|
||||||
{
|
{
|
||||||
if (prts[0]->port_type() != NetNet::PINPUT)
|
if (prts[0]->port_type() != NetNet::PINPUT)
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -1051,7 +1051,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
||||||
// later.
|
// later.
|
||||||
|
|
||||||
NetScope::scope_vec_t&instance = scope->instance_arrays[get_name()];
|
NetScope::scope_vec_t&instance = scope->instance_arrays[get_name()];
|
||||||
for (unsigned inst = 0 ; inst < instance.count() ; inst += 1) {
|
for (unsigned inst = 0 ; inst < instance.size() ; inst += 1) {
|
||||||
rmod->elaborate(des, instance[inst]);
|
rmod->elaborate(des, instance[inst]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1079,8 +1079,8 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
||||||
// input. If so, consider printing a port binding
|
// input. If so, consider printing a port binding
|
||||||
// warning.
|
// warning.
|
||||||
if (warn_portbinding) {
|
if (warn_portbinding) {
|
||||||
svector<PEIdent*> mport = rmod->get_port(idx);
|
vector<PEIdent*> mport = rmod->get_port(idx);
|
||||||
if (mport.count() == 0)
|
if (mport.size() == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
perm_string pname = peek_tail_name(mport[0]->path());
|
perm_string pname = peek_tail_name(mport[0]->path());
|
||||||
|
|
@ -1105,26 +1105,26 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
||||||
// Inside the module, the port is zero or more signals
|
// Inside the module, the port is zero or more signals
|
||||||
// that were already elaborated. List all those signals
|
// that were already elaborated. List all those signals
|
||||||
// and the NetNet equivalents, for all the instances.
|
// and the NetNet equivalents, for all the instances.
|
||||||
svector<PEIdent*> mport = rmod->get_port(idx);
|
vector<PEIdent*> mport = rmod->get_port(idx);
|
||||||
svector<NetNet*>prts (mport.count() * instance.count());
|
vector<NetNet*> prts (mport.size() * instance.size());
|
||||||
|
|
||||||
if (debug_elaborate) {
|
if (debug_elaborate) {
|
||||||
cerr << get_fileline() << ": debug: " << get_name()
|
cerr << get_fileline() << ": debug: " << get_name()
|
||||||
<< ": Port " << idx << " has " << prts.count()
|
<< ": Port " << idx << " has " << prts.size()
|
||||||
<< " sub-ports." << endl;
|
<< " sub-ports." << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Count the internal vector bits of the port.
|
// Count the internal vector bits of the port.
|
||||||
unsigned prts_vector_width = 0;
|
unsigned prts_vector_width = 0;
|
||||||
|
|
||||||
for (unsigned inst = 0 ; inst < instance.count() ; inst += 1) {
|
for (unsigned inst = 0 ; inst < instance.size() ; inst += 1) {
|
||||||
// Scan the instances from MSB to LSB. The port
|
// Scan the instances from MSB to LSB. The port
|
||||||
// will be assembled in that order as well.
|
// will be assembled in that order as well.
|
||||||
NetScope*inst_scope = instance[instance.count()-inst-1];
|
NetScope*inst_scope = instance[instance.size()-inst-1];
|
||||||
|
|
||||||
// Scan the module sub-ports for this instance...
|
// Scan the module sub-ports for this instance...
|
||||||
for (unsigned ldx = 0 ; ldx < mport.count() ; ldx += 1) {
|
for (unsigned ldx = 0 ; ldx < mport.size() ; ldx += 1) {
|
||||||
unsigned lbase = inst * mport.count();
|
unsigned lbase = inst * mport.size();
|
||||||
PEIdent*pport = mport[ldx];
|
PEIdent*pport = mport[ldx];
|
||||||
assert(pport);
|
assert(pport);
|
||||||
prts[lbase + ldx]
|
prts[lbase + ldx]
|
||||||
|
|
@ -1147,10 +1147,10 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
||||||
// We know by design that each instance has the same
|
// We know by design that each instance has the same
|
||||||
// width port. Therefore, the prts_pin_count must be an
|
// width port. Therefore, the prts_pin_count must be an
|
||||||
// even multiple of the instance count.
|
// even multiple of the instance count.
|
||||||
assert(prts_vector_width % instance.count() == 0);
|
assert(prts_vector_width % instance.size() == 0);
|
||||||
|
|
||||||
unsigned desired_vector_width = prts_vector_width;
|
unsigned desired_vector_width = prts_vector_width;
|
||||||
if (instance.count() != 1)
|
if (instance.size() != 1)
|
||||||
desired_vector_width = 0;
|
desired_vector_width = 0;
|
||||||
|
|
||||||
// Elaborate the expression that connects to the
|
// Elaborate the expression that connects to the
|
||||||
|
|
@ -1158,7 +1158,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
||||||
// that connects to the port.
|
// that connects to the port.
|
||||||
|
|
||||||
NetNet*sig;
|
NetNet*sig;
|
||||||
if ((prts.count() == 0)
|
if ((prts.size() == 0)
|
||||||
|| (prts[0]->port_type() == NetNet::PINPUT)) {
|
|| (prts[0]->port_type() == NetNet::PINPUT)) {
|
||||||
|
|
||||||
/* Input to module. elaborate the expression to
|
/* Input to module. elaborate the expression to
|
||||||
|
|
@ -1263,7 +1263,7 @@ v NOTE that this also handles the case that the
|
||||||
assert(sig);
|
assert(sig);
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if ((prts.count() >= 1)
|
if ((prts.size() >= 1)
|
||||||
&& (prts[0]->port_type() != NetNet::PINPUT)) {
|
&& (prts[0]->port_type() != NetNet::PINPUT)) {
|
||||||
assert(sig->type() != NetNet::REG);
|
assert(sig->type() != NetNet::REG);
|
||||||
}
|
}
|
||||||
|
|
@ -1271,13 +1271,13 @@ v NOTE that this also handles the case that the
|
||||||
|
|
||||||
/* If we are working with an instance array, then the
|
/* If we are working with an instance array, then the
|
||||||
signal width must match the port width exactly. */
|
signal width must match the port width exactly. */
|
||||||
if ((instance.count() != 1)
|
if ((instance.size() != 1)
|
||||||
&& (sig->vector_width() != prts_vector_width)
|
&& (sig->vector_width() != prts_vector_width)
|
||||||
&& (sig->vector_width() != prts_vector_width/instance.count())) {
|
&& (sig->vector_width() != prts_vector_width/instance.size())) {
|
||||||
cerr << pins[idx]->get_fileline() << ": error: "
|
cerr << pins[idx]->get_fileline() << ": error: "
|
||||||
<< "Port expression width " << sig->vector_width()
|
<< "Port expression width " << sig->vector_width()
|
||||||
<< " does not match expected width "<< prts_vector_width
|
<< " does not match expected width "<< prts_vector_width
|
||||||
<< " or " << (prts_vector_width/instance.count())
|
<< " or " << (prts_vector_width/instance.size())
|
||||||
<< "." << endl;
|
<< "." << endl;
|
||||||
des->errors += 1;
|
des->errors += 1;
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -1292,7 +1292,7 @@ v NOTE that this also handles the case that the
|
||||||
// Check that the parts have matching pin counts. If
|
// Check that the parts have matching pin counts. If
|
||||||
// not, they are different widths. Note that idx is 0
|
// not, they are different widths. Note that idx is 0
|
||||||
// based, but users count parameter positions from 1.
|
// based, but users count parameter positions from 1.
|
||||||
if ((instance.count() == 1)
|
if ((instance.size() == 1)
|
||||||
&& (prts_vector_width != sig->vector_width())) {
|
&& (prts_vector_width != sig->vector_width())) {
|
||||||
const char *tmp3 = rmod->ports[idx]->name.str();
|
const char *tmp3 = rmod->ports[idx]->name.str();
|
||||||
bool as_signed = false;
|
bool as_signed = false;
|
||||||
|
|
@ -1363,7 +1363,7 @@ v NOTE that this also handles the case that the
|
||||||
// Connect this many of the port pins. If the expression
|
// Connect this many of the port pins. If the expression
|
||||||
// is too small, then reduce the number of connects.
|
// is too small, then reduce the number of connects.
|
||||||
unsigned ccount = prts_vector_width;
|
unsigned ccount = prts_vector_width;
|
||||||
if (instance.count() == 1 && sig->vector_width() < ccount)
|
if (instance.size() == 1 && sig->vector_width() < ccount)
|
||||||
ccount = sig->vector_width();
|
ccount = sig->vector_width();
|
||||||
|
|
||||||
// The spin_modulus is the width of the signal (not the
|
// The spin_modulus is the width of the signal (not the
|
||||||
|
|
@ -1371,7 +1371,7 @@ v NOTE that this also handles the case that the
|
||||||
// signals wide enough for a single instance to be
|
// signals wide enough for a single instance to be
|
||||||
// connected to all the instances.
|
// connected to all the instances.
|
||||||
unsigned spin_modulus = prts_vector_width;
|
unsigned spin_modulus = prts_vector_width;
|
||||||
if (instance.count() != 1)
|
if (instance.size() != 1)
|
||||||
spin_modulus = sig->vector_width();
|
spin_modulus = sig->vector_width();
|
||||||
|
|
||||||
// Now scan the concatenation that makes up the port,
|
// Now scan the concatenation that makes up the port,
|
||||||
|
|
@ -1383,7 +1383,7 @@ v NOTE that this also handles the case that the
|
||||||
NetConcat*ctmp;
|
NetConcat*ctmp;
|
||||||
unsigned spin = 0;
|
unsigned spin = 0;
|
||||||
|
|
||||||
if (prts.count() == 1) {
|
if (prts.size() == 1) {
|
||||||
|
|
||||||
// The simplest case, there are no
|
// The simplest case, there are no
|
||||||
// parts/concatenations on the inside of the
|
// parts/concatenations on the inside of the
|
||||||
|
|
@ -1391,33 +1391,32 @@ v NOTE that this also handles the case that the
|
||||||
// connected directly.
|
// connected directly.
|
||||||
connect(prts[0]->pin(0), sig->pin(0));
|
connect(prts[0]->pin(0), sig->pin(0));
|
||||||
|
|
||||||
} else if (sig->vector_width()==prts_vector_width/instance.count()
|
} else if (sig->vector_width()==prts_vector_width/instance.size()
|
||||||
&& prts.count()/instance.count() == 1) {
|
&& prts.size()/instance.size() == 1) {
|
||||||
|
|
||||||
if (debug_elaborate){
|
if (debug_elaborate){
|
||||||
cerr << get_fileline() << ": debug: " << get_name()
|
cerr << get_fileline() << ": debug: " << get_name()
|
||||||
<< ": Replicating " << prts_vector_width
|
<< ": Replicating " << prts_vector_width
|
||||||
<< " bits across all "
|
<< " bits across all "
|
||||||
<< prts_vector_width/instance.count()
|
<< prts_vector_width/instance.size()
|
||||||
<< " sub-ports." << endl;
|
<< " sub-ports." << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The signal width is exactly the width of a
|
// The signal width is exactly the width of a
|
||||||
// single instance of the port. In this case,
|
// single instance of the port. In this case,
|
||||||
// connect the sig to all the ports identically.
|
// connect the sig to all the ports identically.
|
||||||
for (unsigned ldx = 0 ; ldx < prts.count() ; ldx += 1)
|
for (unsigned ldx = 0 ; ldx < prts.size() ; ldx += 1)
|
||||||
connect(prts[ldx]->pin(0), sig->pin(0));
|
connect(prts[ldx]->pin(0), sig->pin(0));
|
||||||
|
|
||||||
} else switch (prts[0]->port_type()) {
|
} else switch (prts[0]->port_type()) {
|
||||||
case NetNet::POUTPUT:
|
case NetNet::POUTPUT:
|
||||||
ctmp = new NetConcat(scope, scope->local_symbol(),
|
ctmp = new NetConcat(scope, scope->local_symbol(),
|
||||||
prts_vector_width,
|
prts_vector_width, prts.size());
|
||||||
prts.count());
|
|
||||||
des->add_node(ctmp);
|
des->add_node(ctmp);
|
||||||
connect(ctmp->pin(0), sig->pin(0));
|
connect(ctmp->pin(0), sig->pin(0));
|
||||||
for (unsigned ldx = 0 ; ldx < prts.count() ; ldx += 1) {
|
for (unsigned ldx = 0 ; ldx < prts.size() ; ldx += 1) {
|
||||||
connect(ctmp->pin(ldx+1),
|
connect(ctmp->pin(ldx+1),
|
||||||
prts[prts.count()-ldx-1]->pin(0));
|
prts[prts.size()-ldx-1]->pin(0));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -1426,13 +1425,13 @@ v NOTE that this also handles the case that the
|
||||||
cerr << get_fileline() << ": debug: " << get_name()
|
cerr << get_fileline() << ": debug: " << get_name()
|
||||||
<< ": Dividing " << prts_vector_width
|
<< ": Dividing " << prts_vector_width
|
||||||
<< " bits across all "
|
<< " bits across all "
|
||||||
<< prts_vector_width/instance.count()
|
<< prts_vector_width/instance.size()
|
||||||
<< " input sub-ports of port "
|
<< " input sub-ports of port "
|
||||||
<< idx << "." << endl;
|
<< idx << "." << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned ldx = 0 ; ldx < prts.count() ; ldx += 1) {
|
for (unsigned ldx = 0 ; ldx < prts.size() ; ldx += 1) {
|
||||||
NetNet*sp = prts[prts.count()-ldx-1];
|
NetNet*sp = prts[prts.size()-ldx-1];
|
||||||
NetPartSelect*ptmp = new NetPartSelect(sig, spin,
|
NetPartSelect*ptmp = new NetPartSelect(sig, spin,
|
||||||
sp->vector_width(),
|
sp->vector_width(),
|
||||||
NetPartSelect::VP);
|
NetPartSelect::VP);
|
||||||
|
|
@ -2013,6 +2012,14 @@ NetProc* PAssignNB::elaborate(Design*des, NetScope*scope) const
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (scope->is_auto() && lval()->has_aa_term(des, scope)) {
|
||||||
|
cerr << get_fileline() << ": error: automatically allocated "
|
||||||
|
"variables may not be assigned values using non-blocking "
|
||||||
|
"assignments." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Elaborate the l-value. */
|
/* Elaborate the l-value. */
|
||||||
NetAssign_*lv = elaborate_lval(des, scope);
|
NetAssign_*lv = elaborate_lval(des, scope);
|
||||||
if (lv == 0) return 0;
|
if (lv == 0) return 0;
|
||||||
|
|
@ -2043,6 +2050,15 @@ NetProc* PAssignNB::elaborate(Design*des, NetScope*scope) const
|
||||||
NetEvWait*event = 0;
|
NetEvWait*event = 0;
|
||||||
if (count_ != 0 || event_ != 0) {
|
if (count_ != 0 || event_ != 0) {
|
||||||
if (count_ != 0) {
|
if (count_ != 0) {
|
||||||
|
if (scope->is_auto() && count_->has_aa_term(des, scope)) {
|
||||||
|
cerr << get_fileline() << ": error: automatically "
|
||||||
|
"allocated variables may not be referenced "
|
||||||
|
"in intra-assignment event controls of "
|
||||||
|
"non-blocking assignments." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
assert(event_ != 0);
|
assert(event_ != 0);
|
||||||
count = elab_and_eval(des, scope, count_, -1);
|
count = elab_and_eval(des, scope, count_, -1);
|
||||||
if (count == 0) {
|
if (count == 0) {
|
||||||
|
|
@ -2053,6 +2069,15 @@ NetProc* PAssignNB::elaborate(Design*des, NetScope*scope) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (scope->is_auto() && event_->has_aa_term(des, scope)) {
|
||||||
|
cerr << get_fileline() << ": error: automatically "
|
||||||
|
"allocated variables may not be referenced "
|
||||||
|
"in intra-assignment event controls of "
|
||||||
|
"non-blocking assignments." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
NetProc*st = event_->elaborate(des, scope);
|
NetProc*st = event_->elaborate(des, scope);
|
||||||
if (st == 0) {
|
if (st == 0) {
|
||||||
cerr << get_fileline() << ": unable to elaborate "
|
cerr << get_fileline() << ": unable to elaborate "
|
||||||
|
|
@ -2587,6 +2612,22 @@ NetCAssign* PCAssign::elaborate(Design*des, NetScope*scope) const
|
||||||
NetCAssign*dev = 0;
|
NetCAssign*dev = 0;
|
||||||
assert(scope);
|
assert(scope);
|
||||||
|
|
||||||
|
if (scope->is_auto() && lval_->has_aa_term(des, scope)) {
|
||||||
|
cerr << get_fileline() << ": error: automatically allocated "
|
||||||
|
"variables may not be assigned values using procedural "
|
||||||
|
"continuous assignments." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scope->is_auto() && expr_->has_aa_term(des, scope)) {
|
||||||
|
cerr << get_fileline() << ": error: automatically allocated "
|
||||||
|
"variables may not be referenced in procedural "
|
||||||
|
"continuous assignments." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
NetAssign_*lval = lval_->elaborate_lval(des, scope, false);
|
NetAssign_*lval = lval_->elaborate_lval(des, scope, false);
|
||||||
if (lval == 0)
|
if (lval == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -2618,6 +2659,14 @@ NetDeassign* PDeassign::elaborate(Design*des, NetScope*scope) const
|
||||||
{
|
{
|
||||||
assert(scope);
|
assert(scope);
|
||||||
|
|
||||||
|
if (scope->is_auto() && lval_->has_aa_term(des, scope)) {
|
||||||
|
cerr << get_fileline() << ": error: automatically allocated "
|
||||||
|
"variables may not be assigned values using procedural "
|
||||||
|
"continuous assignments." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
NetAssign_*lval = lval_->elaborate_lval(des, scope, false);
|
NetAssign_*lval = lval_->elaborate_lval(des, scope, false);
|
||||||
if (lval == 0)
|
if (lval == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -2876,6 +2925,16 @@ NetProc* PEventStatement::elaborate_st(Design*des, NetScope*scope,
|
||||||
the sub-expression as a net and decide how to handle
|
the sub-expression as a net and decide how to handle
|
||||||
the edge. */
|
the edge. */
|
||||||
|
|
||||||
|
if (scope->is_auto()) {
|
||||||
|
if (! dynamic_cast<PEIdent*>(expr_[idx]->expr())) {
|
||||||
|
cerr << get_fileline() << ": sorry, complex event "
|
||||||
|
"expressions are not yet supported in "
|
||||||
|
"automatic tasks." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool save_flag = error_implicit;
|
bool save_flag = error_implicit;
|
||||||
error_implicit = true;
|
error_implicit = true;
|
||||||
NetExpr*tmp = elab_and_eval(des, scope, expr_[idx]->expr(), 0);
|
NetExpr*tmp = elab_and_eval(des, scope, expr_[idx]->expr(), 0);
|
||||||
|
|
@ -3151,6 +3210,22 @@ NetForce* PForce::elaborate(Design*des, NetScope*scope) const
|
||||||
NetForce*dev = 0;
|
NetForce*dev = 0;
|
||||||
assert(scope);
|
assert(scope);
|
||||||
|
|
||||||
|
if (scope->is_auto() && lval_->has_aa_term(des, scope)) {
|
||||||
|
cerr << get_fileline() << ": error: automatically allocated "
|
||||||
|
"variables may not be assigned values using procedural "
|
||||||
|
"force statements." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scope->is_auto() && expr_->has_aa_term(des, scope)) {
|
||||||
|
cerr << get_fileline() << ": error: automatically allocated "
|
||||||
|
"variables may not be referenced in procedural force "
|
||||||
|
"statements." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
NetAssign_*lval = lval_->elaborate_lval(des, scope, true);
|
NetAssign_*lval = lval_->elaborate_lval(des, scope, true);
|
||||||
if (lval == 0)
|
if (lval == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -3356,6 +3431,14 @@ NetProc* PRelease::elaborate(Design*des, NetScope*scope) const
|
||||||
{
|
{
|
||||||
assert(scope);
|
assert(scope);
|
||||||
|
|
||||||
|
if (scope->is_auto() && lval_->has_aa_term(des, scope)) {
|
||||||
|
cerr << get_fileline() << ": error: automatically allocated "
|
||||||
|
"variables may not be assigned values using procedural "
|
||||||
|
"force statements." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
NetAssign_*lval = lval_->elaborate_lval(des, scope, true);
|
NetAssign_*lval = lval_->elaborate_lval(des, scope, true);
|
||||||
if (lval == 0)
|
if (lval == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -3503,15 +3586,7 @@ bool PProcess::elaborate(Design*des, NetScope*scope) const
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
NetProcTop*top=0;
|
NetProcTop*top=new NetProcTop(scope, type(), cur);
|
||||||
switch (type()) {
|
|
||||||
case PProcess::PR_INITIAL:
|
|
||||||
top = new NetProcTop(scope, NetProcTop::KINITIAL, cur);
|
|
||||||
break;
|
|
||||||
case PProcess::PR_ALWAYS:
|
|
||||||
top = new NetProcTop(scope, NetProcTop::KALWAYS, cur);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
ivl_assert(*this, top);
|
ivl_assert(*this, top);
|
||||||
|
|
||||||
// Evaluate the attributes for this process, if there
|
// Evaluate the attributes for this process, if there
|
||||||
|
|
@ -3536,7 +3611,7 @@ bool PProcess::elaborate(Design*des, NetScope*scope) const
|
||||||
gets into its wait statement before non-combinational
|
gets into its wait statement before non-combinational
|
||||||
code is executed. */
|
code is executed. */
|
||||||
do {
|
do {
|
||||||
if (top->type() != NetProcTop::KALWAYS)
|
if (top->type() != IVL_PR_ALWAYS)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
NetEvWait*st = dynamic_cast<NetEvWait*>(top->statement());
|
NetEvWait*st = dynamic_cast<NetEvWait*>(top->statement());
|
||||||
|
|
@ -3959,6 +4034,12 @@ bool PScope::elaborate_behaviors_(Design*des, NetScope*scope) const
|
||||||
result_flag &= (*st)->elaborate(des, scope);
|
result_flag &= (*st)->elaborate(des, scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (list<AProcess*>::const_iterator st = analog_behaviors.begin()
|
||||||
|
; st != analog_behaviors.end() ; st ++ ) {
|
||||||
|
|
||||||
|
result_flag &= (*st)->elaborate(des, scope);
|
||||||
|
}
|
||||||
|
|
||||||
return result_flag;
|
return result_flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -4046,7 +4127,7 @@ bool Design::check_always_delay() const
|
||||||
* a runtime infinite loop will happen. If we possible have some
|
* a runtime infinite loop will happen. If we possible have some
|
||||||
* delay then print a warning that an infinite loop is possible.
|
* delay then print a warning that an infinite loop is possible.
|
||||||
*/
|
*/
|
||||||
if (pr->type() == NetProcTop::KALWAYS) {
|
if (pr->type() == IVL_PR_ALWAYS) {
|
||||||
DelayType dly_type = pr->statement()->delay_type();
|
DelayType dly_type = pr->statement()->delay_type();
|
||||||
|
|
||||||
if (dly_type == NO_DELAY || dly_type == ZERO_DELAY) {
|
if (dly_type == NO_DELAY || dly_type == ZERO_DELAY) {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2008 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
|
||||||
|
* General Public License as published by the Free Software
|
||||||
|
* Foundation; either version 2 of the License, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
# include "config.h"
|
||||||
|
|
||||||
|
# include "AStatement.h"
|
||||||
|
# include "netlist.h"
|
||||||
|
# include "netmisc.h"
|
||||||
|
# include "util.h"
|
||||||
|
|
||||||
|
# include <typeinfo>
|
||||||
|
|
||||||
|
NetProc* AContrib::elaborate(Design*des, NetScope*scope) const
|
||||||
|
{
|
||||||
|
NetExpr*lval = elab_and_eval(des, scope, lval_, -1);
|
||||||
|
NetExpr*rval = elab_and_eval(des, scope, rval_, -1);
|
||||||
|
|
||||||
|
NetContribution*st = new NetContribution(lval, rval);
|
||||||
|
st->set_line(*this);
|
||||||
|
return st;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AProcess::elaborate(Design*des, NetScope*scope) const
|
||||||
|
{
|
||||||
|
NetProc*statement = statement_->elaborate(des, scope);
|
||||||
|
if (statement == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
NetAnalogTop*top = new NetAnalogTop(scope, type_, statement);
|
||||||
|
|
||||||
|
// Evaluate the attributes for this process, if there
|
||||||
|
// are any. These attributes are to be attached to the
|
||||||
|
// NetProcTop object.
|
||||||
|
struct attrib_list_t*attrib_list = 0;
|
||||||
|
unsigned attrib_list_n = 0;
|
||||||
|
attrib_list = evaluate_attributes(attributes, attrib_list_n, des, scope);
|
||||||
|
|
||||||
|
for (unsigned adx = 0 ; adx < attrib_list_n ; adx += 1)
|
||||||
|
top->attribute(attrib_list[adx].key,
|
||||||
|
attrib_list[adx].val);
|
||||||
|
|
||||||
|
delete[]attrib_list;
|
||||||
|
|
||||||
|
top->set_line(*this);
|
||||||
|
des->add_process(top);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
9
emit.cc
9
emit.cc
|
|
@ -190,6 +190,13 @@ bool NetProcTop::emit(struct target_t*tgt) const
|
||||||
return tgt->process(this);
|
return tgt->process(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool NetAnalogTop::emit(struct target_t*tgt) const
|
||||||
|
{
|
||||||
|
cerr << get_fileline() << ": sorry: "
|
||||||
|
<< "I don't know how to emit for analog processes." << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool NetProc::emit_proc(struct target_t*tgt) const
|
bool NetProc::emit_proc(struct target_t*tgt) const
|
||||||
{
|
{
|
||||||
cerr << "EMIT: Proc type? " << typeid(*this).name() << endl;
|
cerr << "EMIT: Proc type? " << typeid(*this).name() << endl;
|
||||||
|
|
@ -456,6 +463,8 @@ int Design::emit(struct target_t*tgt) const
|
||||||
bool proc_rc = true;
|
bool proc_rc = true;
|
||||||
for (const NetProcTop*idx = procs_ ; idx ; idx = idx->next_)
|
for (const NetProcTop*idx = procs_ ; idx ; idx = idx->next_)
|
||||||
proc_rc &= idx->emit(tgt);
|
proc_rc &= idx->emit(tgt);
|
||||||
|
for (const NetAnalogTop*idx = aprocs_ ; idx ; idx = idx->next_)
|
||||||
|
proc_rc &= idx->emit(tgt);
|
||||||
|
|
||||||
rc = tgt->end_design(this);
|
rc = tgt->end_design(this);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -484,6 +484,7 @@ NetNet* NetEBDiv::synthesize(Design*des, NetScope*scope)
|
||||||
lsig->vector_width(),
|
lsig->vector_width(),
|
||||||
rsig->vector_width());
|
rsig->vector_width());
|
||||||
div->set_line(*this);
|
div->set_line(*this);
|
||||||
|
div->set_signed(has_sign());
|
||||||
des->add_node(div);
|
des->add_node(div);
|
||||||
|
|
||||||
connect(div->pin_DataA(), lsig->pin(0));
|
connect(div->pin_DataA(), lsig->pin(0));
|
||||||
|
|
|
||||||
4
ivl.def
4
ivl.def
|
|
@ -15,6 +15,9 @@ ivl_const_signed
|
||||||
ivl_const_type
|
ivl_const_type
|
||||||
ivl_const_width
|
ivl_const_width
|
||||||
|
|
||||||
|
ivl_discipline_domain
|
||||||
|
ivl_discipline_name
|
||||||
|
|
||||||
ivl_event_any
|
ivl_event_any
|
||||||
ivl_event_basename
|
ivl_event_basename
|
||||||
ivl_event_name
|
ivl_event_name
|
||||||
|
|
@ -172,6 +175,7 @@ ivl_signal_attr_val
|
||||||
ivl_signal_basename
|
ivl_signal_basename
|
||||||
ivl_signal_data_type
|
ivl_signal_data_type
|
||||||
ivl_signal_dimensions
|
ivl_signal_dimensions
|
||||||
|
ivl_signal_discipline
|
||||||
ivl_signal_file
|
ivl_signal_file
|
||||||
ivl_signal_integer
|
ivl_signal_integer
|
||||||
ivl_signal_lineno
|
ivl_signal_lineno
|
||||||
|
|
|
||||||
35
ivl_target.h
35
ivl_target.h
|
|
@ -151,6 +151,7 @@ _BEGIN_DECL
|
||||||
typedef struct ivl_array_s *ivl_array_t;
|
typedef struct ivl_array_s *ivl_array_t;
|
||||||
typedef struct ivl_delaypath_s*ivl_delaypath_t;
|
typedef struct ivl_delaypath_s*ivl_delaypath_t;
|
||||||
typedef struct ivl_design_s *ivl_design_t;
|
typedef struct ivl_design_s *ivl_design_t;
|
||||||
|
typedef struct ivl_discipline_s*ivl_discipline_t;
|
||||||
typedef struct ivl_event_s *ivl_event_t;
|
typedef struct ivl_event_s *ivl_event_t;
|
||||||
typedef struct ivl_expr_s *ivl_expr_t;
|
typedef struct ivl_expr_s *ivl_expr_t;
|
||||||
typedef struct ivl_island_s *ivl_island_t;
|
typedef struct ivl_island_s *ivl_island_t;
|
||||||
|
|
@ -159,6 +160,7 @@ typedef struct ivl_lval_s *ivl_lval_t;
|
||||||
typedef struct ivl_net_const_s*ivl_net_const_t;
|
typedef struct ivl_net_const_s*ivl_net_const_t;
|
||||||
typedef struct ivl_net_logic_s*ivl_net_logic_t;
|
typedef struct ivl_net_logic_s*ivl_net_logic_t;
|
||||||
typedef struct ivl_udp_s *ivl_udp_t;
|
typedef struct ivl_udp_s *ivl_udp_t;
|
||||||
|
typedef struct ivl_nature_s *ivl_nature_t;
|
||||||
typedef struct ivl_net_probe_s*ivl_net_probe_t;
|
typedef struct ivl_net_probe_s*ivl_net_probe_t;
|
||||||
typedef struct ivl_nexus_s *ivl_nexus_t;
|
typedef struct ivl_nexus_s *ivl_nexus_t;
|
||||||
typedef struct ivl_nexus_ptr_s*ivl_nexus_ptr_t;
|
typedef struct ivl_nexus_ptr_s*ivl_nexus_ptr_t;
|
||||||
|
|
@ -176,6 +178,12 @@ typedef struct ivl_statement_s*ivl_statement_t;
|
||||||
* changes and additions to the enumerations.
|
* changes and additions to the enumerations.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
typedef enum ivl_dis_domain_e {
|
||||||
|
IVL_DIS_NONE = 0,
|
||||||
|
IVL_DIS_DISCRETE = 1,
|
||||||
|
IVL_DIS_CONTINUOUS = 2
|
||||||
|
} ivl_dis_domain_t;
|
||||||
|
|
||||||
typedef enum ivl_drive_e {
|
typedef enum ivl_drive_e {
|
||||||
IVL_DR_HiZ = 0,
|
IVL_DR_HiZ = 0,
|
||||||
IVL_DR_SMALL = 1,
|
IVL_DR_SMALL = 1,
|
||||||
|
|
@ -543,6 +551,28 @@ extern double ivl_const_real(ivl_net_const_t net);
|
||||||
/* extern ivl_nexus_t ivl_const_pin(ivl_net_const_t net, unsigned idx); */
|
/* extern ivl_nexus_t ivl_const_pin(ivl_net_const_t net, unsigned idx); */
|
||||||
/* extern unsigned ivl_const_pins(ivl_net_const_t net); */
|
/* extern unsigned ivl_const_pins(ivl_net_const_t net); */
|
||||||
|
|
||||||
|
/* DISCIPLINES
|
||||||
|
*
|
||||||
|
* Disciplines are Verilog-AMS construct. A discipline is a collection
|
||||||
|
* of attributes that can be attached to a signal.
|
||||||
|
*
|
||||||
|
* FUNCTION SUMMARY
|
||||||
|
*
|
||||||
|
* ivl_discipline_name
|
||||||
|
* This is the name of the discipline in the Verilog-AMS source.
|
||||||
|
*
|
||||||
|
* ivl_discipline_domain
|
||||||
|
* This is the domain: continuous or discrete.
|
||||||
|
*
|
||||||
|
* SEMANTIC NOTES
|
||||||
|
*
|
||||||
|
* The discipline domain will not be IVL_DIS_NONE. The "none" domain
|
||||||
|
* is a place-holder internally for incomplete parsing, and is also
|
||||||
|
* available for code generaters to use.
|
||||||
|
*/
|
||||||
|
extern const char*ivl_discipline_name(ivl_discipline_t net);
|
||||||
|
extern ivl_dis_domain_t ivl_discipline_domain(ivl_discipline_t net);
|
||||||
|
|
||||||
/* EVENTS
|
/* EVENTS
|
||||||
*
|
*
|
||||||
* Events are a unification of named events and implicit events
|
* Events are a unification of named events and implicit events
|
||||||
|
|
@ -1584,6 +1614,10 @@ extern int ivl_scope_time_units(ivl_scope_t net);
|
||||||
* The signal may be an array (of vectors) in which case this
|
* The signal may be an array (of vectors) in which case this
|
||||||
* function returns >0, the number of dimensions of the array.
|
* function returns >0, the number of dimensions of the array.
|
||||||
*
|
*
|
||||||
|
* ivl_signal_discipline
|
||||||
|
* If the signal has been declared with a domain (Verilog-AMS) then
|
||||||
|
* this function wil return a non-nil ivl_discipline_t.
|
||||||
|
*
|
||||||
* ivl_signal_msb
|
* ivl_signal_msb
|
||||||
* ivl_signal_lsb
|
* ivl_signal_lsb
|
||||||
* ivl_signal_width
|
* ivl_signal_width
|
||||||
|
|
@ -1651,6 +1685,7 @@ extern ivl_nexus_t ivl_signal_nex(ivl_signal_t net, unsigned word);
|
||||||
extern int ivl_signal_array_base(ivl_signal_t net);
|
extern int ivl_signal_array_base(ivl_signal_t net);
|
||||||
extern unsigned ivl_signal_array_count(ivl_signal_t net);
|
extern unsigned ivl_signal_array_count(ivl_signal_t net);
|
||||||
extern unsigned ivl_signal_dimensions(ivl_signal_t net);
|
extern unsigned ivl_signal_dimensions(ivl_signal_t net);
|
||||||
|
extern ivl_discipline_t ivl_signal_discipline(ivl_signal_t net);
|
||||||
extern int ivl_signal_msb(ivl_signal_t net);
|
extern int ivl_signal_msb(ivl_signal_t net);
|
||||||
extern int ivl_signal_lsb(ivl_signal_t net);
|
extern int ivl_signal_lsb(ivl_signal_t net);
|
||||||
extern unsigned ivl_signal_width(ivl_signal_t net);
|
extern unsigned ivl_signal_width(ivl_signal_t net);
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef __globals_H
|
#ifndef __globals_H
|
||||||
#define __globals_H
|
#define __globals_H
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1999-2007 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 1999-2008 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -22,9 +22,11 @@
|
||||||
# include <stdio.h>
|
# include <stdio.h>
|
||||||
|
|
||||||
extern void reset_lexor(FILE*out, char*paths[]);
|
extern void reset_lexor(FILE*out, char*paths[]);
|
||||||
|
extern void destroy_lexor();
|
||||||
extern void load_precompiled_defines(FILE*src);
|
extern void load_precompiled_defines(FILE*src);
|
||||||
extern void define_macro(const char*name, const char*value, int keyword,
|
extern void define_macro(const char*name, const char*value, int keyword,
|
||||||
int argc);
|
int argc);
|
||||||
|
extern void free_macros();
|
||||||
extern void dump_precompiled_defines(FILE*out);
|
extern void dump_precompiled_defines(FILE*out);
|
||||||
|
|
||||||
/* These variables contain the include directories to be searched when
|
/* These variables contain the include directories to be searched when
|
||||||
|
|
|
||||||
|
|
@ -78,6 +78,9 @@ struct include_stack_t
|
||||||
YY_BUFFER_STATE yybs;
|
YY_BUFFER_STATE yybs;
|
||||||
|
|
||||||
struct include_stack_t* next;
|
struct include_stack_t* next;
|
||||||
|
|
||||||
|
/* A single line comment can be associated with this include. */
|
||||||
|
char* comment;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void emit_pathline(struct include_stack_t* isp);
|
static void emit_pathline(struct include_stack_t* isp);
|
||||||
|
|
@ -295,9 +298,10 @@ keywords (include|define|undef|ifdef|ifndef|else|elseif|endif)
|
||||||
|
|
||||||
/* Catch single-line comments that share the line with an include
|
/* Catch single-line comments that share the line with an include
|
||||||
* directive. And while I'm at it, I might as well preserve the
|
* directive. And while I'm at it, I might as well preserve the
|
||||||
* comment in the output stream.
|
* comment in the output stream. This will be printed after the
|
||||||
|
* file has been included.
|
||||||
*/
|
*/
|
||||||
<PPINCLUDE>"//"[^\r\n]* { ECHO; }
|
<PPINCLUDE>"//"[^\r\n]* { standby->comment = strdup(yytext); }
|
||||||
|
|
||||||
/* These finish the include directive (EOF or EOL) so I revert the
|
/* These finish the include directive (EOF or EOL) so I revert the
|
||||||
* lexor state and execute the inclusion.
|
* lexor state and execute the inclusion.
|
||||||
|
|
@ -829,6 +833,21 @@ void define_macro(const char* name, const char* value, int keyword, int argc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void free_macro(struct define_t* def)
|
||||||
|
{
|
||||||
|
if (def == 0) return;
|
||||||
|
free_macro(def->left);
|
||||||
|
free_macro(def->right);
|
||||||
|
free(def->name);
|
||||||
|
free(def->value);
|
||||||
|
free(def);
|
||||||
|
}
|
||||||
|
|
||||||
|
void free_macros()
|
||||||
|
{
|
||||||
|
free_macro(def_table);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The do_define function accumulates the defined value in these
|
* The do_define function accumulates the defined value in these
|
||||||
* variables. When the define is over, the def_finish() function
|
* variables. When the define is over, the def_finish() function
|
||||||
|
|
@ -1418,6 +1437,7 @@ static void include_filename()
|
||||||
standby->path = strdup(yytext+1);
|
standby->path = strdup(yytext+1);
|
||||||
standby->path[strlen(standby->path)-1] = 0;
|
standby->path[strlen(standby->path)-1] = 0;
|
||||||
standby->lineno = 0;
|
standby->lineno = 0;
|
||||||
|
standby->comment = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void do_include()
|
static void do_include()
|
||||||
|
|
@ -1457,6 +1477,8 @@ static void do_include()
|
||||||
|
|
||||||
if ((standby->file = fopen(path, "r")))
|
if ((standby->file = fopen(path, "r")))
|
||||||
{
|
{
|
||||||
|
/* Free the original path before we overwrite it. */
|
||||||
|
free(standby->path);
|
||||||
standby->path = strdup(path);
|
standby->path = strdup(path);
|
||||||
goto code_that_switches_buffers;
|
goto code_that_switches_buffers;
|
||||||
}
|
}
|
||||||
|
|
@ -1468,6 +1490,9 @@ static void do_include()
|
||||||
|
|
||||||
code_that_switches_buffers:
|
code_that_switches_buffers:
|
||||||
|
|
||||||
|
/* Clear the current files path from the search list. */
|
||||||
|
include_dir[0] = 0;
|
||||||
|
|
||||||
if(depend_file)
|
if(depend_file)
|
||||||
fprintf(depend_file, "%s\n", standby->path);
|
fprintf(depend_file, "%s\n", standby->path);
|
||||||
|
|
||||||
|
|
@ -1530,6 +1555,17 @@ static int load_next_input()
|
||||||
/* Delete the current input buffers, and free the cell. */
|
/* Delete the current input buffers, and free the cell. */
|
||||||
yy_delete_buffer(YY_CURRENT_BUFFER);
|
yy_delete_buffer(YY_CURRENT_BUFFER);
|
||||||
|
|
||||||
|
/* If there was a comment for this include print it before we
|
||||||
|
* return to the previous input stream. This technically belongs
|
||||||
|
* to the previous stream, but it should not create any problems
|
||||||
|
* since it is only a comment.
|
||||||
|
*/
|
||||||
|
if (isp->comment) {
|
||||||
|
fprintf(yyout, "%s\n", isp->comment);
|
||||||
|
free(isp->comment);
|
||||||
|
isp->comment = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (isp->file)
|
if (isp->file)
|
||||||
{
|
{
|
||||||
free(isp->path);
|
free(isp->path);
|
||||||
|
|
@ -1726,6 +1762,7 @@ void reset_lexor(FILE* out, char* paths[])
|
||||||
isp->ebs = 0;
|
isp->ebs = 0;
|
||||||
isp->lineno = 0;
|
isp->lineno = 0;
|
||||||
isp->stringify_flag = 0;
|
isp->stringify_flag = 0;
|
||||||
|
isp->comment = NULL;
|
||||||
|
|
||||||
if (isp->file == 0)
|
if (isp->file == 0)
|
||||||
{
|
{
|
||||||
|
|
@ -1756,6 +1793,7 @@ void reset_lexor(FILE* out, char* paths[])
|
||||||
isp->next = 0;
|
isp->next = 0;
|
||||||
isp->lineno = 0;
|
isp->lineno = 0;
|
||||||
isp->stringify_flag = 0;
|
isp->stringify_flag = 0;
|
||||||
|
isp->comment = NULL;
|
||||||
|
|
||||||
if (tail)
|
if (tail)
|
||||||
tail->next = isp;
|
tail->next = isp;
|
||||||
|
|
@ -1765,3 +1803,17 @@ void reset_lexor(FILE* out, char* paths[])
|
||||||
tail = isp;
|
tail = isp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Modern version of flex (>=2.5.9) can clean up the scanner data.
|
||||||
|
*/
|
||||||
|
void destroy_lexor()
|
||||||
|
{
|
||||||
|
# ifdef FLEX_SCANNER
|
||||||
|
# if YY_FLEX_MAJOR_VERSION >= 2 && YY_FLEX_MINOR_VERSION >= 5
|
||||||
|
# if defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9
|
||||||
|
yylex_destroy();
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
|
|
||||||
15
ivlpp/main.c
15
ivlpp/main.c
|
|
@ -189,12 +189,14 @@ static int flist_read_names(const char*path)
|
||||||
add_source_file(cp);
|
add_source_file(cp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fclose(fd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char*argv[])
|
int main(int argc, char*argv[])
|
||||||
{
|
{
|
||||||
int opt, idx;
|
int opt, idx;
|
||||||
|
unsigned lp;
|
||||||
const char*flist_path = 0;
|
const char*flist_path = 0;
|
||||||
unsigned flag_errors = 0;
|
unsigned flag_errors = 0;
|
||||||
char*out_path = 0;
|
char*out_path = 0;
|
||||||
|
|
@ -368,6 +370,7 @@ int main(int argc, char*argv[])
|
||||||
start scanning. */
|
start scanning. */
|
||||||
reset_lexor(out, source_list);
|
reset_lexor(out, source_list);
|
||||||
if (yylex()) return -1;
|
if (yylex()) return -1;
|
||||||
|
destroy_lexor();
|
||||||
|
|
||||||
if(depend_file) {
|
if(depend_file) {
|
||||||
fclose(depend_file);
|
fclose(depend_file);
|
||||||
|
|
@ -378,5 +381,17 @@ int main(int argc, char*argv[])
|
||||||
fclose(precomp_out);
|
fclose(precomp_out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Free the source and include directory lists. */
|
||||||
|
for (lp = 0; lp < source_cnt; lp += 1) {
|
||||||
|
free(source_list[lp]);
|
||||||
|
}
|
||||||
|
free(source_list);
|
||||||
|
for (lp = 0; lp < include_cnt; lp += 1) {
|
||||||
|
free(include_dir[lp]);
|
||||||
|
}
|
||||||
|
free(include_dir);
|
||||||
|
|
||||||
|
free_macros();
|
||||||
|
|
||||||
return error_count;
|
return error_count;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -247,7 +247,7 @@ S [afpnumkKMGT]
|
||||||
value instead. */
|
value instead. */
|
||||||
if (rc == IDENTIFIER && gn_verilog_ams_flag) {
|
if (rc == IDENTIFIER && gn_verilog_ams_flag) {
|
||||||
perm_string tmp = lex_strings.make(yylval.text);
|
perm_string tmp = lex_strings.make(yylval.text);
|
||||||
map<perm_string,discipline_t*>::iterator cur = disciplines.find(tmp);
|
map<perm_string,ivl_discipline_t>::iterator cur = disciplines.find(tmp);
|
||||||
if (cur != disciplines.end()) {
|
if (cur != disciplines.end()) {
|
||||||
yylval.discipline = (*cur).second;
|
yylval.discipline = (*cur).second;
|
||||||
rc = DISCIPLINE_IDENTIFIER;
|
rc = DISCIPLINE_IDENTIFIER;
|
||||||
|
|
|
||||||
2
main.cc
2
main.cc
|
|
@ -705,7 +705,7 @@ int main(int argc, char*argv[])
|
||||||
pform_dump(out, (*cur).second);
|
pform_dump(out, (*cur).second);
|
||||||
}
|
}
|
||||||
out << "PFORM DUMP DISCIPLINES:" << endl;
|
out << "PFORM DUMP DISCIPLINES:" << endl;
|
||||||
for (map<perm_string,discipline_t*>::iterator cur = disciplines.begin()
|
for (map<perm_string,ivl_discipline_t>::iterator cur = disciplines.begin()
|
||||||
; cur != disciplines.end() ; cur ++ ) {
|
; cur != disciplines.end() ; cur ++ ) {
|
||||||
pform_dump(out, (*cur).second);
|
pform_dump(out, (*cur).second);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2008 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
|
||||||
|
* General Public License as published by the Free Software
|
||||||
|
* Foundation; either version 2 of the License, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
# include "config.h"
|
||||||
|
|
||||||
|
# include <typeinfo>
|
||||||
|
# include <cstdlib>
|
||||||
|
# include <climits>
|
||||||
|
# include "compiler.h"
|
||||||
|
# include "netlist.h"
|
||||||
|
# include "netmisc.h"
|
||||||
|
# include "ivl_assert.h"
|
||||||
|
|
||||||
|
NetContribution::NetContribution(NetExpr*l, NetExpr*r)
|
||||||
|
: lval_(l), rval_(r)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
NetContribution::~NetContribution()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
@ -36,7 +36,7 @@
|
||||||
# include "ivl_assert.h"
|
# include "ivl_assert.h"
|
||||||
|
|
||||||
Design:: Design()
|
Design:: Design()
|
||||||
: errors(0), nodes_(0), procs_(0), lcounter_(0)
|
: errors(0), nodes_(0), procs_(0), aprocs_(0), lcounter_(0)
|
||||||
{
|
{
|
||||||
procs_idx_ = 0;
|
procs_idx_ = 0;
|
||||||
des_precision_ = 0;
|
des_precision_ = 0;
|
||||||
|
|
@ -764,6 +764,11 @@ void Design::add_process(NetProcTop*pro)
|
||||||
procs_ = pro;
|
procs_ = pro;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Design::add_process(NetAnalogTop*pro)
|
||||||
|
{
|
||||||
|
pro->next_ = aprocs_;
|
||||||
|
aprocs_ = pro;
|
||||||
|
}
|
||||||
void Design::delete_process(NetProcTop*top)
|
void Design::delete_process(NetProcTop*top)
|
||||||
{
|
{
|
||||||
assert(top);
|
assert(top);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000-2005 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2000-2008 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -16,9 +16,6 @@
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
#ifdef HAVE_CVS_IDENT
|
|
||||||
#ident "$Id: net_modulo.cc,v 1.9 2005/09/15 22:54:47 steve Exp $"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
# include "config.h"
|
# include "config.h"
|
||||||
|
|
||||||
|
|
@ -69,6 +66,16 @@ Link& NetModulo::pin_Result()
|
||||||
return pin(0);
|
return pin(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NetModulo::set_signed(bool flag)
|
||||||
|
{
|
||||||
|
signed_flag_ = flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NetModulo::get_signed() const
|
||||||
|
{
|
||||||
|
return signed_flag_;
|
||||||
|
}
|
||||||
|
|
||||||
const Link& NetModulo::pin_Result() const
|
const Link& NetModulo::pin_Result() const
|
||||||
{
|
{
|
||||||
return pin(0);
|
return pin(0);
|
||||||
|
|
@ -93,25 +100,3 @@ const Link& NetModulo::pin_DataB() const
|
||||||
{
|
{
|
||||||
return pin(2);
|
return pin(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* $Log: net_modulo.cc,v $
|
|
||||||
* Revision 1.9 2005/09/15 22:54:47 steve
|
|
||||||
* Fix bug configuring NetModulo pins.
|
|
||||||
*
|
|
||||||
* Revision 1.8 2005/03/12 06:43:35 steve
|
|
||||||
* Update support for LPM_MOD.
|
|
||||||
*
|
|
||||||
* Revision 1.7 2004/02/18 17:11:56 steve
|
|
||||||
* Use perm_strings for named langiage items.
|
|
||||||
*
|
|
||||||
* Revision 1.6 2003/03/06 00:28:41 steve
|
|
||||||
* All NetObj objects have lex_string base names.
|
|
||||||
*
|
|
||||||
* Revision 1.5 2002/08/12 01:34:59 steve
|
|
||||||
* conditional ident string using autoconfig.
|
|
||||||
*
|
|
||||||
* Revision 1.4 2002/08/11 23:47:04 steve
|
|
||||||
* Add missing Log and Ident strings.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
|
||||||
18
netlist.cc
18
netlist.cc
|
|
@ -242,7 +242,7 @@ NetNode::~NetNode()
|
||||||
design_->del_node(this);
|
design_->del_node(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
NetBranch::NetBranch(discipline_t*dis)
|
NetBranch::NetBranch(ivl_discipline_t dis)
|
||||||
: NetPins(2), discipline_(dis)
|
: NetPins(2), discipline_(dis)
|
||||||
{
|
{
|
||||||
pin(0).set_dir(Link::PASSIVE);
|
pin(0).set_dir(Link::PASSIVE);
|
||||||
|
|
@ -647,12 +647,12 @@ void NetNet::set_isint(bool flag)
|
||||||
isint_ = flag;
|
isint_ = flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
discipline_t* NetNet::get_discipline() const
|
ivl_discipline_t NetNet::get_discipline() const
|
||||||
{
|
{
|
||||||
return discipline_;
|
return discipline_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetNet::set_discipline(discipline_t*dis)
|
void NetNet::set_discipline(ivl_discipline_t dis)
|
||||||
{
|
{
|
||||||
ivl_assert(*this, discipline_ == 0);
|
ivl_assert(*this, discipline_ == 0);
|
||||||
discipline_ = dis;
|
discipline_ = dis;
|
||||||
|
|
@ -849,7 +849,7 @@ NetProc::~NetProc()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
NetProcTop::NetProcTop(NetScope*s, Type t, NetProc*st)
|
NetProcTop::NetProcTop(NetScope*s, ivl_process_type_t t, NetProc*st)
|
||||||
: type_(t), statement_(st), scope_(s)
|
: type_(t), statement_(st), scope_(s)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
@ -874,6 +874,16 @@ NetScope* NetProcTop::scope()
|
||||||
return scope_;
|
return scope_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NetAnalogTop::NetAnalogTop(NetScope*scope, ivl_process_type_t t, NetProc*st)
|
||||||
|
: type_(t), statement_(st), scope_(scope)
|
||||||
|
{
|
||||||
|
next_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
NetAnalogTop::~NetAnalogTop()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
const NetScope* NetProcTop::scope() const
|
const NetScope* NetProcTop::scope() const
|
||||||
{
|
{
|
||||||
return scope_;
|
return scope_;
|
||||||
|
|
|
||||||
76
netlist.h
76
netlist.h
|
|
@ -69,7 +69,6 @@ class NetEvTrig;
|
||||||
class NetEvWait;
|
class NetEvWait;
|
||||||
|
|
||||||
class nature_t;
|
class nature_t;
|
||||||
class discipline_t;
|
|
||||||
|
|
||||||
struct target;
|
struct target;
|
||||||
struct functor_t;
|
struct functor_t;
|
||||||
|
|
@ -173,12 +172,12 @@ class IslandBranch {
|
||||||
class NetBranch : public NetPins {
|
class NetBranch : public NetPins {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit NetBranch(discipline_t*dis);
|
explicit NetBranch(ivl_discipline_t dis);
|
||||||
explicit NetBranch(discipline_t*dis, perm_string name);
|
explicit NetBranch(ivl_discipline_t dis, perm_string name);
|
||||||
~NetBranch();
|
~NetBranch();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
discipline_t*discipline_;
|
ivl_discipline_t discipline_;
|
||||||
perm_string name_;
|
perm_string name_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -555,8 +554,8 @@ class NetNet : public NetObj {
|
||||||
void set_isint(bool);
|
void set_isint(bool);
|
||||||
|
|
||||||
/* Attach a discipline to the net. */
|
/* Attach a discipline to the net. */
|
||||||
discipline_t* get_discipline() const;
|
ivl_discipline_t get_discipline() const;
|
||||||
void set_discipline(discipline_t*dis);
|
void set_discipline(ivl_discipline_t dis);
|
||||||
|
|
||||||
/* These methods return the msb and lsb indices for the most
|
/* These methods return the msb and lsb indices for the most
|
||||||
significant and least significant bits. These are signed
|
significant and least significant bits. These are signed
|
||||||
|
|
@ -620,7 +619,7 @@ class NetNet : public NetObj {
|
||||||
ivl_variable_type_t data_type_;
|
ivl_variable_type_t data_type_;
|
||||||
bool signed_;
|
bool signed_;
|
||||||
bool isint_; // original type of integer
|
bool isint_; // original type of integer
|
||||||
discipline_t*discipline_;
|
ivl_discipline_t discipline_;
|
||||||
|
|
||||||
long msb_, lsb_;
|
long msb_, lsb_;
|
||||||
const unsigned dimensions_;
|
const unsigned dimensions_;
|
||||||
|
|
@ -830,7 +829,7 @@ class NetScope : public Attrib {
|
||||||
|
|
||||||
/* Module instance arrays are collected here for access during
|
/* Module instance arrays are collected here for access during
|
||||||
the multiple elaboration passes. */
|
the multiple elaboration passes. */
|
||||||
typedef svector<NetScope*> scope_vec_t;
|
typedef vector<NetScope*> scope_vec_t;
|
||||||
map<perm_string, scope_vec_t>instance_arrays;
|
map<perm_string, scope_vec_t>instance_arrays;
|
||||||
|
|
||||||
/* Loop generate uses this as scratch space during
|
/* Loop generate uses this as scratch space during
|
||||||
|
|
@ -1178,6 +1177,9 @@ class NetModulo : public NetNode {
|
||||||
unsigned width_a() const;
|
unsigned width_a() const;
|
||||||
unsigned width_b() const;
|
unsigned width_b() const;
|
||||||
|
|
||||||
|
void set_signed(bool);
|
||||||
|
bool get_signed() const;
|
||||||
|
|
||||||
Link& pin_DataA();
|
Link& pin_DataA();
|
||||||
Link& pin_DataB();
|
Link& pin_DataB();
|
||||||
Link& pin_Result();
|
Link& pin_Result();
|
||||||
|
|
@ -1194,6 +1196,8 @@ class NetModulo : public NetNode {
|
||||||
unsigned width_r_;
|
unsigned width_r_;
|
||||||
unsigned width_a_;
|
unsigned width_a_;
|
||||||
unsigned width_b_;
|
unsigned width_b_;
|
||||||
|
|
||||||
|
bool signed_flag_;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -2430,6 +2434,24 @@ class NetCondit : public NetProc {
|
||||||
NetProc*else_;
|
NetProc*else_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This represents the analog contribution statement. The l-val is a
|
||||||
|
* branch expression, and the r-value is an arbitrary expression that
|
||||||
|
* may include branches and real values.
|
||||||
|
*/
|
||||||
|
class NetContribution : public NetProc {
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit NetContribution(NetExpr*lval, NetExpr*rval);
|
||||||
|
~NetContribution();
|
||||||
|
|
||||||
|
virtual void dump(ostream&, unsigned ind) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
NetExpr*lval_;
|
||||||
|
NetExpr*rval_;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The procedural deassign statement (the opposite of assign) releases
|
* The procedural deassign statement (the opposite of assign) releases
|
||||||
* any assign expressions attached to the bits of the reg. The
|
* any assign expressions attached to the bits of the reg. The
|
||||||
|
|
@ -3040,12 +3062,10 @@ class NetWhile : public NetProc {
|
||||||
class NetProcTop : public LineInfo, public Attrib {
|
class NetProcTop : public LineInfo, public Attrib {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum Type { KINITIAL, KALWAYS };
|
NetProcTop(NetScope*s, ivl_process_type_t t, class NetProc*st);
|
||||||
|
|
||||||
NetProcTop(NetScope*s, Type t, class NetProc*st);
|
|
||||||
~NetProcTop();
|
~NetProcTop();
|
||||||
|
|
||||||
Type type() const { return type_; }
|
ivl_process_type_t type() const { return type_; }
|
||||||
NetProc*statement();
|
NetProc*statement();
|
||||||
const NetProc*statement() const;
|
const NetProc*statement() const;
|
||||||
|
|
||||||
|
|
@ -3070,7 +3090,7 @@ class NetProcTop : public LineInfo, public Attrib {
|
||||||
bool emit(struct target_t*tgt) const;
|
bool emit(struct target_t*tgt) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const Type type_;
|
const ivl_process_type_t type_;
|
||||||
NetProc*const statement_;
|
NetProc*const statement_;
|
||||||
|
|
||||||
NetScope*scope_;
|
NetScope*scope_;
|
||||||
|
|
@ -3078,6 +3098,32 @@ class NetProcTop : public LineInfo, public Attrib {
|
||||||
NetProcTop*next_;
|
NetProcTop*next_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class NetAnalogTop : public LineInfo, public Attrib {
|
||||||
|
|
||||||
|
public:
|
||||||
|
NetAnalogTop(NetScope*scope, ivl_process_type_t t, NetProc*st);
|
||||||
|
~NetAnalogTop();
|
||||||
|
|
||||||
|
ivl_process_type_t type() const { return type_; }
|
||||||
|
|
||||||
|
NetProc*statement();
|
||||||
|
const NetProc*statement() const;
|
||||||
|
|
||||||
|
NetScope*scope();
|
||||||
|
const NetScope*scope() const;
|
||||||
|
|
||||||
|
void dump(ostream&, unsigned ind) const;
|
||||||
|
bool emit(struct target_t*tgt) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const ivl_process_type_t type_;
|
||||||
|
NetProc* statement_;
|
||||||
|
|
||||||
|
NetScope*scope_;
|
||||||
|
friend class Design;
|
||||||
|
NetAnalogTop*next_;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This class represents a binary operator, with the left and right
|
* This class represents a binary operator, with the left and right
|
||||||
* operands and a single character for the operator. The operator
|
* operands and a single character for the operator. The operator
|
||||||
|
|
@ -3655,6 +3701,7 @@ class NetEUBits : public NetEUnary {
|
||||||
|
|
||||||
virtual NetNet* synthesize(Design*, NetScope*scope);
|
virtual NetNet* synthesize(Design*, NetScope*scope);
|
||||||
|
|
||||||
|
virtual NetEUBits* dup_expr() const;
|
||||||
virtual NetExpr* eval_tree(int prune_to_width = -1);
|
virtual NetExpr* eval_tree(int prune_to_width = -1);
|
||||||
virtual ivl_variable_type_t expr_type() const;
|
virtual ivl_variable_type_t expr_type() const;
|
||||||
};
|
};
|
||||||
|
|
@ -3818,6 +3865,7 @@ class Design {
|
||||||
|
|
||||||
// PROCESSES
|
// PROCESSES
|
||||||
void add_process(NetProcTop*);
|
void add_process(NetProcTop*);
|
||||||
|
void add_process(NetAnalogTop*);
|
||||||
void delete_process(NetProcTop*);
|
void delete_process(NetProcTop*);
|
||||||
bool check_always_delay() const;
|
bool check_always_delay() const;
|
||||||
|
|
||||||
|
|
@ -3849,6 +3897,8 @@ class Design {
|
||||||
NetProcTop*procs_;
|
NetProcTop*procs_;
|
||||||
NetProcTop*procs_idx_;
|
NetProcTop*procs_idx_;
|
||||||
|
|
||||||
|
NetAnalogTop*aprocs_;
|
||||||
|
|
||||||
map<string,const char*> flags_;
|
map<string,const char*> flags_;
|
||||||
|
|
||||||
int des_precision_;
|
int des_precision_;
|
||||||
|
|
|
||||||
65
parse.y
65
parse.y
|
|
@ -108,6 +108,12 @@ static svector<PExpr*>* copy_range(svector<PExpr*>* orig)
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class T> void append(vector<T>&out, const vector<T>&in)
|
||||||
|
{
|
||||||
|
for (size_t idx = 0 ; idx < in.size() ; idx += 1)
|
||||||
|
out.push_back(in[idx]);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is a shorthand for making a PECallFunction that takes a single
|
* This is a shorthand for making a PECallFunction that takes a single
|
||||||
* arg. This is used by some of the code that detects built-ins.
|
* arg. This is used by some of the code that detects built-ins.
|
||||||
|
|
@ -142,7 +148,7 @@ static PECallFunction*make_call_function(perm_string tn, PExpr*arg1, PExpr*arg2)
|
||||||
list<perm_string>*perm_strings;
|
list<perm_string>*perm_strings;
|
||||||
pform_name_t*pform_name;
|
pform_name_t*pform_name;
|
||||||
|
|
||||||
discipline_t*discipline;
|
ivl_discipline_t discipline;
|
||||||
|
|
||||||
hname_t*hier;
|
hname_t*hier;
|
||||||
|
|
||||||
|
|
@ -158,7 +164,7 @@ static PECallFunction*make_call_function(perm_string tn, PExpr*arg1, PExpr*arg2)
|
||||||
|
|
||||||
Module::port_t *mport;
|
Module::port_t *mport;
|
||||||
LexicalScope::range_t* value_range;
|
LexicalScope::range_t* value_range;
|
||||||
svector<Module::port_t*>*mports;
|
vector<Module::port_t*>*mports;
|
||||||
|
|
||||||
named_pexpr_t*named_pexpr;
|
named_pexpr_t*named_pexpr;
|
||||||
svector<named_pexpr_t*>*named_pexprs;
|
svector<named_pexpr_t*>*named_pexprs;
|
||||||
|
|
@ -180,7 +186,6 @@ static PECallFunction*make_call_function(perm_string tn, PExpr*arg1, PExpr*arg2)
|
||||||
PEventStatement*event_statement;
|
PEventStatement*event_statement;
|
||||||
Statement*statement;
|
Statement*statement;
|
||||||
svector<Statement*>*statement_list;
|
svector<Statement*>*statement_list;
|
||||||
AStatement*astatement;
|
|
||||||
|
|
||||||
PTaskFuncArg function_type;
|
PTaskFuncArg function_type;
|
||||||
|
|
||||||
|
|
@ -304,7 +309,7 @@ static PECallFunction*make_call_function(perm_string tn, PExpr*arg1, PExpr*arg2)
|
||||||
%type <statement> statement statement_or_null
|
%type <statement> statement statement_or_null
|
||||||
%type <statement_list> statement_list
|
%type <statement_list> statement_list
|
||||||
|
|
||||||
%type <astatement> analog_statement
|
%type <statement> analog_statement
|
||||||
|
|
||||||
%type <letter> spec_polarity
|
%type <letter> spec_polarity
|
||||||
%type <perm_strings> specify_path_identifiers
|
%type <perm_strings> specify_path_identifiers
|
||||||
|
|
@ -705,9 +710,9 @@ discipline_items
|
||||||
|
|
||||||
discipline_item
|
discipline_item
|
||||||
: K_domain K_discrete ';'
|
: K_domain K_discrete ';'
|
||||||
{ pform_discipline_domain(@1, DD_DISCRETE); }
|
{ pform_discipline_domain(@1, IVL_DIS_DISCRETE); }
|
||||||
| K_domain K_continuous ';'
|
| K_domain K_continuous ';'
|
||||||
{ pform_discipline_domain(@1, DD_CONTINUOUS); }
|
{ pform_discipline_domain(@1, IVL_DIS_CONTINUOUS); }
|
||||||
| K_potential IDENTIFIER ';'
|
| K_potential IDENTIFIER ';'
|
||||||
{ pform_discipline_potential(@1, $2); delete[] $2; }
|
{ pform_discipline_potential(@1, $2); delete[] $2; }
|
||||||
| K_flow IDENTIFIER ';'
|
| K_flow IDENTIFIER ';'
|
||||||
|
|
@ -1659,30 +1664,28 @@ list_of_identifiers
|
||||||
|
|
||||||
list_of_ports
|
list_of_ports
|
||||||
: port_opt
|
: port_opt
|
||||||
{ svector<Module::port_t*>*tmp
|
{ vector<Module::port_t*>*tmp
|
||||||
= new svector<Module::port_t*>(1);
|
= new vector<Module::port_t*>(1);
|
||||||
(*tmp)[0] = $1;
|
(*tmp)[0] = $1;
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
}
|
}
|
||||||
| list_of_ports ',' port_opt
|
| list_of_ports ',' port_opt
|
||||||
{ svector<Module::port_t*>*tmp
|
{ vector<Module::port_t*>*tmp = $1;
|
||||||
= new svector<Module::port_t*>(*$1, $3);
|
tmp->push_back($3);
|
||||||
delete $1;
|
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
list_of_port_declarations
|
list_of_port_declarations
|
||||||
: port_declaration
|
: port_declaration
|
||||||
{ svector<Module::port_t*>*tmp
|
{ vector<Module::port_t*>*tmp
|
||||||
= new svector<Module::port_t*>(1);
|
= new vector<Module::port_t*>(1);
|
||||||
(*tmp)[0] = $1;
|
(*tmp)[0] = $1;
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
}
|
}
|
||||||
| list_of_port_declarations ',' port_declaration
|
| list_of_port_declarations ',' port_declaration
|
||||||
{ svector<Module::port_t*>*tmp
|
{ vector<Module::port_t*>*tmp = $1;
|
||||||
= new svector<Module::port_t*>(*$1, $3);
|
tmp->push_back($3);
|
||||||
delete $1;
|
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
}
|
}
|
||||||
| list_of_port_declarations ',' IDENTIFIER
|
| list_of_port_declarations ',' IDENTIFIER
|
||||||
|
|
@ -1690,8 +1693,8 @@ list_of_port_declarations
|
||||||
perm_string name = lex_strings.make($3);
|
perm_string name = lex_strings.make($3);
|
||||||
ptmp = pform_module_port_reference(name, @3.text,
|
ptmp = pform_module_port_reference(name, @3.text,
|
||||||
@3.first_line);
|
@3.first_line);
|
||||||
svector<Module::port_t*>*tmp
|
vector<Module::port_t*>*tmp = $1;
|
||||||
= new svector<Module::port_t*>(*$1, ptmp);
|
tmp->push_back(ptmp);
|
||||||
|
|
||||||
/* Get the port declaration details, the port type
|
/* Get the port declaration details, the port type
|
||||||
and what not, from context data stored by the
|
and what not, from context data stored by the
|
||||||
|
|
@ -1701,7 +1704,6 @@ list_of_port_declarations
|
||||||
port_declaration_context.port_net_type,
|
port_declaration_context.port_net_type,
|
||||||
port_declaration_context.sign_flag,
|
port_declaration_context.sign_flag,
|
||||||
port_declaration_context.range, 0);
|
port_declaration_context.range, 0);
|
||||||
delete $1;
|
|
||||||
delete[]$3;
|
delete[]$3;
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
}
|
}
|
||||||
|
|
@ -2093,16 +2095,16 @@ module_item
|
||||||
/* Always and initial items are behavioral processes. */
|
/* Always and initial items are behavioral processes. */
|
||||||
|
|
||||||
| attribute_list_opt K_always statement
|
| attribute_list_opt K_always statement
|
||||||
{ PProcess*tmp = pform_make_behavior(PProcess::PR_ALWAYS, $3, $1);
|
{ PProcess*tmp = pform_make_behavior(IVL_PR_ALWAYS, $3, $1);
|
||||||
FILE_NAME(tmp, @2);
|
FILE_NAME(tmp, @2);
|
||||||
}
|
}
|
||||||
| attribute_list_opt K_initial statement
|
| attribute_list_opt K_initial statement
|
||||||
{ PProcess*tmp = pform_make_behavior(PProcess::PR_INITIAL, $3, $1);
|
{ PProcess*tmp = pform_make_behavior(IVL_PR_INITIAL, $3, $1);
|
||||||
FILE_NAME(tmp, @2);
|
FILE_NAME(tmp, @2);
|
||||||
}
|
}
|
||||||
|
|
||||||
| attribute_list_opt K_analog analog_statement
|
| attribute_list_opt K_analog analog_statement
|
||||||
{ pform_make_analog_behavior(@2, AProcess::PR_ALWAYS, $3); }
|
{ pform_make_analog_behavior(@2, IVL_PR_ALWAYS, $3); }
|
||||||
|
|
||||||
/* The task declaration rule matches the task declaration
|
/* The task declaration rule matches the task declaration
|
||||||
header, then pushes the function scope. This causes the
|
header, then pushes the function scope. This causes the
|
||||||
|
|
@ -2777,8 +2779,7 @@ port_reference
|
||||||
|
|
||||||
Module::port_t*ptmp = new Module::port_t;
|
Module::port_t*ptmp = new Module::port_t;
|
||||||
ptmp->name = perm_string();
|
ptmp->name = perm_string();
|
||||||
ptmp->expr = svector<PEIdent*>(1);
|
ptmp->expr.push_back(wtmp);
|
||||||
ptmp->expr[0] = wtmp;
|
|
||||||
|
|
||||||
delete[]$1;
|
delete[]$1;
|
||||||
$$ = ptmp;
|
$$ = ptmp;
|
||||||
|
|
@ -2801,8 +2802,7 @@ port_reference
|
||||||
|
|
||||||
Module::port_t*ptmp = new Module::port_t;
|
Module::port_t*ptmp = new Module::port_t;
|
||||||
ptmp->name = perm_string();
|
ptmp->name = perm_string();
|
||||||
ptmp->expr = svector<PEIdent*>(1);
|
ptmp->expr.push_back(tmp);
|
||||||
ptmp->expr[0] = tmp;
|
|
||||||
delete[]$1;
|
delete[]$1;
|
||||||
$$ = ptmp;
|
$$ = ptmp;
|
||||||
}
|
}
|
||||||
|
|
@ -2813,8 +2813,7 @@ port_reference
|
||||||
PEIdent*wtmp = new PEIdent(lex_strings.make($1));
|
PEIdent*wtmp = new PEIdent(lex_strings.make($1));
|
||||||
FILE_NAME(wtmp, @1);
|
FILE_NAME(wtmp, @1);
|
||||||
ptmp->name = lex_strings.make($1);
|
ptmp->name = lex_strings.make($1);
|
||||||
ptmp->expr = svector<PEIdent*>(1);
|
ptmp->expr.push_back(wtmp);
|
||||||
ptmp->expr[0] = wtmp;
|
|
||||||
delete[]$1;
|
delete[]$1;
|
||||||
$$ = ptmp;
|
$$ = ptmp;
|
||||||
}
|
}
|
||||||
|
|
@ -2826,7 +2825,7 @@ port_reference_list
|
||||||
{ $$ = $1; }
|
{ $$ = $1; }
|
||||||
| port_reference_list ',' port_reference
|
| port_reference_list ',' port_reference
|
||||||
{ Module::port_t*tmp = $1;
|
{ Module::port_t*tmp = $1;
|
||||||
tmp->expr = svector<PEIdent*>(tmp->expr, $3->expr);
|
append(tmp->expr, $3->expr);
|
||||||
delete $3;
|
delete $3;
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
}
|
}
|
||||||
|
|
@ -2978,7 +2977,13 @@ real_variable
|
||||||
{ perm_string name = lex_strings.make($1);
|
{ perm_string name = lex_strings.make($1);
|
||||||
pform_makewire(@1, name, NetNet::REG, NetNet::NOT_A_PORT, IVL_VT_REAL, 0);
|
pform_makewire(@1, name, NetNet::REG, NetNet::NOT_A_PORT, IVL_VT_REAL, 0);
|
||||||
if ($2 != 0) {
|
if ($2 != 0) {
|
||||||
yyerror(@2, "sorry: real variables do not currently support arrays.");
|
index_component_t index;
|
||||||
|
if ($2->size() > 1) {
|
||||||
|
yyerror(@2, "sorry: only 1 dimensional arrays "
|
||||||
|
"are currently supported.");
|
||||||
|
}
|
||||||
|
index = $2->front();
|
||||||
|
pform_set_reg_idx(name, index.msb, index.lsb);
|
||||||
delete $2;
|
delete $2;
|
||||||
}
|
}
|
||||||
$$ = $1;
|
$$ = $1;
|
||||||
|
|
|
||||||
11
pform.cc
11
pform.cc
|
|
@ -384,20 +384,19 @@ Module::port_t* pform_module_port_reference(perm_string name,
|
||||||
PEIdent*tmp = new PEIdent(name);
|
PEIdent*tmp = new PEIdent(name);
|
||||||
FILE_NAME(tmp, file, lineno);
|
FILE_NAME(tmp, file, lineno);
|
||||||
ptmp->name = name;
|
ptmp->name = name;
|
||||||
ptmp->expr = svector<PEIdent*>(1);
|
ptmp->expr.push_back(tmp);
|
||||||
ptmp->expr[0] = tmp;
|
|
||||||
|
|
||||||
return ptmp;
|
return ptmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pform_module_set_ports(svector<Module::port_t*>*ports)
|
void pform_module_set_ports(vector<Module::port_t*>*ports)
|
||||||
{
|
{
|
||||||
assert(pform_cur_module);
|
assert(pform_cur_module);
|
||||||
|
|
||||||
/* The parser parses ``module foo()'' as having one
|
/* The parser parses ``module foo()'' as having one
|
||||||
unconnected port, but it is really a module with no
|
unconnected port, but it is really a module with no
|
||||||
ports. Fix it up here. */
|
ports. Fix it up here. */
|
||||||
if (ports && (ports->count() == 1) && ((*ports)[0] == 0)) {
|
if (ports && (ports->size() == 1) && ((*ports)[0] == 0)) {
|
||||||
delete ports;
|
delete ports;
|
||||||
ports = 0;
|
ports = 0;
|
||||||
}
|
}
|
||||||
|
|
@ -1327,7 +1326,7 @@ void pform_make_reginit(const struct vlltype&li,
|
||||||
FILE_NAME(lval, li);
|
FILE_NAME(lval, li);
|
||||||
PAssign*ass = new PAssign(lval, expr, true);
|
PAssign*ass = new PAssign(lval, expr, true);
|
||||||
FILE_NAME(ass, li);
|
FILE_NAME(ass, li);
|
||||||
PProcess*top = new PProcess(PProcess::PR_INITIAL, ass);
|
PProcess*top = new PProcess(IVL_PR_INITIAL, ass);
|
||||||
FILE_NAME(top, li);
|
FILE_NAME(top, li);
|
||||||
|
|
||||||
pform_put_behavior_in_scope(top);
|
pform_put_behavior_in_scope(top);
|
||||||
|
|
@ -1970,7 +1969,7 @@ svector<PWire*>* pform_make_udp_input_ports(list<perm_string>*names)
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
PProcess* pform_make_behavior(PProcess::Type type, Statement*st,
|
PProcess* pform_make_behavior(ivl_process_type_t type, Statement*st,
|
||||||
svector<named_pexpr_t*>*attr)
|
svector<named_pexpr_t*>*attr)
|
||||||
{
|
{
|
||||||
PProcess*pp = new PProcess(type, st);
|
PProcess*pp = new PProcess(type, st);
|
||||||
|
|
|
||||||
15
pform.h
15
pform.h
|
|
@ -143,7 +143,7 @@ extern PWire* pform_get_wire_in_scope(perm_string name);
|
||||||
*/
|
*/
|
||||||
extern void pform_startmodule(const char*, const char*file, unsigned lineno,
|
extern void pform_startmodule(const char*, const char*file, unsigned lineno,
|
||||||
svector<named_pexpr_t*>*attr);
|
svector<named_pexpr_t*>*attr);
|
||||||
extern void pform_module_set_ports(svector<Module::port_t*>*);
|
extern void pform_module_set_ports(vector<Module::port_t*>*);
|
||||||
|
|
||||||
/* This function is used to support the port definition in a
|
/* This function is used to support the port definition in a
|
||||||
port_definition_list. In this case, we have everything needed to
|
port_definition_list. In this case, we have everything needed to
|
||||||
|
|
@ -311,7 +311,7 @@ extern void pform_module_specify_path(PSpecPath*obj);
|
||||||
* pform_make_behavior creates processes that are declared with always
|
* pform_make_behavior creates processes that are declared with always
|
||||||
* or initial items.
|
* or initial items.
|
||||||
*/
|
*/
|
||||||
extern PProcess* pform_make_behavior(PProcess::Type, Statement*,
|
extern PProcess* pform_make_behavior(ivl_process_type_t, Statement*,
|
||||||
svector<named_pexpr_t*>*attr);
|
svector<named_pexpr_t*>*attr);
|
||||||
|
|
||||||
extern svector<PWire*>* pform_make_udp_input_ports(list<perm_string>*);
|
extern svector<PWire*>* pform_make_udp_input_ports(list<perm_string>*);
|
||||||
|
|
@ -373,7 +373,6 @@ extern void pform_error_nested_modules();
|
||||||
* Functions for handling the parse of natures and disciplines. These
|
* Functions for handling the parse of natures and disciplines. These
|
||||||
* functions are in pform_disciplines.cc
|
* functions are in pform_disciplines.cc
|
||||||
*/
|
*/
|
||||||
class discipline_t;
|
|
||||||
|
|
||||||
extern void pform_start_nature(const char*name);
|
extern void pform_start_nature(const char*name);
|
||||||
extern void pform_end_nature(const struct vlltype&loc);
|
extern void pform_end_nature(const struct vlltype&loc);
|
||||||
|
|
@ -383,22 +382,22 @@ extern void pform_nature_access(const struct vlltype&loc, const char*name);
|
||||||
extern void pform_start_discipline(const char*name);
|
extern void pform_start_discipline(const char*name);
|
||||||
extern void pform_end_discipline(const struct vlltype&loc);
|
extern void pform_end_discipline(const struct vlltype&loc);
|
||||||
|
|
||||||
extern void pform_discipline_domain(const struct vlltype&loc, ddomain_t use_domain);
|
extern void pform_discipline_domain(const struct vlltype&loc, ivl_dis_domain_t use_domain);
|
||||||
extern void pform_discipline_potential(const struct vlltype&loc, const char*name);
|
extern void pform_discipline_potential(const struct vlltype&loc, const char*name);
|
||||||
extern void pform_discipline_flow(const struct vlltype&loc, const char*name);
|
extern void pform_discipline_flow(const struct vlltype&loc, const char*name);
|
||||||
|
|
||||||
extern void pform_attach_discipline(const struct vlltype&loc,
|
extern void pform_attach_discipline(const struct vlltype&loc,
|
||||||
discipline_t*discipline, list<perm_string>*names);
|
ivl_discipline_t discipline, list<perm_string>*names);
|
||||||
|
|
||||||
extern void pform_dump(ostream&out, const nature_t*);
|
extern void pform_dump(ostream&out, const nature_t*);
|
||||||
extern void pform_dump(ostream&out, const discipline_t*);
|
extern void pform_dump(ostream&out, const ivl_discipline_s*);
|
||||||
|
|
||||||
/* ** pform_analog.cc
|
/* ** pform_analog.cc
|
||||||
*/
|
*/
|
||||||
extern void pform_make_analog_behavior(const struct vlltype&loc,
|
extern void pform_make_analog_behavior(const struct vlltype&loc,
|
||||||
AProcess::Type type, AStatement*st);
|
ivl_process_type_t type, Statement*st);
|
||||||
|
|
||||||
extern AStatement*pform_contribution_statement(const struct vlltype&loc,
|
extern AContrib*pform_contribution_statement(const struct vlltype&loc,
|
||||||
PExpr*lval, PExpr*rval);
|
PExpr*lval, PExpr*rval);
|
||||||
|
|
||||||
extern PExpr* pform_make_branch_probe_expression(const struct vlltype&loc,
|
extern PExpr* pform_make_branch_probe_expression(const struct vlltype&loc,
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@
|
||||||
# include "parse_misc.h"
|
# include "parse_misc.h"
|
||||||
# include "AStatement.h"
|
# include "AStatement.h"
|
||||||
|
|
||||||
AStatement* pform_contribution_statement(const struct vlltype&loc,
|
AContrib* pform_contribution_statement(const struct vlltype&loc,
|
||||||
PExpr*lval, PExpr*rval)
|
PExpr*lval, PExpr*rval)
|
||||||
{
|
{
|
||||||
AContrib*tmp = new AContrib(lval, rval);
|
AContrib*tmp = new AContrib(lval, rval);
|
||||||
|
|
@ -31,8 +31,8 @@ AStatement* pform_contribution_statement(const struct vlltype&loc,
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pform_make_analog_behavior(const struct vlltype&loc, AProcess::Type pt,
|
void pform_make_analog_behavior(const struct vlltype&loc, ivl_process_type_t pt,
|
||||||
AStatement*statement)
|
Statement*statement)
|
||||||
{
|
{
|
||||||
AProcess*proc = new AProcess(pt, statement);
|
AProcess*proc = new AProcess(pt, statement);
|
||||||
FILE_NAME(proc, loc);
|
FILE_NAME(proc, loc);
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@
|
||||||
# include "discipline.h"
|
# include "discipline.h"
|
||||||
|
|
||||||
map<perm_string,nature_t*> natures;
|
map<perm_string,nature_t*> natures;
|
||||||
map<perm_string,discipline_t*> disciplines;
|
map<perm_string,ivl_discipline_t> disciplines;
|
||||||
map<perm_string,nature_t*> access_function_nature;
|
map<perm_string,nature_t*> access_function_nature;
|
||||||
|
|
||||||
static perm_string nature_name = perm_string::perm_string();
|
static perm_string nature_name = perm_string::perm_string();
|
||||||
|
|
@ -88,21 +88,21 @@ void pform_end_nature(const struct vlltype&loc)
|
||||||
|
|
||||||
|
|
||||||
static perm_string discipline_name;
|
static perm_string discipline_name;
|
||||||
static ddomain_t discipline_domain = DD_NONE;
|
static ivl_dis_domain_t discipline_domain = IVL_DIS_NONE;
|
||||||
static nature_t* discipline_potential = 0;
|
static nature_t* discipline_potential = 0;
|
||||||
static nature_t* discipline_flow = 0;
|
static nature_t* discipline_flow = 0;
|
||||||
|
|
||||||
void pform_start_discipline(const char*name)
|
void pform_start_discipline(const char*name)
|
||||||
{
|
{
|
||||||
discipline_name = lex_strings.make(name);
|
discipline_name = lex_strings.make(name);
|
||||||
discipline_domain = DD_NONE;
|
discipline_domain = IVL_DIS_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pform_discipline_domain(const struct vlltype&loc, ddomain_t use_domain)
|
void pform_discipline_domain(const struct vlltype&loc, ivl_dis_domain_t use_domain)
|
||||||
{
|
{
|
||||||
assert(use_domain != DD_NONE);
|
assert(use_domain != IVL_DIS_NONE);
|
||||||
|
|
||||||
if (discipline_domain != DD_NONE) {
|
if (discipline_domain != IVL_DIS_NONE) {
|
||||||
cerr << loc.text << ":" << loc.first_line << ": error: "
|
cerr << loc.text << ":" << loc.first_line << ": error: "
|
||||||
<< "Too many domain attributes for discipline "
|
<< "Too many domain attributes for discipline "
|
||||||
<< discipline_name << "." << endl;
|
<< discipline_name << "." << endl;
|
||||||
|
|
@ -159,18 +159,20 @@ void pform_end_discipline(const struct vlltype&loc)
|
||||||
{
|
{
|
||||||
// If the domain is not otherwise specified, then take it to
|
// If the domain is not otherwise specified, then take it to
|
||||||
// be continuous if potential or flow natures are given.
|
// be continuous if potential or flow natures are given.
|
||||||
if (discipline_domain == DD_NONE && (discipline_potential||discipline_flow))
|
if (discipline_domain == IVL_DIS_NONE && (discipline_potential||discipline_flow))
|
||||||
discipline_domain = DD_CONTINUOUS;
|
discipline_domain = IVL_DIS_CONTINUOUS;
|
||||||
|
|
||||||
discipline_t*tmp = new discipline_t(discipline_name, discipline_domain,
|
ivl_discipline_t tmp = new ivl_discipline_s(discipline_name,
|
||||||
discipline_potential, discipline_flow);
|
discipline_domain,
|
||||||
|
discipline_potential,
|
||||||
|
discipline_flow);
|
||||||
disciplines[discipline_name] = tmp;
|
disciplines[discipline_name] = tmp;
|
||||||
|
|
||||||
FILE_NAME(tmp, loc);
|
FILE_NAME(tmp, loc);
|
||||||
|
|
||||||
/* Clear the static variables for the next item. */
|
/* Clear the static variables for the next item. */
|
||||||
discipline_name = perm_string::perm_string();
|
discipline_name = perm_string::perm_string();
|
||||||
discipline_domain = DD_NONE;
|
discipline_domain = IVL_DIS_NONE;
|
||||||
discipline_potential = 0;
|
discipline_potential = 0;
|
||||||
discipline_flow = 0;
|
discipline_flow = 0;
|
||||||
}
|
}
|
||||||
|
|
@ -183,7 +185,7 @@ void pform_end_discipline(const struct vlltype&loc)
|
||||||
* in the current lexical scope.
|
* in the current lexical scope.
|
||||||
*/
|
*/
|
||||||
void pform_attach_discipline(const struct vlltype&loc,
|
void pform_attach_discipline(const struct vlltype&loc,
|
||||||
discipline_t*discipline, list<perm_string>*names)
|
ivl_discipline_t discipline, list<perm_string>*names)
|
||||||
{
|
{
|
||||||
for (list<perm_string>::iterator cur = names->begin()
|
for (list<perm_string>::iterator cur = names->begin()
|
||||||
; cur != names->end() ; cur ++ ) {
|
; cur != names->end() ; cur ++ ) {
|
||||||
|
|
@ -197,7 +199,7 @@ void pform_attach_discipline(const struct vlltype&loc,
|
||||||
assert(cur_net);
|
assert(cur_net);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (discipline_t*tmp = cur_net->get_discipline()) {
|
if (ivl_discipline_t tmp = cur_net->get_discipline()) {
|
||||||
cerr << loc.text << ":" << loc.first_line << ": error: "
|
cerr << loc.text << ":" << loc.first_line << ": error: "
|
||||||
<< "discipline " << discipline->name()
|
<< "discipline " << discipline->name()
|
||||||
<< " cannot override existing discipline " << tmp->name()
|
<< " cannot override existing discipline " << tmp->name()
|
||||||
|
|
|
||||||
|
|
@ -135,17 +135,29 @@ ostream& operator<< (ostream&o, const pform_name_t&that)
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::ostream& operator << (std::ostream&out, ivl_process_type_t pt)
|
||||||
|
{
|
||||||
|
switch (pt) {
|
||||||
|
case IVL_PR_INITIAL:
|
||||||
|
out << "initial";
|
||||||
|
break;
|
||||||
|
case IVL_PR_ALWAYS:
|
||||||
|
out << "always";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
std::ostream& operator << (std::ostream&out, ddomain_t dom)
|
std::ostream& operator << (std::ostream&out, ivl_dis_domain_t dom)
|
||||||
{
|
{
|
||||||
switch (dom) {
|
switch (dom) {
|
||||||
case DD_NONE:
|
case IVL_DIS_NONE:
|
||||||
out << "no-domain";
|
out << "no-domain";
|
||||||
break;
|
break;
|
||||||
case DD_DISCRETE:
|
case IVL_DIS_DISCRETE:
|
||||||
out << "discrete";
|
out << "discrete";
|
||||||
break;
|
break;
|
||||||
case DD_CONTINUOUS:
|
case IVL_DIS_CONTINUOUS:
|
||||||
out << "continuous";
|
out << "continuous";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
@ -552,16 +564,6 @@ void Statement::dump(ostream&out, unsigned ind) const
|
||||||
dump_attributes_map(out, attributes, ind+2);
|
dump_attributes_map(out, attributes, ind+2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AStatement::dump(ostream&out, unsigned ind) const
|
|
||||||
{
|
|
||||||
/* I give up. I don't know what type this statement is,
|
|
||||||
so just print the C++ typeid and let the user figure
|
|
||||||
it out. */
|
|
||||||
out << setw(ind) << "";
|
|
||||||
out << "/* " << get_fileline() << ": " << typeid(*this).name()
|
|
||||||
<< " */ ;" << endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AContrib::dump(ostream&out, unsigned ind) const
|
void AContrib::dump(ostream&out, unsigned ind) const
|
||||||
{
|
{
|
||||||
out << setw(ind) << "";
|
out << setw(ind) << "";
|
||||||
|
|
@ -900,16 +902,8 @@ void PWhile::dump(ostream&out, unsigned ind) const
|
||||||
|
|
||||||
void PProcess::dump(ostream&out, unsigned ind) const
|
void PProcess::dump(ostream&out, unsigned ind) const
|
||||||
{
|
{
|
||||||
switch (type_) {
|
out << setw(ind) << "" << type_
|
||||||
case PProcess::PR_INITIAL:
|
<< " /* " << get_fileline() << " */" << endl;
|
||||||
out << setw(ind) << "" << "initial";
|
|
||||||
break;
|
|
||||||
case PProcess::PR_ALWAYS:
|
|
||||||
out << setw(ind) << "" << "always";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
out << " /* " << get_fileline() << " */" << endl;
|
|
||||||
|
|
||||||
dump_attributes_map(out, attributes, ind+2);
|
dump_attributes_map(out, attributes, ind+2);
|
||||||
|
|
||||||
|
|
@ -919,10 +913,10 @@ void PProcess::dump(ostream&out, unsigned ind) const
|
||||||
void AProcess::dump(ostream&out, unsigned ind) const
|
void AProcess::dump(ostream&out, unsigned ind) const
|
||||||
{
|
{
|
||||||
switch (type_) {
|
switch (type_) {
|
||||||
case AProcess::PR_INITIAL:
|
case IVL_PR_INITIAL:
|
||||||
out << setw(ind) << "" << "analog initial";
|
out << setw(ind) << "" << "analog initial";
|
||||||
break;
|
break;
|
||||||
case AProcess::PR_ALWAYS:
|
case IVL_PR_ALWAYS:
|
||||||
out << setw(ind) << "" << "analog";
|
out << setw(ind) << "" << "analog";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -1149,7 +1143,7 @@ void Module::dump(ostream&out) const
|
||||||
|
|
||||||
out << "module " << mod_name() << ";" << endl;
|
out << "module " << mod_name() << ";" << endl;
|
||||||
|
|
||||||
for (unsigned idx = 0 ; idx < ports.count() ; idx += 1) {
|
for (unsigned idx = 0 ; idx < ports.size() ; idx += 1) {
|
||||||
port_t*cur = ports[idx];
|
port_t*cur = ports[idx];
|
||||||
|
|
||||||
if (cur == 0) {
|
if (cur == 0) {
|
||||||
|
|
@ -1158,7 +1152,7 @@ void Module::dump(ostream&out) const
|
||||||
}
|
}
|
||||||
|
|
||||||
out << " ." << cur->name << "(" << *cur->expr[0];
|
out << " ." << cur->name << "(" << *cur->expr[0];
|
||||||
for (unsigned wdx = 1 ; wdx < cur->expr.count() ; wdx += 1) {
|
for (unsigned wdx = 1 ; wdx < cur->expr.size() ; wdx += 1) {
|
||||||
out << ", " << *cur->expr[wdx];
|
out << ", " << *cur->expr[wdx];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1306,7 +1300,7 @@ void pform_dump(std::ostream&out, const nature_t*nat)
|
||||||
out << "endnature" << endl;
|
out << "endnature" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pform_dump(std::ostream&out, const discipline_t*dis)
|
void pform_dump(std::ostream&out, const ivl_discipline_s*dis)
|
||||||
{
|
{
|
||||||
out << "discipline " << dis->name() << endl;
|
out << "discipline " << dis->name() << endl;
|
||||||
out << " domain " << dis->domain() << ";" << endl;
|
out << " domain " << dis->domain() << ";" << endl;
|
||||||
|
|
|
||||||
|
|
@ -335,7 +335,7 @@ static void syn_start_process(NetProcTop*t)
|
||||||
last_ = first_;
|
last_ = first_;
|
||||||
ptr_ = first_;
|
ptr_ = first_;
|
||||||
|
|
||||||
first_->token = (t->type() == NetProcTop::KALWAYS)? S_ALWAYS : S_INITIAL;
|
first_->token = (t->type() == IVL_PR_ALWAYS)? S_ALWAYS : S_INITIAL;
|
||||||
first_->top = t;
|
first_->top = t;
|
||||||
first_->next_ = 0;
|
first_->next_ = 0;
|
||||||
|
|
||||||
|
|
|
||||||
22
sync.cc
22
sync.cc
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2002 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2002-2008 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -16,9 +16,6 @@
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
#ifdef HAVE_CVS_IDENT
|
|
||||||
#ident "$Id: sync.cc,v 1.3 2002/09/24 00:58:35 steve Exp $"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
# include "config.h"
|
# include "config.h"
|
||||||
|
|
||||||
|
|
@ -59,23 +56,8 @@ bool NetEvWait::is_synchronous()
|
||||||
|
|
||||||
bool NetProcTop::is_synchronous()
|
bool NetProcTop::is_synchronous()
|
||||||
{
|
{
|
||||||
if (type_ == NetProcTop::KINITIAL)
|
if (type_ == IVL_PR_INITIAL)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return statement_->is_synchronous();
|
return statement_->is_synchronous();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* $Log: sync.cc,v $
|
|
||||||
* Revision 1.3 2002/09/24 00:58:35 steve
|
|
||||||
* More detailed check of process edge events.
|
|
||||||
*
|
|
||||||
* Revision 1.2 2002/09/16 21:55:06 steve
|
|
||||||
* Reject multiple probes on synchronous logic.
|
|
||||||
*
|
|
||||||
* Revision 1.1 2002/09/16 00:30:33 steve
|
|
||||||
* Add to synth2 support for synthesis of
|
|
||||||
* synchronous logic. This includes DFF enables
|
|
||||||
* modeled by if/then/else.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
|
||||||
4
synth.cc
4
synth.cc
|
|
@ -131,10 +131,10 @@ void synth_f::process(class Design*des, class NetProcTop*top)
|
||||||
{
|
{
|
||||||
top_ = top;
|
top_ = top;
|
||||||
switch (top->type()) {
|
switch (top->type()) {
|
||||||
case NetProcTop::KALWAYS:
|
case IVL_PR_ALWAYS:
|
||||||
proc_always_(des);
|
proc_always_(des);
|
||||||
break;
|
break;
|
||||||
case NetProcTop::KINITIAL:
|
case IVL_PR_INITIAL:
|
||||||
proc_initial_(des);
|
proc_initial_(des);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
16
t-dll-api.cc
16
t-dll-api.cc
|
|
@ -20,6 +20,7 @@
|
||||||
# include "config.h"
|
# include "config.h"
|
||||||
# include "StringHeap.h"
|
# include "StringHeap.h"
|
||||||
# include "t-dll.h"
|
# include "t-dll.h"
|
||||||
|
# include "discipline.h"
|
||||||
# include <stdlib.h>
|
# include <stdlib.h>
|
||||||
# include <string.h>
|
# include <string.h>
|
||||||
#ifdef HAVE_MALLOC_H
|
#ifdef HAVE_MALLOC_H
|
||||||
|
|
@ -81,6 +82,16 @@ extern "C" ivl_net_const_t ivl_design_const(ivl_design_t des, unsigned idx)
|
||||||
return des->consts[idx];
|
return des->consts[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" ivl_dis_domain_t ivl_discipline_domain(ivl_discipline_t net)
|
||||||
|
{
|
||||||
|
return net->domain();
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" const char* ivl_discipline_name(ivl_discipline_t net)
|
||||||
|
{
|
||||||
|
return net->name();
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" ivl_expr_type_t ivl_expr_type(ivl_expr_t net)
|
extern "C" ivl_expr_type_t ivl_expr_type(ivl_expr_t net)
|
||||||
{
|
{
|
||||||
if (net == 0)
|
if (net == 0)
|
||||||
|
|
@ -1729,6 +1740,11 @@ extern "C" unsigned ivl_signal_dimensions(ivl_signal_t net)
|
||||||
return net->array_dimensions_;
|
return net->array_dimensions_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" ivl_discipline_t ivl_signal_discipline(ivl_signal_t net)
|
||||||
|
{
|
||||||
|
return net->discipline;
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" const char* ivl_signal_attr(ivl_signal_t net, const char*key)
|
extern "C" const char* ivl_signal_attr(ivl_signal_t net, const char*key)
|
||||||
{
|
{
|
||||||
if (net->nattr == 0)
|
if (net->nattr == 0)
|
||||||
|
|
|
||||||
|
|
@ -39,16 +39,8 @@ bool dll_target::process(const NetProcTop*net)
|
||||||
ivl_process_t obj = (struct ivl_process_s*)
|
ivl_process_t obj = (struct ivl_process_s*)
|
||||||
calloc(1, sizeof(struct ivl_process_s));
|
calloc(1, sizeof(struct ivl_process_s));
|
||||||
|
|
||||||
switch (net->type()) {
|
obj->type_ = net->type();
|
||||||
case NetProcTop::KINITIAL:
|
|
||||||
obj->type_ = IVL_PR_INITIAL;
|
|
||||||
break;
|
|
||||||
case NetProcTop::KALWAYS:
|
|
||||||
obj->type_ = IVL_PR_ALWAYS;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
FILE_NAME(obj, net);
|
FILE_NAME(obj, net);
|
||||||
|
|
||||||
/* Save the scope of the process. */
|
/* Save the scope of the process. */
|
||||||
|
|
|
||||||
3
t-dll.cc
3
t-dll.cc
|
|
@ -1782,7 +1782,7 @@ void dll_target::lpm_modulo(const NetModulo*net)
|
||||||
unsigned wid = net->width_r();
|
unsigned wid = net->width_r();
|
||||||
|
|
||||||
obj->width = wid;
|
obj->width = wid;
|
||||||
obj->u_.arith.signed_flag = 0;
|
obj->u_.arith.signed_flag = net->get_signed()? 1 : 0;
|
||||||
|
|
||||||
const Nexus*nex;
|
const Nexus*nex;
|
||||||
|
|
||||||
|
|
@ -2410,6 +2410,7 @@ void dll_target::signal(const NetNet*net)
|
||||||
obj->lsb_dist = net->msb() >= net->lsb() ? 1 : -1;
|
obj->lsb_dist = net->msb() >= net->lsb() ? 1 : -1;
|
||||||
obj->isint_ = false;
|
obj->isint_ = false;
|
||||||
obj->local_ = net->local_flag()? 1 : 0;
|
obj->local_ = net->local_flag()? 1 : 0;
|
||||||
|
obj->discipline = net->get_discipline();
|
||||||
|
|
||||||
obj->array_dimensions_ = net->array_dimensions();
|
obj->array_dimensions_ = net->array_dimensions();
|
||||||
|
|
||||||
|
|
|
||||||
1
t-dll.h
1
t-dll.h
|
|
@ -623,6 +623,7 @@ struct ivl_signal_s {
|
||||||
ivl_signal_type_t type_;
|
ivl_signal_type_t type_;
|
||||||
ivl_signal_port_t port_;
|
ivl_signal_port_t port_;
|
||||||
ivl_variable_type_t data_type;
|
ivl_variable_type_t data_type;
|
||||||
|
ivl_discipline_t discipline;
|
||||||
perm_string file;
|
perm_string file;
|
||||||
unsigned lineno;
|
unsigned lineno;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1238,17 +1238,24 @@ static void show_signal(ivl_signal_t net)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char*discipline_txt = "NONE";
|
||||||
|
if (ivl_signal_discipline(net)) {
|
||||||
|
ivl_discipline_t dis = ivl_signal_discipline(net);
|
||||||
|
discipline_txt = ivl_discipline_name(dis);
|
||||||
|
}
|
||||||
|
|
||||||
for (idx = 0 ; idx < ivl_signal_array_count(net) ; idx += 1) {
|
for (idx = 0 ; idx < ivl_signal_array_count(net) ; idx += 1) {
|
||||||
|
|
||||||
nex = ivl_signal_nex(net, idx);
|
nex = ivl_signal_nex(net, idx);
|
||||||
|
|
||||||
fprintf(out, " %s %s %s%s[%d:%d] %s[word=%u, adr=%d] <width=%u%s> nexus=%s\n",
|
fprintf(out, " %s %s %s%s[%d:%d] %s[word=%u, adr=%d] <width=%u%s> <discipline=%s> nexus=%s\n",
|
||||||
type, sign, port, data_type,
|
type, sign, port, data_type,
|
||||||
ivl_signal_msb(net), ivl_signal_lsb(net),
|
ivl_signal_msb(net), ivl_signal_lsb(net),
|
||||||
ivl_signal_basename(net),
|
ivl_signal_basename(net),
|
||||||
idx, ivl_signal_array_base(net)+idx,
|
idx, ivl_signal_array_base(net)+idx,
|
||||||
ivl_signal_width(net),
|
ivl_signal_width(net),
|
||||||
ivl_signal_local(net)? ", local":"",
|
ivl_signal_local(net)? ", local":"",
|
||||||
|
discipline_txt,
|
||||||
ivl_nexus_name(nex));
|
ivl_nexus_name(nex));
|
||||||
|
|
||||||
show_nexus_details(net, nex);
|
show_nexus_details(net, nex);
|
||||||
|
|
|
||||||
|
|
@ -198,11 +198,11 @@ vhdl_expr *vhdl_expr::resize(int newwidth)
|
||||||
else
|
else
|
||||||
return this; // Doesn't make sense to resize non-vector type
|
return this; // Doesn't make sense to resize non-vector type
|
||||||
|
|
||||||
vhdl_fcall *resize = new vhdl_fcall("Resize", rtype);
|
vhdl_fcall *resizef = new vhdl_fcall("Resize", rtype);
|
||||||
resize->add_expr(this);
|
resizef->add_expr(this);
|
||||||
resize->add_expr(new vhdl_const_int(newwidth));
|
resizef->add_expr(new vhdl_const_int(newwidth));
|
||||||
|
|
||||||
return resize;
|
return resizef;
|
||||||
}
|
}
|
||||||
|
|
||||||
vhdl_expr *vhdl_const_int::to_vector(vhdl_type_name_t name, int w)
|
vhdl_expr *vhdl_const_int::to_vector(vhdl_type_name_t name, int w)
|
||||||
|
|
|
||||||
|
|
@ -157,10 +157,10 @@ int draw_stask_display(vhdl_procedural *proc, stmt_container *container,
|
||||||
// function in VHDL
|
// function in VHDL
|
||||||
|
|
||||||
assert(i < count);
|
assert(i < count);
|
||||||
ivl_expr_t net = ivl_stmt_parm(stmt, i++);
|
ivl_expr_t netp = ivl_stmt_parm(stmt, i++);
|
||||||
assert(net);
|
assert(netp);
|
||||||
|
|
||||||
vhdl_expr *base = translate_expr(net);
|
vhdl_expr *base = translate_expr(netp);
|
||||||
if (NULL == base)
|
if (NULL == base)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -698,11 +698,11 @@ static int draw_constant_drivers(ivl_scope_t scope, void *_parent)
|
||||||
for (int i = 0; i < nsigs; i++) {
|
for (int i = 0; i < nsigs; i++) {
|
||||||
ivl_signal_t sig = ivl_scope_sig(scope, i);
|
ivl_signal_t sig = ivl_scope_sig(scope, i);
|
||||||
|
|
||||||
for (unsigned i = ivl_signal_array_base(sig);
|
for (unsigned j = ivl_signal_array_base(sig);
|
||||||
i < ivl_signal_array_count(sig);
|
j < ivl_signal_array_count(sig);
|
||||||
i++) {
|
j++) {
|
||||||
// Make sure the nexus code is generated
|
// Make sure the nexus code is generated
|
||||||
ivl_nexus_t nex = ivl_signal_nex(sig, i);
|
ivl_nexus_t nex = ivl_signal_nex(sig, j);
|
||||||
seen_nexus(nex);
|
seen_nexus(nex);
|
||||||
|
|
||||||
nexus_private_t *priv =
|
nexus_private_t *priv =
|
||||||
|
|
@ -712,7 +712,7 @@ static int draw_constant_drivers(ivl_scope_t scope, void *_parent)
|
||||||
vhdl_scope *arch_scope = ent->get_arch()->get_scope();
|
vhdl_scope *arch_scope = ent->get_arch()->get_scope();
|
||||||
|
|
||||||
if (priv->const_driver) {
|
if (priv->const_driver) {
|
||||||
assert(i == 0); // TODO: Make work for more words
|
assert(j == 0); // TODO: Make work for more words
|
||||||
|
|
||||||
vhdl_var_ref *ref = nexus_to_var_ref(arch_scope, nex);
|
vhdl_var_ref *ref = nexus_to_var_ref(arch_scope, nex);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -424,8 +424,8 @@ static int draw_wait(vhdl_procedural *_proc, stmt_container *container,
|
||||||
ivl_event_t event = ivl_stmt_events(stmt, i);
|
ivl_event_t event = ivl_stmt_events(stmt, i);
|
||||||
|
|
||||||
int nany = ivl_event_nany(event);
|
int nany = ivl_event_nany(event);
|
||||||
for (int i = 0; i < nany; i++) {
|
for (int j = 0; j < nany; j++) {
|
||||||
ivl_nexus_t nexus = ivl_event_any(event, i);
|
ivl_nexus_t nexus = ivl_event_any(event, j);
|
||||||
vhdl_var_ref *ref = nexus_to_var_ref(proc->get_scope(), nexus);
|
vhdl_var_ref *ref = nexus_to_var_ref(proc->get_scope(), nexus);
|
||||||
|
|
||||||
wait->add_sensitivity(ref->get_name());
|
wait->add_sensitivity(ref->get_name());
|
||||||
|
|
@ -441,8 +441,8 @@ static int draw_wait(vhdl_procedural *_proc, stmt_container *container,
|
||||||
ivl_event_t event = ivl_stmt_events(stmt, i);
|
ivl_event_t event = ivl_stmt_events(stmt, i);
|
||||||
|
|
||||||
int nany = ivl_event_nany(event);
|
int nany = ivl_event_nany(event);
|
||||||
for (int i = 0; i < nany; i++) {
|
for (int j = 0; j < nany; j++) {
|
||||||
ivl_nexus_t nexus = ivl_event_any(event, i);
|
ivl_nexus_t nexus = ivl_event_any(event, j);
|
||||||
vhdl_var_ref *ref = nexus_to_var_ref(proc->get_scope(), nexus);
|
vhdl_var_ref *ref = nexus_to_var_ref(proc->get_scope(), nexus);
|
||||||
|
|
||||||
ref->set_name(ref->get_name() + "'Event");
|
ref->set_name(ref->get_name() + "'Event");
|
||||||
|
|
@ -450,8 +450,8 @@ static int draw_wait(vhdl_procedural *_proc, stmt_container *container,
|
||||||
}
|
}
|
||||||
|
|
||||||
int nneg = ivl_event_nneg(event);
|
int nneg = ivl_event_nneg(event);
|
||||||
for (int i = 0; i < nneg; i++) {
|
for (int j = 0; j < nneg; j++) {
|
||||||
ivl_nexus_t nexus = ivl_event_neg(event, i);
|
ivl_nexus_t nexus = ivl_event_neg(event, j);
|
||||||
vhdl_var_ref *ref = nexus_to_var_ref(proc->get_scope(), nexus);
|
vhdl_var_ref *ref = nexus_to_var_ref(proc->get_scope(), nexus);
|
||||||
vhdl_fcall *detect =
|
vhdl_fcall *detect =
|
||||||
new vhdl_fcall("falling_edge", vhdl_type::boolean());
|
new vhdl_fcall("falling_edge", vhdl_type::boolean());
|
||||||
|
|
@ -461,8 +461,8 @@ static int draw_wait(vhdl_procedural *_proc, stmt_container *container,
|
||||||
}
|
}
|
||||||
|
|
||||||
int npos = ivl_event_npos(event);
|
int npos = ivl_event_npos(event);
|
||||||
for (int i = 0; i < npos; i++) {
|
for (int j = 0; j < npos; j++) {
|
||||||
ivl_nexus_t nexus = ivl_event_pos(event, i);
|
ivl_nexus_t nexus = ivl_event_pos(event, j);
|
||||||
vhdl_var_ref *ref = nexus_to_var_ref(proc->get_scope(), nexus);
|
vhdl_var_ref *ref = nexus_to_var_ref(proc->get_scope(), nexus);
|
||||||
vhdl_fcall *detect =
|
vhdl_fcall *detect =
|
||||||
new vhdl_fcall("rising_edge", vhdl_type::boolean());
|
new vhdl_fcall("rising_edge", vhdl_type::boolean());
|
||||||
|
|
|
||||||
|
|
@ -354,23 +354,17 @@ static int draw_signal_real_real(ivl_expr_t exp)
|
||||||
{
|
{
|
||||||
ivl_signal_t sig = ivl_expr_signal(exp);
|
ivl_signal_t sig = ivl_expr_signal(exp);
|
||||||
int res = allocate_word();
|
int res = allocate_word();
|
||||||
unsigned long word = 0;
|
|
||||||
|
|
||||||
if (ivl_signal_dimensions(sig) > 0) {
|
if (ivl_signal_dimensions(sig) == 0) {
|
||||||
ivl_expr_t ix = ivl_expr_oper1(exp);
|
fprintf(vvp_out, " %%load/wr %d, v%p_0;\n", res, sig);
|
||||||
if (!number_is_immediate(ix, IMM_WID, 0)) {
|
|
||||||
/* XXXX Need to generate a %load/ar instruction. */
|
|
||||||
assert(0);
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The index is constant, so we can return to direct
|
ivl_expr_t word_ex = ivl_expr_oper1(exp);
|
||||||
readout with the specific word selected. */
|
int word_ix = allocate_word();
|
||||||
word = get_number_immediate(ix);
|
draw_eval_expr_into_integer(word_ex, word_ix);
|
||||||
}
|
fprintf(vvp_out, " %%load/ar %d, v%p, %d;\n", res, sig, word_ix);
|
||||||
|
clr_word(word_ix);
|
||||||
fprintf(vvp_out, " %%load/wr %d, v%p_%lu;\n", res, sig, word);
|
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -497,16 +497,30 @@ static int show_stmt_assign_sig_real(ivl_statement_t net)
|
||||||
ivl_signal_t var;
|
ivl_signal_t var;
|
||||||
|
|
||||||
res = draw_eval_real(ivl_stmt_rval(net));
|
res = draw_eval_real(ivl_stmt_rval(net));
|
||||||
clr_word(res);
|
|
||||||
|
|
||||||
assert(ivl_stmt_lvals(net) == 1);
|
assert(ivl_stmt_lvals(net) == 1);
|
||||||
lval = ivl_stmt_lval(net, 0);
|
lval = ivl_stmt_lval(net, 0);
|
||||||
var = ivl_lval_sig(lval);
|
var = ivl_lval_sig(lval);
|
||||||
assert(var != 0);
|
assert(var != 0);
|
||||||
|
|
||||||
assert(ivl_signal_dimensions(var) == 0);
|
if (ivl_signal_dimensions(var) == 0) {
|
||||||
|
clr_word(res);
|
||||||
fprintf(vvp_out, " %%set/wr v%p_0, %d;\n", var, res);
|
fprintf(vvp_out, " %%set/wr v%p_0, %d;\n", var, res);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For now, only support 1-dimensional arrays.
|
||||||
|
assert(ivl_signal_dimensions(var) == 1);
|
||||||
|
|
||||||
|
// Calculate the word index into an index register
|
||||||
|
ivl_expr_t word_ex = ivl_lval_idx(lval);
|
||||||
|
int word_ix = allocate_word();
|
||||||
|
draw_eval_expr_into_integer(word_ex, word_ix);
|
||||||
|
// Generate an assignment to write to the array.
|
||||||
|
fprintf(vvp_out, " %%set/ar v%p, %d, %d;\n", var, word_ix, res);
|
||||||
|
|
||||||
|
clr_word(res);
|
||||||
|
clr_word(word_ix);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1170,6 +1170,8 @@ static void draw_lpm_add(ivl_lpm_t net)
|
||||||
case IVL_LPM_MOD:
|
case IVL_LPM_MOD:
|
||||||
if (dto == IVL_VT_REAL)
|
if (dto == IVL_VT_REAL)
|
||||||
type = "mod.r";
|
type = "mod.r";
|
||||||
|
else if (ivl_lpm_signed(net))
|
||||||
|
type = "mod.s";
|
||||||
else
|
else
|
||||||
type = "mod";
|
type = "mod";
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -100,7 +100,8 @@ static int vpi_get_dec_size(vpiHandle item)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void array_from_iterator(struct strobe_cb_info*info, vpiHandle argv)
|
static int array_from_iterator(struct strobe_cb_info*info, vpiHandle argv,
|
||||||
|
int check_no_aa_vars)
|
||||||
{
|
{
|
||||||
if (argv) {
|
if (argv) {
|
||||||
vpiHandle item;
|
vpiHandle item;
|
||||||
|
|
@ -111,13 +112,17 @@ static void array_from_iterator(struct strobe_cb_info*info, vpiHandle argv)
|
||||||
free(items);
|
free(items);
|
||||||
info->nitems = 0;
|
info->nitems = 0;
|
||||||
info->items = 0;
|
info->items = 0;
|
||||||
return;
|
return check_no_aa_vars;
|
||||||
}
|
}
|
||||||
|
if (check_no_aa_vars && vpi_get(vpiAutomatic, items[0]))
|
||||||
|
check_no_aa_vars = 0;
|
||||||
|
|
||||||
for (item = vpi_scan(argv) ; item ; item = vpi_scan(argv)) {
|
for (item = vpi_scan(argv) ; item ; item = vpi_scan(argv)) {
|
||||||
items = realloc(items, (nitems+1)*sizeof(vpiHandle));
|
items = realloc(items, (nitems+1)*sizeof(vpiHandle));
|
||||||
items[nitems] = item;
|
items[nitems] = item;
|
||||||
nitems += 1;
|
nitems += 1;
|
||||||
|
if (check_no_aa_vars && vpi_get(vpiAutomatic, item))
|
||||||
|
check_no_aa_vars = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
info->nitems = nitems;
|
info->nitems = nitems;
|
||||||
|
|
@ -127,6 +132,7 @@ static void array_from_iterator(struct strobe_cb_info*info, vpiHandle argv)
|
||||||
info->nitems = 0;
|
info->nitems = 0;
|
||||||
info->items = 0;
|
info->items = 0;
|
||||||
}
|
}
|
||||||
|
return check_no_aa_vars;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -902,7 +908,7 @@ static PLI_INT32 sys_display_calltf(PLI_BYTE8*name)
|
||||||
info = malloc(sizeof (struct strobe_cb_info));
|
info = malloc(sizeof (struct strobe_cb_info));
|
||||||
info->default_format = get_default_format(name);
|
info->default_format = get_default_format(name);
|
||||||
info->scope = scope;
|
info->scope = scope;
|
||||||
array_from_iterator(info, argv);
|
array_from_iterator(info, argv, 0);
|
||||||
|
|
||||||
vpi_put_userdata(sys, info);
|
vpi_put_userdata(sys, info);
|
||||||
}
|
}
|
||||||
|
|
@ -995,7 +1001,13 @@ static PLI_INT32 sys_strobe_calltf(PLI_BYTE8*name)
|
||||||
info->mcd = 1;
|
info->mcd = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
array_from_iterator(info, argv);
|
if (!array_from_iterator(info, argv, 1)) {
|
||||||
|
vpi_printf("ERROR: %s parameters may not include automatically "
|
||||||
|
"allocated variables\n", name);
|
||||||
|
free(info->items);
|
||||||
|
free(info);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
info->name = strdup(name);
|
info->name = strdup(name);
|
||||||
info->default_format = get_default_format(name);
|
info->default_format = get_default_format(name);
|
||||||
info->scope= scope;
|
info->scope= scope;
|
||||||
|
|
@ -1095,7 +1107,13 @@ static PLI_INT32 sys_monitor_calltf(PLI_BYTE8*name)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make an array of handles from the argument list. */
|
/* Make an array of handles from the argument list. */
|
||||||
array_from_iterator(&monitor_info, argv);
|
if (!array_from_iterator(&monitor_info, argv, 1)) {
|
||||||
|
vpi_printf("ERROR: $monitor parameters may not include "
|
||||||
|
"automatically allocated variables\n");
|
||||||
|
free(monitor_info.items);
|
||||||
|
monitor_info.nitems = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
monitor_info.name = strdup(name);
|
monitor_info.name = strdup(name);
|
||||||
monitor_info.default_format = get_default_format(name);
|
monitor_info.default_format = get_default_format(name);
|
||||||
monitor_info.scope = scope;
|
monitor_info.scope = scope;
|
||||||
|
|
@ -1211,7 +1229,7 @@ static PLI_INT32 sys_fdisplay_calltf(PLI_BYTE8*name)
|
||||||
assert(scope);
|
assert(scope);
|
||||||
info.default_format = get_default_format(name);
|
info.default_format = get_default_format(name);
|
||||||
info.scope = scope;
|
info.scope = scope;
|
||||||
array_from_iterator(&info, argv);
|
array_from_iterator(&info, argv, 0);
|
||||||
do_display(mcd, &info);
|
do_display(mcd, &info);
|
||||||
free(info.items);
|
free(info.items);
|
||||||
|
|
||||||
|
|
@ -1969,7 +1987,7 @@ static PLI_INT32 sys_swrite_calltf(PLI_BYTE8 *name)
|
||||||
info.name = name;
|
info.name = name;
|
||||||
info.default_format = get_default_format(name);
|
info.default_format = get_default_format(name);
|
||||||
info.scope = scope;
|
info.scope = scope;
|
||||||
array_from_iterator(&info, argv);
|
array_from_iterator(&info, argv, 0);
|
||||||
|
|
||||||
/* Because %u and %z may put embedded NULL characters into the returned
|
/* Because %u and %z may put embedded NULL characters into the returned
|
||||||
* string strlen() may not match the real size! */
|
* string strlen() may not match the real size! */
|
||||||
|
|
@ -2049,7 +2067,7 @@ static PLI_INT32 sys_sformat_calltf(PLI_BYTE8 *name)
|
||||||
info.name = name;
|
info.name = name;
|
||||||
info.default_format = get_default_format(name);
|
info.default_format = get_default_format(name);
|
||||||
info.scope = scope;
|
info.scope = scope;
|
||||||
array_from_iterator(&info, argv);
|
array_from_iterator(&info, argv, 0);
|
||||||
idx = -1;
|
idx = -1;
|
||||||
size = get_format(&result, fmt, &info, &idx);
|
size = get_format(&result, fmt, &info, &idx);
|
||||||
free(fmt);
|
free(fmt);
|
||||||
|
|
|
||||||
65
vvp/arith.cc
65
vvp/arith.cc
|
|
@ -144,13 +144,25 @@ void vvp_arith_div::wide4_(vvp_net_ptr_t ptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
vvp_vector2_t b2 (op_b_);
|
vvp_vector2_t b2 (op_b_);
|
||||||
if (b2.is_NaN()) {
|
if (b2.is_NaN() || b2.is_zero()) {
|
||||||
vvp_send_vec4(ptr.ptr()->out, x_val_, 0);
|
vvp_send_vec4(ptr.ptr()->out, x_val_, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
vvp_vector2_t res2 = a2 / b2;
|
bool negate = false;
|
||||||
vvp_send_vec4(ptr.ptr()->out, vector2_to_vector4(res2, wid_), 0);
|
if (signed_flag_) {
|
||||||
|
if (a2.value(a2.size()-1)) {
|
||||||
|
a2 = -a2;
|
||||||
|
negate = true;
|
||||||
|
}
|
||||||
|
if (b2.value(b2.size()-1)) {
|
||||||
|
b2 = -b2;
|
||||||
|
negate = !negate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vvp_vector2_t res = a2 / b2;
|
||||||
|
if (negate) res = -res;
|
||||||
|
vvp_send_vec4(ptr.ptr()->out, vector2_to_vector4(res, wid_), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void vvp_arith_div::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
void vvp_arith_div::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||||
|
|
@ -180,17 +192,34 @@ void vvp_arith_div::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||||
the operands for now, and remember to put the sign back
|
the operands for now, and remember to put the sign back
|
||||||
later. */
|
later. */
|
||||||
if (signed_flag_) {
|
if (signed_flag_) {
|
||||||
|
unsigned long sign_mask = 0;
|
||||||
|
if (op_a_.size() != 8 * sizeof(unsigned long)) {
|
||||||
|
sign_mask = -1UL << op_a_.size();
|
||||||
|
}
|
||||||
if (op_a_.value(op_a_.size()-1)) {
|
if (op_a_.value(op_a_.size()-1)) {
|
||||||
a = (-a) & ~ (-1UL << op_a_.size());
|
a = (-a) & ~sign_mask;
|
||||||
negate = !negate;
|
negate = !negate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sign_mask = 0;
|
||||||
|
if (op_b_.size() != 8 * sizeof(unsigned long)) {
|
||||||
|
sign_mask = -1UL << op_b_.size();
|
||||||
|
}
|
||||||
if (op_b_.value(op_b_.size()-1)) {
|
if (op_b_.value(op_b_.size()-1)) {
|
||||||
b = (-b) & ~ (-1UL << op_b_.size());
|
b = (-b) & ~sign_mask;
|
||||||
negate = ! negate;
|
negate = ! negate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (b == 0) {
|
||||||
|
vvp_vector4_t xval (wid_);
|
||||||
|
for (unsigned idx = 0 ; idx < wid_ ; idx += 1)
|
||||||
|
xval.set_bit(idx, BIT4_X);
|
||||||
|
|
||||||
|
vvp_send_vec4(ptr.ptr()->out, xval, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned long val = a / b;
|
unsigned long val = a / b;
|
||||||
if (negate)
|
if (negate)
|
||||||
val = -val;
|
val = -val;
|
||||||
|
|
@ -229,12 +258,23 @@ void vvp_arith_mod::wide_(vvp_net_ptr_t ptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
vvp_vector2_t b2 (op_b_);
|
vvp_vector2_t b2 (op_b_);
|
||||||
if (b2.is_NaN()) {
|
if (b2.is_NaN() || b2.is_zero()) {
|
||||||
vvp_send_vec4(ptr.ptr()->out, x_val_, 0);
|
vvp_send_vec4(ptr.ptr()->out, x_val_, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool negate = false;
|
||||||
|
if (signed_flag_) {
|
||||||
|
if (a2.value(a2.size()-1)) {
|
||||||
|
a2 = -a2;
|
||||||
|
negate = true;
|
||||||
|
}
|
||||||
|
if (b2.value(b2.size()-1)) {
|
||||||
|
b2 = -b2;
|
||||||
|
}
|
||||||
|
}
|
||||||
vvp_vector2_t res = a2 % b2;
|
vvp_vector2_t res = a2 % b2;
|
||||||
|
if (negate) res = -res;
|
||||||
vvp_send_vec4(ptr.ptr()->out, vector2_to_vector4(res, res.size()), 0);
|
vvp_send_vec4(ptr.ptr()->out, vector2_to_vector4(res, res.size()), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -265,14 +305,21 @@ void vvp_arith_mod::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||||
the operands for now, and remember to put the sign back
|
the operands for now, and remember to put the sign back
|
||||||
later. */
|
later. */
|
||||||
if (signed_flag_) {
|
if (signed_flag_) {
|
||||||
|
unsigned long sign_mask = 0;
|
||||||
|
if (op_a_.size() != 8 * sizeof(unsigned long)) {
|
||||||
|
sign_mask = -1UL << op_a_.size();
|
||||||
|
}
|
||||||
if (op_a_.value(op_a_.size()-1)) {
|
if (op_a_.value(op_a_.size()-1)) {
|
||||||
a = (-a) & ~ (-1UL << op_a_.size());
|
a = (-a) & ~sign_mask;
|
||||||
negate = !negate;
|
negate = !negate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sign_mask = 0;
|
||||||
|
if (op_b_.size() != 8 * sizeof(unsigned long)) {
|
||||||
|
sign_mask = -1UL << op_b_.size();
|
||||||
|
}
|
||||||
if (op_b_.value(op_b_.size()-1)) {
|
if (op_b_.value(op_b_.size()-1)) {
|
||||||
b = (-b) & ~ (-1UL << op_b_.size());
|
b = (-b) & ~sign_mask;
|
||||||
negate = ! negate;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
123
vvp/array.cc
123
vvp/array.cc
|
|
@ -53,7 +53,28 @@ vvp_array_t array_find(const char*label)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The vpiArray object holds an array of vpi objects that themselves
|
* The vpiArray object holds an array of vpi objects that themselves
|
||||||
* represent the words of the array. The vpi_array_t is a pointer to this.
|
* represent the words of the array. The vpi_array_t is a pointer to
|
||||||
|
* a struct __vpiArray.
|
||||||
|
*
|
||||||
|
* The details of the implementation depends on what this is an array
|
||||||
|
* of. The easiest case is if this is an array of nets.
|
||||||
|
*
|
||||||
|
* - Array of Nets:
|
||||||
|
* If this represents an array of nets, then the nets member points to
|
||||||
|
* an array of vpiHandle objects. Each vpiHandle is a word. This is
|
||||||
|
* done because typically each word of a net array is simultaneously
|
||||||
|
* driven and accessed by other means, so there is no advantage to
|
||||||
|
* compacting the array in any other way.
|
||||||
|
*
|
||||||
|
* - Array of vector4 words.
|
||||||
|
* In this case, the nets pointer is nil, and the vals4 member points
|
||||||
|
* to a vvl_vector4array_t object that is a compact representation of
|
||||||
|
* an array of vvp_vector4_t vectors.
|
||||||
|
*
|
||||||
|
* - Array of real variables
|
||||||
|
* The valsr member points to a vvp_realarray_t objects that has an
|
||||||
|
* array of double variables. This is very much line the way the
|
||||||
|
* vector4 array works.
|
||||||
*/
|
*/
|
||||||
struct __vpiArray {
|
struct __vpiArray {
|
||||||
__vpiArray() { }
|
__vpiArray() { }
|
||||||
|
|
@ -70,7 +91,8 @@ struct __vpiArray {
|
||||||
// If this is a net array, nets lists the handles.
|
// If this is a net array, nets lists the handles.
|
||||||
vpiHandle*nets;
|
vpiHandle*nets;
|
||||||
// If this is a var array, then these are used instead of nets.
|
// If this is a var array, then these are used instead of nets.
|
||||||
vvp_vector4array_t *vals;
|
vvp_vector4array_t *vals4;
|
||||||
|
vvp_realarray_t *valsr;
|
||||||
struct __vpiArrayWord*vals_words;
|
struct __vpiArrayWord*vals_words;
|
||||||
|
|
||||||
class vvp_fun_arrayport*ports_;
|
class vvp_fun_arrayport*ports_;
|
||||||
|
|
@ -127,7 +149,7 @@ struct __vpiArrayVthrA {
|
||||||
/* Get the array word size. This has only been checked for reg arrays. */
|
/* Get the array word size. This has only been checked for reg arrays. */
|
||||||
unsigned get_array_word_size(vvp_array_t array)
|
unsigned get_array_word_size(vvp_array_t array)
|
||||||
{
|
{
|
||||||
assert(array->vals);
|
assert(array->vals4);
|
||||||
return array->vals_width;
|
return array->vals_width;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -424,7 +446,7 @@ static int vpi_array_var_word_get(int code, vpiHandle ref)
|
||||||
|
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case vpiSize:
|
case vpiSize:
|
||||||
return (int) parent->vals->width();
|
return (int) parent->vals4->width();
|
||||||
|
|
||||||
case vpiLeftRange:
|
case vpiLeftRange:
|
||||||
return parent->msb.value;
|
return parent->msb.value;
|
||||||
|
|
@ -432,6 +454,9 @@ static int vpi_array_var_word_get(int code, vpiHandle ref)
|
||||||
case vpiRightRange:
|
case vpiRightRange:
|
||||||
return parent->lsb.value;
|
return parent->lsb.value;
|
||||||
|
|
||||||
|
case vpiAutomatic:
|
||||||
|
return (int) parent->scope->is_automatic;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -461,9 +486,9 @@ static void vpi_array_var_word_get_value(vpiHandle ref, p_vpi_value value)
|
||||||
|
|
||||||
assert(obj);
|
assert(obj);
|
||||||
unsigned index = decode_array_word_pointer(obj, parent);
|
unsigned index = decode_array_word_pointer(obj, parent);
|
||||||
unsigned width = parent->vals->width();
|
unsigned width = parent->vals4->width();
|
||||||
|
|
||||||
vpip_vec4_get_value(parent->vals->get_word(index), width,
|
vpip_vec4_get_value(parent->vals4->get_word(index), width,
|
||||||
parent->signed_flag, value);
|
parent->signed_flag, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -539,7 +564,7 @@ static vpiHandle array_iterator_scan(vpiHandle ref, int)
|
||||||
if (obj->array->nets)
|
if (obj->array->nets)
|
||||||
return obj->array->nets[obj->next];
|
return obj->array->nets[obj->next];
|
||||||
|
|
||||||
assert(obj->array->vals);
|
assert(obj->array->vals4);
|
||||||
|
|
||||||
if (obj->array->vals_words == 0)
|
if (obj->array->vals_words == 0)
|
||||||
array_make_vals_words(obj->array);
|
array_make_vals_words(obj->array);
|
||||||
|
|
@ -612,6 +637,9 @@ static int vpi_array_vthr_A_get(int code, vpiHandle ref)
|
||||||
case vpiRightRange:
|
case vpiRightRange:
|
||||||
return parent->lsb.value;
|
return parent->lsb.value;
|
||||||
|
|
||||||
|
case vpiAutomatic:
|
||||||
|
return (int) parent->scope->is_automatic;
|
||||||
|
|
||||||
// For now &A<> is only a constant select. This will need
|
// For now &A<> is only a constant select. This will need
|
||||||
// to be changed when it supports variable selection.
|
// to be changed when it supports variable selection.
|
||||||
case vpiConstantSelect:
|
case vpiConstantSelect:
|
||||||
|
|
@ -702,10 +730,10 @@ void array_set_word(vvp_array_t arr,
|
||||||
if (address >= arr->array_count)
|
if (address >= arr->array_count)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (arr->vals) {
|
if (arr->vals4) {
|
||||||
assert(arr->nets == 0);
|
assert(arr->nets == 0);
|
||||||
if (part_off != 0 || val.size() != arr->vals_width) {
|
if (part_off != 0 || val.size() != arr->vals_width) {
|
||||||
vvp_vector4_t tmp = arr->vals->get_word(address);
|
vvp_vector4_t tmp = arr->vals4->get_word(address);
|
||||||
if ((part_off + val.size()) > tmp.size()) {
|
if ((part_off + val.size()) > tmp.size()) {
|
||||||
cerr << "part_off=" << part_off
|
cerr << "part_off=" << part_off
|
||||||
<< " val.size()=" << val.size()
|
<< " val.size()=" << val.size()
|
||||||
|
|
@ -714,9 +742,9 @@ void array_set_word(vvp_array_t arr,
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
tmp.set_vec(part_off, val);
|
tmp.set_vec(part_off, val);
|
||||||
arr->vals->set_word(address, tmp);
|
arr->vals4->set_word(address, tmp);
|
||||||
} else {
|
} else {
|
||||||
arr->vals->set_word(address, val);
|
arr->vals4->set_word(address, val);
|
||||||
}
|
}
|
||||||
array_word_change(arr, address);
|
array_word_change(arr, address);
|
||||||
return;
|
return;
|
||||||
|
|
@ -734,15 +762,22 @@ void array_set_word(vvp_array_t arr,
|
||||||
array_word_change(arr, address);
|
array_word_change(arr, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
vvp_vector4_t array_get_word(vvp_array_t arr, unsigned address)
|
void array_set_word(vvp_array_t arr, unsigned address, double val)
|
||||||
{
|
{
|
||||||
if (arr->vals) {
|
assert(arr->valsr!= 0);
|
||||||
assert(arr->nets == 0);
|
assert(arr->nets == 0);
|
||||||
|
|
||||||
return arr->vals->get_word(address);
|
arr->valsr->set_word(address, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
vvp_vector4_t array_get_word(vvp_array_t arr, unsigned address)
|
||||||
|
{
|
||||||
|
if (arr->vals4) {
|
||||||
|
assert(arr->nets == 0);
|
||||||
|
return arr->vals4->get_word(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(arr->vals == 0);
|
assert(arr->vals4 == 0);
|
||||||
assert(arr->nets != 0);
|
assert(arr->nets != 0);
|
||||||
|
|
||||||
if (address >= arr->array_count) {
|
if (address >= arr->array_count) {
|
||||||
|
|
@ -767,6 +802,26 @@ vvp_vector4_t array_get_word(vvp_array_t arr, unsigned address)
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double array_get_word_r(vvp_array_t arr, unsigned address)
|
||||||
|
{
|
||||||
|
if (arr->valsr) {
|
||||||
|
assert(arr->vals4 == 0);
|
||||||
|
assert(arr->nets == 0);
|
||||||
|
return arr->valsr->get_word(address);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(arr->nets);
|
||||||
|
vpiHandle word = arr->nets[address];
|
||||||
|
struct __vpiRealVar*vsig = vpip_realvar_from_handle(word);
|
||||||
|
assert(vsig);
|
||||||
|
vvp_fun_signal_real*sig = dynamic_cast<vvp_fun_signal_real*> (vsig->net->fun);
|
||||||
|
assert(sig);
|
||||||
|
|
||||||
|
double val = sig->real_value();
|
||||||
|
return val;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static vpiHandle vpip_make_array(char*label, const char*name,
|
static vpiHandle vpip_make_array(char*label, const char*name,
|
||||||
int first_addr, int last_addr,
|
int first_addr, int last_addr,
|
||||||
bool signed_flag)
|
bool signed_flag)
|
||||||
|
|
@ -792,7 +847,8 @@ static vpiHandle vpip_make_array(char*label, const char*name,
|
||||||
|
|
||||||
// Start off now knowing if we are nets or variables.
|
// Start off now knowing if we are nets or variables.
|
||||||
obj->nets = 0;
|
obj->nets = 0;
|
||||||
obj->vals = 0;
|
obj->vals4 = 0;
|
||||||
|
obj->valsr = 0;
|
||||||
obj->vals_width = 0;
|
obj->vals_width = 0;
|
||||||
vpip_make_dec_const(&obj->msb, 0);
|
vpip_make_dec_const(&obj->msb, 0);
|
||||||
vpip_make_dec_const(&obj->lsb, 0);
|
vpip_make_dec_const(&obj->lsb, 0);
|
||||||
|
|
@ -842,6 +898,19 @@ void array_attach_word(vvp_array_t array, unsigned long addr, vpiHandle word)
|
||||||
sig->is_netarray = 1;
|
sig->is_netarray = 1;
|
||||||
sig->within.parent = &array->base;
|
sig->within.parent = &array->base;
|
||||||
sig->id.index = vpip_make_dec_const(addr + array->first_addr.value);
|
sig->id.index = vpip_make_dec_const(addr + array->first_addr.value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (struct __vpiRealVar*sig = (struct __vpiRealVar*)word) {
|
||||||
|
vvp_net_t*net = sig->net;
|
||||||
|
assert(net);
|
||||||
|
vvp_fun_signal_base*fun = dynamic_cast<vvp_fun_signal_base*>(net->fun);
|
||||||
|
assert(fun);
|
||||||
|
fun->attach_as_word(array, addr);
|
||||||
|
sig->is_netarray = 1;
|
||||||
|
sig->within.parent = &array->base;
|
||||||
|
sig->id.index = vpip_make_dec_const(addr + array->first_addr.value);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -856,10 +925,10 @@ void compile_var_array(char*label, char*name, int last, int first,
|
||||||
/* Make the words. */
|
/* Make the words. */
|
||||||
arr->vals_width = labs(msb-lsb) + 1;
|
arr->vals_width = labs(msb-lsb) + 1;
|
||||||
if (vpip_peek_current_scope()->is_automatic) {
|
if (vpip_peek_current_scope()->is_automatic) {
|
||||||
arr->vals = new vvp_vector4array_aa(arr->vals_width,
|
arr->vals4 = new vvp_vector4array_aa(arr->vals_width,
|
||||||
arr->array_count);
|
arr->array_count);
|
||||||
} else {
|
} else {
|
||||||
arr->vals = new vvp_vector4array_sa(arr->vals_width,
|
arr->vals4 = new vvp_vector4array_sa(arr->vals_width,
|
||||||
arr->array_count);
|
arr->array_count);
|
||||||
}
|
}
|
||||||
vpip_make_dec_const(&arr->msb, msb);
|
vpip_make_dec_const(&arr->msb, msb);
|
||||||
|
|
@ -878,14 +947,16 @@ void compile_real_array(char*label, char*name, int last, int first,
|
||||||
vpiHandle obj = vpip_make_array(label, name, first, last, true);
|
vpiHandle obj = vpip_make_array(label, name, first, last, true);
|
||||||
|
|
||||||
struct __vpiArray*arr = ARRAY_HANDLE(obj);
|
struct __vpiArray*arr = ARRAY_HANDLE(obj);
|
||||||
vvp_array_t array = array_find(label);
|
|
||||||
|
|
||||||
/* Make the words. */
|
/* Make the words. */
|
||||||
for (unsigned idx = 0 ; idx < arr->array_count ; idx += 1) {
|
arr->valsr = new vvp_realarray_t(arr->array_count);
|
||||||
char buf[64];
|
arr->vals_width = 1;
|
||||||
snprintf(buf, sizeof buf, "%s_%u", label, idx);
|
|
||||||
compile_varw_real(strdup(buf), array, idx, msb, lsb);
|
/* Do these even make sense for real arrays? These are the
|
||||||
}
|
part select of a vector, but the real value is not
|
||||||
|
vectorable. */
|
||||||
|
vpip_make_dec_const(&arr->msb, msb);
|
||||||
|
vpip_make_dec_const(&arr->lsb, lsb);
|
||||||
|
|
||||||
count_real_arrays += 1;
|
count_real_arrays += 1;
|
||||||
count_real_array_words += arr->array_count;
|
count_real_array_words += arr->array_count;
|
||||||
|
|
@ -1133,7 +1204,7 @@ void array_word_change(vvp_array_t array, unsigned long addr)
|
||||||
|
|
||||||
if (cur->cb_data.cb_rtn != 0) {
|
if (cur->cb_data.cb_rtn != 0) {
|
||||||
if (cur->cb_data.value)
|
if (cur->cb_data.value)
|
||||||
vpip_vec4_get_value(array->vals->get_word(addr),
|
vpip_vec4_get_value(array->vals4->get_word(addr),
|
||||||
array->vals_width,
|
array->vals_width,
|
||||||
array->signed_flag,
|
array->signed_flag,
|
||||||
cur->cb_data.value);
|
cur->cb_data.value);
|
||||||
|
|
@ -1269,7 +1340,7 @@ void compile_array_alias(char*label, char*name, char*src)
|
||||||
|
|
||||||
// Share the words with the source array.
|
// Share the words with the source array.
|
||||||
obj->nets = mem->nets;
|
obj->nets = mem->nets;
|
||||||
obj->vals = mem->vals;
|
obj->vals4 = mem->vals4;
|
||||||
|
|
||||||
obj->ports_ = 0;
|
obj->ports_ = 0;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -39,12 +39,13 @@ extern void array_attach_word(vvp_array_t array, unsigned long addr,
|
||||||
extern void array_alias_word(vvp_array_t array, unsigned long addr,
|
extern void array_alias_word(vvp_array_t array, unsigned long addr,
|
||||||
vpiHandle word);
|
vpiHandle word);
|
||||||
|
|
||||||
extern void array_set_word(vvp_array_t arr,
|
extern void array_set_word(vvp_array_t arr, unsigned idx,
|
||||||
unsigned idx,
|
unsigned off, vvp_vector4_t val);
|
||||||
unsigned off,
|
extern void array_set_word(vvp_array_t arr, unsigned idx,
|
||||||
vvp_vector4_t val);
|
double val);
|
||||||
|
|
||||||
extern vvp_vector4_t array_get_word(vvp_array_t array, unsigned address);
|
extern vvp_vector4_t array_get_word(vvp_array_t array, unsigned address);
|
||||||
|
extern double array_get_word_r(vvp_array_t array, unsigned address);
|
||||||
|
|
||||||
/* VPI hooks */
|
/* VPI hooks */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -107,6 +107,7 @@ extern bool of_JMP0(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_JMP0XZ(vthread_t thr, vvp_code_t code);
|
extern bool of_JMP0XZ(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_JMP1(vthread_t thr, vvp_code_t code);
|
extern bool of_JMP1(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_JOIN(vthread_t thr, vvp_code_t code);
|
extern bool of_JOIN(vthread_t thr, vvp_code_t code);
|
||||||
|
extern bool of_LOAD_AR(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_LOAD_AV(vthread_t thr, vvp_code_t code);
|
extern bool of_LOAD_AV(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_LOAD_AVP0(vthread_t thr, vvp_code_t code);
|
extern bool of_LOAD_AVP0(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_LOAD_AVP0_S(vthread_t thr, vvp_code_t code);
|
extern bool of_LOAD_AVP0_S(vthread_t thr, vvp_code_t code);
|
||||||
|
|
@ -138,6 +139,7 @@ extern bool of_POW_WR(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_RELEASE_NET(vthread_t thr, vvp_code_t code);
|
extern bool of_RELEASE_NET(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_RELEASE_REG(vthread_t thr, vvp_code_t code);
|
extern bool of_RELEASE_REG(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_RELEASE_WR(vthread_t thr, vvp_code_t code);
|
extern bool of_RELEASE_WR(vthread_t thr, vvp_code_t code);
|
||||||
|
extern bool of_SET_AR(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_SET_AV(vthread_t thr, vvp_code_t code);
|
extern bool of_SET_AV(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_SET_VEC(vthread_t thr, vvp_code_t code);
|
extern bool of_SET_VEC(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_SET_WORDR(vthread_t thr, vvp_code_t code);
|
extern bool of_SET_WORDR(vthread_t thr, vvp_code_t code);
|
||||||
|
|
|
||||||
|
|
@ -150,6 +150,7 @@ const static struct opcode_table_s opcode_table[] = {
|
||||||
{ "%jmp/0xz",of_JMP0XZ, 2, {OA_CODE_PTR, OA_BIT1, OA_NONE} },
|
{ "%jmp/0xz",of_JMP0XZ, 2, {OA_CODE_PTR, OA_BIT1, OA_NONE} },
|
||||||
{ "%jmp/1", of_JMP1, 2, {OA_CODE_PTR, OA_BIT1, OA_NONE} },
|
{ "%jmp/1", of_JMP1, 2, {OA_CODE_PTR, OA_BIT1, OA_NONE} },
|
||||||
{ "%join", of_JOIN, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
{ "%join", of_JOIN, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||||
|
{ "%load/ar",of_LOAD_AR,3, {OA_BIT1, OA_ARR_PTR, OA_BIT2} },
|
||||||
{ "%load/av",of_LOAD_AV,3, {OA_BIT1, OA_ARR_PTR, OA_BIT2} },
|
{ "%load/av",of_LOAD_AV,3, {OA_BIT1, OA_ARR_PTR, OA_BIT2} },
|
||||||
{ "%load/avp0",of_LOAD_AVP0,3, {OA_BIT1, OA_ARR_PTR, OA_BIT2} },
|
{ "%load/avp0",of_LOAD_AVP0,3, {OA_BIT1, OA_ARR_PTR, OA_BIT2} },
|
||||||
{ "%load/avp0/s",of_LOAD_AVP0_S,3,{OA_BIT1, OA_ARR_PTR, OA_BIT2} },
|
{ "%load/avp0/s",of_LOAD_AVP0_S,3,{OA_BIT1, OA_ARR_PTR, OA_BIT2} },
|
||||||
|
|
@ -181,11 +182,11 @@ const static struct opcode_table_s opcode_table[] = {
|
||||||
{ "%release/net",of_RELEASE_NET,3,{OA_FUNC_PTR,OA_BIT1,OA_BIT2} },
|
{ "%release/net",of_RELEASE_NET,3,{OA_FUNC_PTR,OA_BIT1,OA_BIT2} },
|
||||||
{ "%release/reg",of_RELEASE_REG,3,{OA_FUNC_PTR,OA_BIT1,OA_BIT2} },
|
{ "%release/reg",of_RELEASE_REG,3,{OA_FUNC_PTR,OA_BIT1,OA_BIT2} },
|
||||||
{ "%release/wr",of_RELEASE_WR,2,{OA_FUNC_PTR,OA_BIT1,OA_NONE} },
|
{ "%release/wr",of_RELEASE_WR,2,{OA_FUNC_PTR,OA_BIT1,OA_NONE} },
|
||||||
|
{ "%set/ar", of_SET_AR, 3, {OA_ARR_PTR, OA_BIT1, OA_BIT2} },
|
||||||
{ "%set/av", of_SET_AV, 3, {OA_ARR_PTR, OA_BIT1, OA_BIT2} },
|
{ "%set/av", of_SET_AV, 3, {OA_ARR_PTR, OA_BIT1, OA_BIT2} },
|
||||||
{ "%set/v", of_SET_VEC,3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
|
{ "%set/v", of_SET_VEC,3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
|
||||||
{ "%set/wr", of_SET_WORDR,2,{OA_FUNC_PTR, OA_BIT1, OA_NONE} },
|
{ "%set/wr", of_SET_WORDR,2,{OA_FUNC_PTR, OA_BIT1, OA_NONE} },
|
||||||
{ "%set/x0", of_SET_X0, 3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
|
{ "%set/x0", of_SET_X0, 3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
|
||||||
// { "%set/x0/x",of_SET_X0_X,3,{OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
|
|
||||||
{ "%shiftl/i0", of_SHIFTL_I0, 2, {OA_BIT1,OA_NUMBER, OA_NONE} },
|
{ "%shiftl/i0", of_SHIFTL_I0, 2, {OA_BIT1,OA_NUMBER, OA_NONE} },
|
||||||
{ "%shiftr/i0", of_SHIFTR_I0, 2, {OA_BIT1,OA_NUMBER, OA_NONE} },
|
{ "%shiftr/i0", of_SHIFTR_I0, 2, {OA_BIT1,OA_NUMBER, OA_NONE} },
|
||||||
{ "%shiftr/s/i0", of_SHIFTR_S_I0,2,{OA_BIT1,OA_NUMBER, OA_NONE} },
|
{ "%shiftr/s/i0", of_SHIFTR_S_I0,2,{OA_BIT1,OA_NUMBER, OA_NONE} },
|
||||||
|
|
@ -978,7 +979,7 @@ void compile_arith_div_r(char*label, unsigned argc, struct symb_s*argv)
|
||||||
make_arith(arith, label, argc, argv);
|
make_arith(arith, label, argc, argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
void compile_arith_mod(char*label, long wid,
|
void compile_arith_mod(char*label, long wid, bool signed_flag,
|
||||||
unsigned argc, struct symb_s*argv)
|
unsigned argc, struct symb_s*argv)
|
||||||
{
|
{
|
||||||
assert( wid > 0 );
|
assert( wid > 0 );
|
||||||
|
|
@ -989,7 +990,7 @@ void compile_arith_mod(char*label, long wid,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
vvp_arith_ *arith = new vvp_arith_mod(wid, false);
|
vvp_arith_ *arith = new vvp_arith_mod(wid, signed_flag);
|
||||||
|
|
||||||
make_arith(arith, label, argc, argv);
|
make_arith(arith, label, argc, argv);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -157,7 +157,7 @@ extern void compile_arith_cast_real(char*label, bool signed_flag,
|
||||||
unsigned argc, struct symb_s*argv);
|
unsigned argc, struct symb_s*argv);
|
||||||
extern void compile_arith_div(char*label, long width, bool signed_flag,
|
extern void compile_arith_div(char*label, long width, bool signed_flag,
|
||||||
unsigned argc, struct symb_s*argv);
|
unsigned argc, struct symb_s*argv);
|
||||||
extern void compile_arith_mod(char*label, long width,
|
extern void compile_arith_mod(char*label, long width, bool signed_flag,
|
||||||
unsigned argc, struct symb_s*argv);
|
unsigned argc, struct symb_s*argv);
|
||||||
extern void compile_arith_mult(char*label, long width,
|
extern void compile_arith_mult(char*label, long width,
|
||||||
unsigned argc, struct symb_s*argv);
|
unsigned argc, struct symb_s*argv);
|
||||||
|
|
|
||||||
|
|
@ -93,6 +93,7 @@
|
||||||
".arith/div.s" { return K_ARITH_DIV_S; }
|
".arith/div.s" { return K_ARITH_DIV_S; }
|
||||||
".arith/mod" { return K_ARITH_MOD; }
|
".arith/mod" { return K_ARITH_MOD; }
|
||||||
".arith/mod.r" { return K_ARITH_MOD_R; }
|
".arith/mod.r" { return K_ARITH_MOD_R; }
|
||||||
|
".arith/mod.s" { return K_ARITH_MOD_S; }
|
||||||
".arith/mult" { return K_ARITH_MULT; }
|
".arith/mult" { return K_ARITH_MULT; }
|
||||||
".arith/mult.r" { return K_ARITH_MULT_R; }
|
".arith/mult.r" { return K_ARITH_MULT_R; }
|
||||||
".arith/pow" { return K_ARITH_POW; }
|
".arith/pow" { return K_ARITH_POW; }
|
||||||
|
|
|
||||||
|
|
@ -512,9 +512,14 @@ The <wid> is, line the %load/v, the result width. But unlike the
|
||||||
(%load/vp0/s) to the desired width.
|
(%load/vp0/s) to the desired width.
|
||||||
|
|
||||||
* %load/wr <bit>, <vpi-label>
|
* %load/wr <bit>, <vpi-label>
|
||||||
|
* %load/ar <bit>, <array-label>, <index>
|
||||||
|
|
||||||
This instruction reads a real value from the vpi-like object to a word
|
The %load/wr instruction reads a real value from the vpi-like object
|
||||||
register.
|
to a word register <bit>.
|
||||||
|
|
||||||
|
The %load/ar instruction reads a real value from an array. The <index>
|
||||||
|
is the index register that contains the canonical word address into
|
||||||
|
the array.
|
||||||
|
|
||||||
* %load/x1p <bit>, <functor-label>, <wid>
|
* %load/x1p <bit>, <functor-label>, <wid>
|
||||||
|
|
||||||
|
|
@ -708,8 +713,17 @@ The address (in canonical form) is precalculated and loaded into index
|
||||||
register 3. This is the address of the word within the array.
|
register 3. This is the address of the word within the array.
|
||||||
|
|
||||||
* %set/wr <vpi-label>, <bit>
|
* %set/wr <vpi-label>, <bit>
|
||||||
|
* %set/ar <array-label>, <index>, <bit>
|
||||||
|
|
||||||
This instruction writes a real word to the specified VPI-like object.
|
The %set/wr instruction writes a real word to the specified VPI-like
|
||||||
|
object.
|
||||||
|
|
||||||
|
The %set/ar instruction writes a real work to the specified array
|
||||||
|
word. The <array-label> addresses the array, and the <index> is the
|
||||||
|
name of the index register to address into the word. The index
|
||||||
|
register must contain an integer value that is the canonical address
|
||||||
|
of the array word. The <bit> is the index register that contains the
|
||||||
|
real value word to write.
|
||||||
|
|
||||||
* %set/x0 <var-label>, <bit>, <wid>
|
* %set/x0 <var-label>, <bit>, <wid>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ static struct __vpiModPath*modpath_dst = 0;
|
||||||
|
|
||||||
%token K_A K_ALIAS K_ALIAS_S K_ALIAS_R
|
%token K_A K_ALIAS K_ALIAS_S K_ALIAS_R
|
||||||
%token K_ARITH_ABS K_ARITH_DIV K_ARITH_DIV_R K_ARITH_DIV_S K_ARITH_MOD
|
%token K_ARITH_ABS K_ARITH_DIV K_ARITH_DIV_R K_ARITH_DIV_S K_ARITH_MOD
|
||||||
%token K_ARITH_MOD_R
|
%token K_ARITH_MOD_R K_ARITH_MOD_S
|
||||||
%token K_ARITH_MULT K_ARITH_MULT_R K_ARITH_SUB K_ARITH_SUB_R
|
%token K_ARITH_MULT K_ARITH_MULT_R K_ARITH_SUB K_ARITH_SUB_R
|
||||||
%token K_ARITH_SUM K_ARITH_SUM_R K_ARITH_POW K_ARITH_POW_R K_ARITH_POW_S
|
%token K_ARITH_SUM K_ARITH_SUM_R K_ARITH_POW K_ARITH_POW_R K_ARITH_POW_S
|
||||||
%token K_ARRAY K_ARRAY_I K_ARRAY_R K_ARRAY_S K_ARRAY_PORT
|
%token K_ARRAY K_ARRAY_I K_ARRAY_R K_ARRAY_S K_ARRAY_PORT
|
||||||
|
|
@ -288,7 +288,7 @@ statement
|
||||||
|
|
||||||
| T_LABEL K_ARITH_MOD T_NUMBER ',' symbols ';'
|
| T_LABEL K_ARITH_MOD T_NUMBER ',' symbols ';'
|
||||||
{ struct symbv_s obj = $5;
|
{ struct symbv_s obj = $5;
|
||||||
compile_arith_mod($1, $3, obj.cnt, obj.vect);
|
compile_arith_mod($1, $3, false, obj.cnt, obj.vect);
|
||||||
}
|
}
|
||||||
|
|
||||||
| T_LABEL K_ARITH_MOD_R T_NUMBER ',' symbols ';'
|
| T_LABEL K_ARITH_MOD_R T_NUMBER ',' symbols ';'
|
||||||
|
|
@ -296,6 +296,11 @@ statement
|
||||||
compile_arith_mod_r($1, obj.cnt, obj.vect);
|
compile_arith_mod_r($1, obj.cnt, obj.vect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
| T_LABEL K_ARITH_MOD_S T_NUMBER ',' symbols ';'
|
||||||
|
{ struct symbv_s obj = $5;
|
||||||
|
compile_arith_mod($1, $3, true, obj.cnt, obj.vect);
|
||||||
|
}
|
||||||
|
|
||||||
| T_LABEL K_ARITH_MULT T_NUMBER ',' symbols ';'
|
| T_LABEL K_ARITH_MULT T_NUMBER ',' symbols ';'
|
||||||
{ struct symbv_s obj = $5;
|
{ struct symbv_s obj = $5;
|
||||||
compile_arith_mult($1, $3, obj.cnt, obj.vect);
|
compile_arith_mult($1, $3, obj.cnt, obj.vect);
|
||||||
|
|
|
||||||
|
|
@ -119,6 +119,14 @@ void delete_vpi_callback(struct __vpiCallback* ref)
|
||||||
*/
|
*/
|
||||||
static struct __vpiCallback* make_value_change(p_cb_data data)
|
static struct __vpiCallback* make_value_change(p_cb_data data)
|
||||||
{
|
{
|
||||||
|
if (vpi_get(vpiAutomatic, data->obj)) {
|
||||||
|
fprintf(stderr, "vpi error: cannot place value change "
|
||||||
|
"callback on automatically allocated "
|
||||||
|
"variable '%s'\n",
|
||||||
|
vpi_get_str(vpiName, data->obj));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
struct __vpiCallback*obj = new_vpi_callback();
|
struct __vpiCallback*obj = new_vpi_callback();
|
||||||
obj->cb_data = *data;
|
obj->cb_data = *data;
|
||||||
if (data->time) {
|
if (data->time) {
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,9 @@ static int string_get(int code, vpiHandle ref)
|
||||||
case vpiConstType:
|
case vpiConstType:
|
||||||
return vpiStringConst;
|
return vpiStringConst;
|
||||||
|
|
||||||
|
case vpiAutomatic:
|
||||||
|
return 0;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "vvp error: get %d not supported "
|
fprintf(stderr, "vvp error: get %d not supported "
|
||||||
"by vpiStringConst\n", code);
|
"by vpiStringConst\n", code);
|
||||||
|
|
@ -343,6 +346,9 @@ static int binary_get(int code, vpiHandle ref)
|
||||||
case vpiSize:
|
case vpiSize:
|
||||||
return rfp->bits.size();
|
return rfp->bits.size();
|
||||||
|
|
||||||
|
case vpiAutomatic:
|
||||||
|
return 0;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "vvp error: get %d not supported "
|
fprintf(stderr, "vvp error: get %d not supported "
|
||||||
"by vpiBinaryConst\n", code);
|
"by vpiBinaryConst\n", code);
|
||||||
|
|
@ -533,6 +539,9 @@ static int dec_get(int code, vpiHandle ref)
|
||||||
case vpiSize:
|
case vpiSize:
|
||||||
return 32;
|
return 32;
|
||||||
|
|
||||||
|
case vpiAutomatic:
|
||||||
|
return 0;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "vvp error: get %d not supported "
|
fprintf(stderr, "vvp error: get %d not supported "
|
||||||
"by vpiDecConst\n", code);
|
"by vpiDecConst\n", code);
|
||||||
|
|
@ -636,6 +645,9 @@ static int real_get(int code, vpiHandle ref)
|
||||||
case vpiSigned:
|
case vpiSigned:
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
case vpiAutomatic:
|
||||||
|
return 0;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "vvp error: get %d not supported "
|
fprintf(stderr, "vvp error: get %d not supported "
|
||||||
"by vpiDecConst\n", code);
|
"by vpiDecConst\n", code);
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,14 @@ struct __vpiScope* vpip_scope(__vpiSignal*sig)
|
||||||
return sig->within.scope;
|
return sig->within.scope;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct __vpiScope* vpip_scope(__vpiRealVar*sig)
|
||||||
|
{
|
||||||
|
if (sig->is_netarray)
|
||||||
|
return (struct __vpiScope*) vpi_handle(vpiScope, sig->within.parent);
|
||||||
|
else
|
||||||
|
return sig->within.scope;
|
||||||
|
}
|
||||||
|
|
||||||
const char *vpip_string(const char*str)
|
const char *vpip_string(const char*str)
|
||||||
{
|
{
|
||||||
static vpip_string_chunk first_chunk = {0, {0}};
|
static vpip_string_chunk first_chunk = {0, {0}};
|
||||||
|
|
@ -684,6 +692,14 @@ vpiHandle vpi_put_value(vpiHandle obj, s_vpi_value*vp,
|
||||||
if (flags!=vpiNoDelay && flags!=vpiForceFlag && flags!=vpiReleaseFlag) {
|
if (flags!=vpiNoDelay && flags!=vpiForceFlag && flags!=vpiReleaseFlag) {
|
||||||
vvp_time64_t dly;
|
vvp_time64_t dly;
|
||||||
|
|
||||||
|
if (vpi_get(vpiAutomatic, obj)) {
|
||||||
|
fprintf(stderr, "vpi error: cannot put a value with "
|
||||||
|
"a delay on automatically allocated "
|
||||||
|
"variable '%s'\n",
|
||||||
|
vpi_get_str(vpiName, obj));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
assert(when != 0);
|
assert(when != 0);
|
||||||
|
|
||||||
switch (when->type) {
|
switch (when->type) {
|
||||||
|
|
|
||||||
|
|
@ -223,7 +223,6 @@ struct __vpiSignal {
|
||||||
unsigned signed_flag : 1;
|
unsigned signed_flag : 1;
|
||||||
unsigned isint_ : 1; // original type was integer
|
unsigned isint_ : 1; // original type was integer
|
||||||
unsigned is_netarray : 1; // This is word of a net array
|
unsigned is_netarray : 1; // This is word of a net array
|
||||||
unsigned is_automatic : 1;
|
|
||||||
/* The represented value is here. */
|
/* The represented value is here. */
|
||||||
vvp_net_t*node;
|
vvp_net_t*node;
|
||||||
};
|
};
|
||||||
|
|
@ -354,17 +353,22 @@ extern void vpip_real_value_change(struct __vpiCallback*cbh,
|
||||||
*/
|
*/
|
||||||
struct __vpiRealVar {
|
struct __vpiRealVar {
|
||||||
struct __vpiHandle base;
|
struct __vpiHandle base;
|
||||||
|
union { // The scope or parent array that contains me.
|
||||||
vpiHandle parent;
|
vpiHandle parent;
|
||||||
struct __vpiScope* scope;
|
struct __vpiScope* scope;
|
||||||
|
} within;
|
||||||
/* The name of this variable, or the index for array words. */
|
/* The name of this variable, or the index for array words. */
|
||||||
union {
|
union {
|
||||||
const char*name;
|
const char*name;
|
||||||
vpiHandle index;
|
vpiHandle index;
|
||||||
} id;
|
} id;
|
||||||
|
unsigned is_netarray : 1; // This is word of a net array
|
||||||
vvp_net_t*net;
|
vvp_net_t*net;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern struct __vpiScope* vpip_scope(__vpiRealVar*sig);
|
||||||
extern vpiHandle vpip_make_real_var(const char*name, vvp_net_t*net);
|
extern vpiHandle vpip_make_real_var(const char*name, vvp_net_t*net);
|
||||||
|
extern struct __vpiRealVar* vpip_realvar_from_handle(vpiHandle obj);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* When a loaded VPI module announces a system task/function, one
|
* When a loaded VPI module announces a system task/function, one
|
||||||
|
|
|
||||||
|
|
@ -28,15 +28,24 @@
|
||||||
#endif
|
#endif
|
||||||
# include <assert.h>
|
# include <assert.h>
|
||||||
|
|
||||||
|
struct __vpiRealVar* vpip_realvar_from_handle(vpiHandle obj)
|
||||||
|
{
|
||||||
|
assert(obj);
|
||||||
|
if (obj->vpi_type->type_code == vpiRealVar)
|
||||||
|
return (struct __vpiRealVar*)obj;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int real_var_get(int code, vpiHandle ref)
|
static int real_var_get(int code, vpiHandle ref)
|
||||||
{
|
{
|
||||||
assert(ref->vpi_type->type_code == vpiRealVar);
|
assert(ref->vpi_type->type_code == vpiRealVar);
|
||||||
|
|
||||||
struct __vpiRealVar*rfp = (struct __vpiRealVar*)ref;
|
struct __vpiRealVar*rfp = vpip_realvar_from_handle(ref);
|
||||||
|
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case vpiArray:
|
case vpiArray:
|
||||||
return rfp->parent != 0;
|
return rfp->is_netarray != 0;
|
||||||
|
|
||||||
case vpiSize:
|
case vpiSize:
|
||||||
return 1;
|
return 1;
|
||||||
|
|
@ -45,7 +54,7 @@ static int real_var_get(int code, vpiHandle ref)
|
||||||
return 0; // Not implemented for now!
|
return 0; // Not implemented for now!
|
||||||
|
|
||||||
case vpiAutomatic:
|
case vpiAutomatic:
|
||||||
return (int) rfp->scope->is_automatic;
|
return (int) vpip_scope(rfp)->is_automatic;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -62,8 +71,8 @@ static char* real_var_get_str(int code, vpiHandle ref)
|
||||||
}
|
}
|
||||||
|
|
||||||
char *nm, *ixs;
|
char *nm, *ixs;
|
||||||
if (rfp->parent) {
|
if (rfp->is_netarray) {
|
||||||
nm = strdup(vpi_get_str(vpiName, rfp->parent));
|
nm = strdup(vpi_get_str(vpiName, rfp->within.parent));
|
||||||
s_vpi_value vp;
|
s_vpi_value vp;
|
||||||
vp.format = vpiDecStrVal;
|
vp.format = vpiDecStrVal;
|
||||||
vpi_get_value(rfp->id.index, &vp);
|
vpi_get_value(rfp->id.index, &vp);
|
||||||
|
|
@ -73,7 +82,7 @@ static char* real_var_get_str(int code, vpiHandle ref)
|
||||||
ixs = NULL;
|
ixs = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *rbuf = generic_get_str(code, &rfp->scope->base, nm, ixs);
|
char *rbuf = generic_get_str(code, &(vpip_scope(rfp)->base), nm, ixs);
|
||||||
free(nm);
|
free(nm);
|
||||||
return rbuf;
|
return rbuf;
|
||||||
}
|
}
|
||||||
|
|
@ -87,10 +96,13 @@ static vpiHandle real_var_get_handle(int code, vpiHandle ref)
|
||||||
switch (code) {
|
switch (code) {
|
||||||
|
|
||||||
case vpiParent:
|
case vpiParent:
|
||||||
return rfp->parent;
|
return rfp->is_netarray ? rfp->within.parent : 0;
|
||||||
|
|
||||||
case vpiIndex:
|
case vpiIndex:
|
||||||
return rfp->parent ? rfp->id.index : 0;
|
return rfp->is_netarray ? rfp->id.index : 0;
|
||||||
|
|
||||||
|
case vpiScope:
|
||||||
|
return &(vpip_scope(rfp)->base);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -103,7 +115,7 @@ static vpiHandle real_var_iterate(int code, vpiHandle ref)
|
||||||
struct __vpiRealVar*rfp = (struct __vpiRealVar*)ref;
|
struct __vpiRealVar*rfp = (struct __vpiRealVar*)ref;
|
||||||
|
|
||||||
if (code == vpiIndex) {
|
if (code == vpiIndex) {
|
||||||
return rfp->parent ? (rfp->id.index->vpi_type->iterate_)
|
return rfp->is_netarray ? (rfp->id.index->vpi_type->iterate_)
|
||||||
(code, rfp->id.index) : 0;
|
(code, rfp->id.index) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -179,22 +191,17 @@ void vpip_real_value_change(struct __vpiCallback*cbh,
|
||||||
fun->add_vpi_callback(cbh);
|
fun->add_vpi_callback(cbh);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Since reals do not currently support arrays none of the array code
|
|
||||||
* has been tested! Though it should work since it is a copy of the
|
|
||||||
* signal code.
|
|
||||||
*/
|
|
||||||
vpiHandle vpip_make_real_var(const char*name, vvp_net_t*net)
|
vpiHandle vpip_make_real_var(const char*name, vvp_net_t*net)
|
||||||
{
|
{
|
||||||
struct __vpiRealVar*obj = (struct __vpiRealVar*)
|
struct __vpiRealVar*obj = (struct __vpiRealVar*)
|
||||||
malloc(sizeof(struct __vpiRealVar));
|
malloc(sizeof(struct __vpiRealVar));
|
||||||
|
|
||||||
obj->base.vpi_type = &vpip_real_var_rt;
|
obj->base.vpi_type = &vpip_real_var_rt;
|
||||||
obj->parent = 0;
|
|
||||||
obj->id.name = name ? vpip_name_string(name) : 0;
|
obj->id.name = name ? vpip_name_string(name) : 0;
|
||||||
|
obj->is_netarray = 0;
|
||||||
obj->net = net;
|
obj->net = net;
|
||||||
|
|
||||||
obj->scope = vpip_peek_current_scope();
|
obj->within.scope = vpip_peek_current_scope();
|
||||||
|
|
||||||
return &obj->base;
|
return &obj->base;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,9 @@ static int scope_get(int code, vpiHandle obj)
|
||||||
|
|
||||||
case vpiTopModule:
|
case vpiTopModule:
|
||||||
return 0x0 == ref->scope;
|
return 0x0 == ref->scope;
|
||||||
|
|
||||||
|
case vpiAutomatic:
|
||||||
|
return (int) ref->is_automatic;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -330,33 +333,29 @@ compile_scope_decl(char*label, char*type, char*name, const char*tname,
|
||||||
struct __vpiScope*scope = new struct __vpiScope;
|
struct __vpiScope*scope = new struct __vpiScope;
|
||||||
count_vpi_scopes += 1;
|
count_vpi_scopes += 1;
|
||||||
|
|
||||||
if (strcmp(type,"module") == 0) {
|
char*base_type = 0;
|
||||||
|
if (strncmp(type,"auto",4) == 0) {
|
||||||
|
scope->is_automatic = true;
|
||||||
|
base_type = &type[4];
|
||||||
|
} else {
|
||||||
|
scope->is_automatic = false;
|
||||||
|
base_type = &type[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(base_type,"module") == 0) {
|
||||||
scope->base.vpi_type = &vpip_scope_module_rt;
|
scope->base.vpi_type = &vpip_scope_module_rt;
|
||||||
scope->is_automatic = false;
|
} else if (strcmp(base_type,"function") == 0) {
|
||||||
} else if (strcmp(type,"autofunction") == 0) {
|
|
||||||
scope->base.vpi_type = &vpip_scope_function_rt;
|
scope->base.vpi_type = &vpip_scope_function_rt;
|
||||||
scope->is_automatic = true;
|
} else if (strcmp(base_type,"task") == 0) {
|
||||||
} else if (strcmp(type,"function") == 0) {
|
|
||||||
scope->base.vpi_type = &vpip_scope_function_rt;
|
|
||||||
scope->is_automatic = false;
|
|
||||||
} else if (strcmp(type,"autotask") == 0) {
|
|
||||||
scope->base.vpi_type = &vpip_scope_task_rt;
|
scope->base.vpi_type = &vpip_scope_task_rt;
|
||||||
scope->is_automatic = true;
|
} else if (strcmp(base_type,"fork") == 0) {
|
||||||
} else if (strcmp(type,"task") == 0) {
|
|
||||||
scope->base.vpi_type = &vpip_scope_task_rt;
|
|
||||||
scope->is_automatic = false;
|
|
||||||
} else if (strcmp(type,"fork") == 0) {
|
|
||||||
scope->base.vpi_type = &vpip_scope_fork_rt;
|
scope->base.vpi_type = &vpip_scope_fork_rt;
|
||||||
scope->is_automatic = false;
|
} else if (strcmp(base_type,"begin") == 0) {
|
||||||
} else if (strcmp(type,"begin") == 0) {
|
|
||||||
scope->base.vpi_type = &vpip_scope_begin_rt;
|
scope->base.vpi_type = &vpip_scope_begin_rt;
|
||||||
scope->is_automatic = false;
|
} else if (strcmp(base_type,"generate") == 0) {
|
||||||
} else if (strcmp(type,"generate") == 0) {
|
|
||||||
scope->base.vpi_type = &vpip_scope_begin_rt;
|
scope->base.vpi_type = &vpip_scope_begin_rt;
|
||||||
scope->is_automatic = false;
|
|
||||||
} else {
|
} else {
|
||||||
scope->base.vpi_type = &vpip_scope_module_rt;
|
scope->base.vpi_type = &vpip_scope_module_rt;
|
||||||
scope->is_automatic = false;
|
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -396,10 +395,6 @@ compile_scope_decl(char*label, char*type, char*name, const char*tname,
|
||||||
scope->time_units = sp->time_units;
|
scope->time_units = sp->time_units;
|
||||||
scope->time_precision = sp->time_precision;
|
scope->time_precision = sp->time_precision;
|
||||||
|
|
||||||
/* Scopes within automatic scopes are themselves automatic. */
|
|
||||||
if (sp->is_automatic)
|
|
||||||
scope->is_automatic = true;
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
scope->scope = 0x0;
|
scope->scope = 0x0;
|
||||||
|
|
||||||
|
|
@ -476,5 +471,3 @@ unsigned vpip_add_item_to_context(automatic_hooks_s*item,
|
||||||
/* Offset the context index by 2 to leave space for the list links. */
|
/* Offset the context index by 2 to leave space for the list links. */
|
||||||
return 2 + idx;
|
return 2 + idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -528,10 +528,14 @@ static int signal_get(int code, vpiHandle ref)
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case vpiLeftRange: return rfp->msb;
|
case vpiLeftRange:
|
||||||
case vpiRightRange: return rfp->lsb;
|
return rfp->msb;
|
||||||
|
|
||||||
case vpiAutomatic: return rfp->is_automatic;
|
case vpiRightRange:
|
||||||
|
return rfp->lsb;
|
||||||
|
|
||||||
|
case vpiAutomatic:
|
||||||
|
return (int) vpip_scope(rfp)->is_automatic;
|
||||||
|
|
||||||
case _vpiNexusId:
|
case _vpiNexusId:
|
||||||
if (rfp->msb == rfp->lsb)
|
if (rfp->msb == rfp->lsb)
|
||||||
|
|
@ -863,7 +867,6 @@ vpiHandle vpip_make_int(const char*name, int msb, int lsb, vvp_net_t*vec)
|
||||||
struct __vpiSignal*rfp = (struct __vpiSignal*)obj;
|
struct __vpiSignal*rfp = (struct __vpiSignal*)obj;
|
||||||
obj->vpi_type = &vpip_reg_rt;
|
obj->vpi_type = &vpip_reg_rt;
|
||||||
rfp->isint_ = true;
|
rfp->isint_ = true;
|
||||||
rfp->is_automatic = vpip_peek_current_scope()->is_automatic;
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -876,7 +879,6 @@ vpiHandle vpip_make_reg(const char*name, int msb, int lsb,
|
||||||
vpiHandle obj = vpip_make_net(name, msb,lsb, signed_flag, vec);
|
vpiHandle obj = vpip_make_net(name, msb,lsb, signed_flag, vec);
|
||||||
struct __vpiSignal*rfp = (struct __vpiSignal*)obj;
|
struct __vpiSignal*rfp = (struct __vpiSignal*)obj;
|
||||||
obj->vpi_type = &vpip_reg_rt;
|
obj->vpi_type = &vpip_reg_rt;
|
||||||
rfp->is_automatic = vpip_peek_current_scope()->is_automatic;
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -915,7 +917,6 @@ vpiHandle vpip_make_net(const char*name, int msb, int lsb,
|
||||||
obj->signed_flag = signed_flag? 1 : 0;
|
obj->signed_flag = signed_flag? 1 : 0;
|
||||||
obj->isint_ = 0;
|
obj->isint_ = 0;
|
||||||
obj->is_netarray = 0;
|
obj->is_netarray = 0;
|
||||||
obj->is_automatic = vpip_peek_current_scope()->is_automatic;
|
|
||||||
obj->node = node;
|
obj->node = node;
|
||||||
|
|
||||||
// Place this object within a scope. If this object is
|
// Place this object within a scope. If this object is
|
||||||
|
|
@ -972,11 +973,15 @@ static int PV_get(int code, vpiHandle ref)
|
||||||
case vpiConstantSelect:
|
case vpiConstantSelect:
|
||||||
return rfp->twid == 0;
|
return rfp->twid == 0;
|
||||||
|
|
||||||
case vpiLeftRange: rval += rfp->width;
|
case vpiLeftRange:
|
||||||
|
rval += rfp->width;
|
||||||
case vpiRightRange:
|
case vpiRightRange:
|
||||||
rval += vpi_get(vpiRightRange, rfp->parent) + PV_get_base(rfp);
|
rval += vpi_get(vpiRightRange, rfp->parent) + PV_get_base(rfp);
|
||||||
return rval;
|
return rval;
|
||||||
|
|
||||||
|
case vpiAutomatic:
|
||||||
|
return vpi_get(vpiAutomatic, rfp->parent);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "PV_get: property %d is unknown\n", code);
|
fprintf(stderr, "PV_get: property %d is unknown\n", code);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -93,6 +93,9 @@ static int timevar_time_get(int code, vpiHandle ref)
|
||||||
case vpiFuncType:
|
case vpiFuncType:
|
||||||
return vpiTimeFunc;
|
return vpiTimeFunc;
|
||||||
|
|
||||||
|
case vpiAutomatic:
|
||||||
|
return 0;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "Code: %d\n", code);
|
fprintf(stderr, "Code: %d\n", code);
|
||||||
assert(0);
|
assert(0);
|
||||||
|
|
@ -148,6 +151,9 @@ static int timevar_realtime_get(int code, vpiHandle ref)
|
||||||
case vpiFuncType:
|
case vpiFuncType:
|
||||||
return vpiRealFunc;
|
return vpiRealFunc;
|
||||||
|
|
||||||
|
case vpiAutomatic:
|
||||||
|
return 0;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "Code: %d\n", code);
|
fprintf(stderr, "Code: %d\n", code);
|
||||||
assert(0);
|
assert(0);
|
||||||
|
|
|
||||||
|
|
@ -2752,6 +2752,20 @@ bool of_JOIN(vthread_t thr, vvp_code_t cp)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* %load/ar <bit>, <array-label>, <index>;
|
||||||
|
*/
|
||||||
|
bool of_LOAD_AR(vthread_t thr, vvp_code_t cp)
|
||||||
|
{
|
||||||
|
unsigned bit = cp->bit_idx[0];
|
||||||
|
unsigned idx = cp->bit_idx[1];
|
||||||
|
unsigned adr = thr->words[idx].w_int;
|
||||||
|
|
||||||
|
double word = array_get_word_r(cp->array, adr);
|
||||||
|
thr->words[bit].w_real = word;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* %load/av <bit>, <array-label>, <wid> ;
|
* %load/av <bit>, <array-label>, <wid> ;
|
||||||
*
|
*
|
||||||
|
|
@ -3071,7 +3085,7 @@ bool of_LOADI_WR(vthread_t thr, vvp_code_t cp)
|
||||||
static void do_verylong_mod(vthread_t thr, vvp_code_t cp,
|
static void do_verylong_mod(vthread_t thr, vvp_code_t cp,
|
||||||
bool left_is_neg, bool right_is_neg)
|
bool left_is_neg, bool right_is_neg)
|
||||||
{
|
{
|
||||||
bool out_is_neg = left_is_neg != right_is_neg;
|
bool out_is_neg = left_is_neg;
|
||||||
int len=cp->number;
|
int len=cp->number;
|
||||||
unsigned char *a, *z, *t;
|
unsigned char *a, *z, *t;
|
||||||
a = new unsigned char[len+1];
|
a = new unsigned char[len+1];
|
||||||
|
|
@ -3936,6 +3950,24 @@ bool of_RELEASE_WR(vthread_t thr, vvp_code_t cp)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* %set/av <label>, <index>, <bit>
|
||||||
|
*
|
||||||
|
* Write the real value in register <bit> to the array indexed by the
|
||||||
|
* integer value addressed bin index register <index>.
|
||||||
|
*/
|
||||||
|
bool of_SET_AR(vthread_t thr, vvp_code_t cp)
|
||||||
|
{
|
||||||
|
unsigned idx = cp->bit_idx[0];
|
||||||
|
unsigned bit = cp->bit_idx[1];
|
||||||
|
unsigned adr = thr->words[idx].w_int;
|
||||||
|
|
||||||
|
double value = thr->words[bit].w_real;
|
||||||
|
array_set_word(cp->array, adr, value);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This implements the "%set/av <label>, <bit>, <wid>" instruction. In
|
* This implements the "%set/av <label>, <bit>, <wid>" instruction. In
|
||||||
* this case, the <label> is an array label, and the <bit> and <wid>
|
* this case, the <label> is an array label, and the <bit> and <wid>
|
||||||
|
|
|
||||||
|
|
@ -1299,6 +1299,32 @@ bool vector4_to_value(const vvp_vector4_t&vec, double&val, bool signed_flag)
|
||||||
return flag;
|
return flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vvp_realarray_t::vvp_realarray_t(unsigned wor)
|
||||||
|
: words_(wor)
|
||||||
|
{
|
||||||
|
array_ = new double[words_];
|
||||||
|
}
|
||||||
|
|
||||||
|
vvp_realarray_t::~vvp_realarray_t()
|
||||||
|
{
|
||||||
|
delete[]array_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vvp_realarray_t::set_word(unsigned word, double value)
|
||||||
|
{
|
||||||
|
if (word >= words_)
|
||||||
|
return;
|
||||||
|
array_[word] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
double vvp_realarray_t::get_word(unsigned word) const
|
||||||
|
{
|
||||||
|
if (word >= words_)
|
||||||
|
return 0.0;
|
||||||
|
else
|
||||||
|
return array_[word];
|
||||||
|
}
|
||||||
|
|
||||||
vvp_vector4array_t::vvp_vector4array_t(unsigned width__, unsigned words__)
|
vvp_vector4array_t::vvp_vector4array_t(unsigned width__, unsigned words__)
|
||||||
: width_(width__), words_(words__)
|
: width_(width__), words_(words__)
|
||||||
{
|
{
|
||||||
|
|
@ -1994,6 +2020,21 @@ static void div_mod (vvp_vector2_t dividend, vvp_vector2_t divisor,
|
||||||
remainder = vvp_vector2_t(dividend, mask.size());
|
remainder = vvp_vector2_t(dividend, mask.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vvp_vector2_t operator - (const vvp_vector2_t&that)
|
||||||
|
{
|
||||||
|
vvp_vector2_t neg(that);
|
||||||
|
if (neg.wid_ == 0) return neg;
|
||||||
|
|
||||||
|
const unsigned words = (neg.wid_ + neg.BITS_PER_WORD-1) /
|
||||||
|
neg.BITS_PER_WORD;
|
||||||
|
for (unsigned idx = 0 ; idx < words ; idx += 1) {
|
||||||
|
neg.vec_[idx] = ~neg.vec_[idx];
|
||||||
|
}
|
||||||
|
neg += vvp_vector2_t(1, neg.wid_);
|
||||||
|
|
||||||
|
return neg;
|
||||||
|
}
|
||||||
|
|
||||||
vvp_vector2_t operator / (const vvp_vector2_t÷nd,
|
vvp_vector2_t operator / (const vvp_vector2_t÷nd,
|
||||||
const vvp_vector2_t&divisor)
|
const vvp_vector2_t&divisor)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -467,6 +467,26 @@ extern bool vector4_to_value(const vvp_vector4_t&a, vvp_time64_t&val);
|
||||||
#endif
|
#endif
|
||||||
extern bool vector4_to_value(const vvp_vector4_t&a, double&val, bool is_signed);
|
extern bool vector4_to_value(const vvp_vector4_t&a, double&val, bool is_signed);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The __vpiArray handle uses instances of this to keep an array of
|
||||||
|
* real valued variables.
|
||||||
|
*/
|
||||||
|
class vvp_realarray_t {
|
||||||
|
|
||||||
|
public:
|
||||||
|
vvp_realarray_t(unsigned words);
|
||||||
|
~vvp_realarray_t();
|
||||||
|
|
||||||
|
unsigned words() const { return words_; }
|
||||||
|
|
||||||
|
double get_word(unsigned idx) const;
|
||||||
|
void set_word(unsigned idx, double val);
|
||||||
|
|
||||||
|
private:
|
||||||
|
unsigned words_;
|
||||||
|
double*array_;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* vvp_vector4array_t
|
* vvp_vector4array_t
|
||||||
*/
|
*/
|
||||||
|
|
@ -544,6 +564,7 @@ class vvp_vector4array_aa : public vvp_vector4array_t, public automatic_hooks_s
|
||||||
*/
|
*/
|
||||||
class vvp_vector2_t {
|
class vvp_vector2_t {
|
||||||
|
|
||||||
|
friend vvp_vector2_t operator - (const vvp_vector2_t&);
|
||||||
friend vvp_vector2_t operator + (const vvp_vector2_t&,
|
friend vvp_vector2_t operator + (const vvp_vector2_t&,
|
||||||
const vvp_vector2_t&);
|
const vvp_vector2_t&);
|
||||||
friend vvp_vector2_t operator * (const vvp_vector2_t&,
|
friend vvp_vector2_t operator * (const vvp_vector2_t&,
|
||||||
|
|
@ -599,6 +620,7 @@ extern bool operator >= (const vvp_vector2_t&, const vvp_vector2_t&);
|
||||||
extern bool operator < (const vvp_vector2_t&, const vvp_vector2_t&);
|
extern bool operator < (const vvp_vector2_t&, const vvp_vector2_t&);
|
||||||
extern bool operator <= (const vvp_vector2_t&, const vvp_vector2_t&);
|
extern bool operator <= (const vvp_vector2_t&, const vvp_vector2_t&);
|
||||||
extern bool operator == (const vvp_vector2_t&, const vvp_vector2_t&);
|
extern bool operator == (const vvp_vector2_t&, const vvp_vector2_t&);
|
||||||
|
extern vvp_vector2_t operator - (const vvp_vector2_t&);
|
||||||
extern vvp_vector2_t operator + (const vvp_vector2_t&, const vvp_vector2_t&);
|
extern vvp_vector2_t operator + (const vvp_vector2_t&, const vvp_vector2_t&);
|
||||||
extern vvp_vector2_t operator * (const vvp_vector2_t&, const vvp_vector2_t&);
|
extern vvp_vector2_t operator * (const vvp_vector2_t&, const vvp_vector2_t&);
|
||||||
extern vvp_vector2_t operator / (const vvp_vector2_t&, const vvp_vector2_t&);
|
extern vvp_vector2_t operator / (const vvp_vector2_t&, const vvp_vector2_t&);
|
||||||
|
|
|
||||||
|
|
@ -270,6 +270,8 @@ void compile_netw_real(char*label, char*array_label, unsigned long array_addr,
|
||||||
int msb, int lsb,
|
int msb, int lsb,
|
||||||
unsigned argc, struct symb_s*argv)
|
unsigned argc, struct symb_s*argv)
|
||||||
{
|
{
|
||||||
|
cerr << "XXXX compile_netw_real: label=" << label
|
||||||
|
<< ", array_label=" << array_label << endl;
|
||||||
__compile_real(label, 0, array_label, array_addr,
|
__compile_real(label, 0, array_label, array_addr,
|
||||||
msb, lsb, false, argc, argv);
|
msb, lsb, false, argc, argv);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue