Basic infrastructure for compile-time function evaluation.
This commit is contained in:
parent
d10e4bca4c
commit
def9d0ea1d
|
|
@ -108,7 +108,8 @@ O = main.o async.o design_dump.o discipline.o dup_expr.o elaborate.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 nettypes.o net_analog.o net_assign.o \
|
load_module.o netlist.o netmisc.o nettypes.o net_analog.o net_assign.o \
|
||||||
net_design.o \
|
net_design.o \
|
||||||
netenum.o netstruct.o net_event.o net_expr.o net_func.o net_link.o net_modulo.o \
|
netenum.o netstruct.o net_event.o net_expr.o net_func.o net_func_eval.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_nex_input.o net_nex_output.o net_proc.o net_scope.o net_tran.o \
|
||||||
net_udp.o pad_to_width.o parse.o parse_misc.o pform.o pform_analog.o \
|
net_udp.o pad_to_width.o parse.o parse_misc.o pform.o pform_analog.o \
|
||||||
pform_disciplines.o pform_dump.o pform_pclass.o pform_struct_type.o \
|
pform_disciplines.o pform_dump.o pform_pclass.o pform_struct_type.o \
|
||||||
|
|
|
||||||
|
|
@ -1963,8 +1963,12 @@ NetExpr* NetEUFunc::eval_tree()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (need_const_) {
|
if (need_const_) {
|
||||||
cerr << get_fileline() << ": sorry: Constant user functions are "
|
NetFuncDef*def = func_->func_def();
|
||||||
"not yet supported." << endl;
|
ivl_assert(*this, def);
|
||||||
|
|
||||||
|
NetExpr*res = def->evaluate_function(*this, parms_);
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,133 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2012 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 "netlist.h"
|
||||||
|
# include <typeinfo>
|
||||||
|
# include "ivl_assert.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
NetExpr* NetFuncDef::evaluate_function(const LineInfo&loc, const std::vector<NetExpr*>&args) const
|
||||||
|
{
|
||||||
|
// Make the context map;
|
||||||
|
map<perm_string,NetExpr*>::iterator ptr;
|
||||||
|
map<perm_string,NetExpr*>context_map;
|
||||||
|
|
||||||
|
// Put the return value into the map...
|
||||||
|
context_map[scope_->basename()] = 0;
|
||||||
|
// Load the input ports into the map...
|
||||||
|
ivl_assert(loc, ports_.size() == args.size());
|
||||||
|
for (size_t idx = 0 ; idx < ports_.size() ; idx += 1) {
|
||||||
|
NetExpr*tmp = args[idx]->dup_expr();
|
||||||
|
perm_string aname = ports_[idx]->name();
|
||||||
|
context_map[aname] = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform the evaluation
|
||||||
|
bool flag = statement_->evaluate_function(loc, context_map);
|
||||||
|
|
||||||
|
// Extract the result...
|
||||||
|
ptr = context_map.find(scope_->basename());
|
||||||
|
NetExpr*res = ptr->second;
|
||||||
|
context_map.erase(ptr);
|
||||||
|
|
||||||
|
|
||||||
|
// Cleanup the rest of the context.
|
||||||
|
for (ptr = context_map.begin() ; ptr != context_map.end() ; ++ptr) {
|
||||||
|
delete ptr->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Done.
|
||||||
|
if (flag)
|
||||||
|
return res;
|
||||||
|
|
||||||
|
delete res;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
NetExpr* NetExpr::evaluate_function(const LineInfo&,
|
||||||
|
map<perm_string,NetExpr*>&) const
|
||||||
|
{
|
||||||
|
cerr << get_fileline() << ": sorry: I don't know how to evaluate this expression at compile time." << endl;
|
||||||
|
cerr << get_fileline() << ": : Expression type:" << typeid(*this).name() << endl;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NetProc::evaluate_function(const LineInfo&,
|
||||||
|
map<perm_string,NetExpr*>&) const
|
||||||
|
{
|
||||||
|
cerr << get_fileline() << ": sorry: I don't know how to evaluate this statement at compile time." << endl;
|
||||||
|
cerr << get_fileline() << ": : Statement type:" << typeid(*this).name() << endl;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NetAssign::evaluate_function(const LineInfo&loc,
|
||||||
|
map<perm_string,NetExpr*>&context_map) const
|
||||||
|
{
|
||||||
|
if (l_val_count() != 1) {
|
||||||
|
cerr << get_fileline() << ": sorry: I don't know how to evaluate "
|
||||||
|
"concatenated l-values here." << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const NetAssign_*lval = l_val(0);
|
||||||
|
|
||||||
|
ivl_assert(loc, lval->word() == 0);
|
||||||
|
ivl_assert(loc, lval->get_base() == 0);
|
||||||
|
|
||||||
|
NetExpr*rval_result = rval()->evaluate_function(loc, context_map);
|
||||||
|
if (rval_result == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
map<perm_string,NetExpr*>::iterator ptr = context_map.find(lval->name());
|
||||||
|
if (ptr->second)
|
||||||
|
delete ptr->second;
|
||||||
|
ptr->second = rval_result;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Evaluating a NetBlock in a function is a simple matter of
|
||||||
|
* evaluating the statements in order.
|
||||||
|
*/
|
||||||
|
bool NetBlock::evaluate_function(const LineInfo&loc,
|
||||||
|
map<perm_string,NetExpr*>&context_map) const
|
||||||
|
{
|
||||||
|
bool flag = true;
|
||||||
|
NetProc*cur = last_;
|
||||||
|
do {
|
||||||
|
cur = cur->next_;
|
||||||
|
bool cur_flag = cur->evaluate_function(loc, context_map);
|
||||||
|
flag = flag && cur_flag;
|
||||||
|
} while (cur != last_);
|
||||||
|
|
||||||
|
return flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NetExpr* NetEConst::evaluate_function(const LineInfo&,
|
||||||
|
map<perm_string,NetExpr*>&) const
|
||||||
|
{
|
||||||
|
NetEConst*res = new NetEConst(value_);
|
||||||
|
res->set_line(*this);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
30
netlist.h
30
netlist.h
|
|
@ -28,6 +28,7 @@
|
||||||
# include <string>
|
# include <string>
|
||||||
# include <map>
|
# include <map>
|
||||||
# include <list>
|
# include <list>
|
||||||
|
# include <memory>
|
||||||
# include <vector>
|
# include <vector>
|
||||||
# include <set>
|
# include <set>
|
||||||
# include <utility>
|
# include <utility>
|
||||||
|
|
@ -1715,6 +1716,14 @@ class NetExpr : public LineInfo {
|
||||||
// any. This is a deep copy operation.
|
// any. This is a deep copy operation.
|
||||||
virtual NetExpr*dup_expr() const =0;
|
virtual NetExpr*dup_expr() const =0;
|
||||||
|
|
||||||
|
// Evaluate the expression at compile time, a la within a
|
||||||
|
// constant function. This is used by the constant function
|
||||||
|
// evaluation function code, and the return value is an
|
||||||
|
// allocated constant, or nil if the expression cannot be
|
||||||
|
// evaluated for any reason.
|
||||||
|
virtual NetExpr*evaluate_function(const LineInfo&loc,
|
||||||
|
std::map<perm_string,NetExpr*>&ctx) const;
|
||||||
|
|
||||||
// Get the Nexus that are the input to this
|
// Get the Nexus that are the input to this
|
||||||
// expression. Normally this descends down to the reference to
|
// expression. Normally this descends down to the reference to
|
||||||
// a signal that reads from its input.
|
// a signal that reads from its input.
|
||||||
|
|
@ -1776,6 +1785,9 @@ class NetEConst : public NetExpr {
|
||||||
virtual NetNet*synthesize(Design*, NetScope*scope, NetExpr*);
|
virtual NetNet*synthesize(Design*, NetScope*scope, NetExpr*);
|
||||||
virtual NexusSet* nex_input(bool rem_out = true);
|
virtual NexusSet* nex_input(bool rem_out = true);
|
||||||
|
|
||||||
|
virtual NetExpr*evaluate_function(const LineInfo&loc,
|
||||||
|
std::map<perm_string,NetExpr*>&ctx) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
verinum value_;
|
verinum value_;
|
||||||
};
|
};
|
||||||
|
|
@ -2244,6 +2256,15 @@ class NetProc : public virtual LineInfo {
|
||||||
// target. The target returns true if OK, false for errors.
|
// target. The target returns true if OK, false for errors.
|
||||||
virtual bool emit_proc(struct target_t*) const;
|
virtual bool emit_proc(struct target_t*) const;
|
||||||
|
|
||||||
|
// This method is used by the NetFuncDef object to evaluate a
|
||||||
|
// constant function at compile time. The loc is the location
|
||||||
|
// of the function call, and is used for error messages. The
|
||||||
|
// ctx is a map of name to expression. This is for mapping
|
||||||
|
// identifiers to values. The function returns true if the
|
||||||
|
// processing succeeds, or false otherwise.
|
||||||
|
virtual bool evaluate_function(const LineInfo&loc,
|
||||||
|
std::map<perm_string,NetExpr*>&ctx) const;
|
||||||
|
|
||||||
// This method is called by functors that want to scan a
|
// This method is called by functors that want to scan a
|
||||||
// process in search of matchable patterns.
|
// process in search of matchable patterns.
|
||||||
virtual int match_proc(struct proc_match_t*);
|
virtual int match_proc(struct proc_match_t*);
|
||||||
|
|
@ -2446,6 +2467,7 @@ class NetAssign : public NetAssignBase {
|
||||||
virtual bool emit_proc(struct target_t*) const;
|
virtual bool emit_proc(struct target_t*) const;
|
||||||
virtual int match_proc(struct proc_match_t*);
|
virtual int match_proc(struct proc_match_t*);
|
||||||
virtual void dump(ostream&, unsigned ind) const;
|
virtual void dump(ostream&, unsigned ind) const;
|
||||||
|
virtual bool evaluate_function(const LineInfo&loc, std::map<perm_string,NetExpr*>&context_map) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
char op_;
|
char op_;
|
||||||
|
|
@ -2495,6 +2517,8 @@ class NetBlock : public NetProc {
|
||||||
const NetProc*proc_first() const;
|
const NetProc*proc_first() const;
|
||||||
const NetProc*proc_next(const NetProc*cur) const;
|
const NetProc*proc_next(const NetProc*cur) const;
|
||||||
|
|
||||||
|
bool evaluate_function(const LineInfo&loc,
|
||||||
|
std::map<perm_string,NetExpr*>&ctx) const;
|
||||||
|
|
||||||
// synthesize as asynchronous logic, and return true.
|
// synthesize as asynchronous logic, and return true.
|
||||||
bool synth_async(Design*des, NetScope*scope,
|
bool synth_async(Design*des, NetScope*scope,
|
||||||
|
|
@ -2996,6 +3020,12 @@ class NetFuncDef {
|
||||||
|
|
||||||
const NetNet*return_sig() const;
|
const NetNet*return_sig() const;
|
||||||
|
|
||||||
|
// When we want to evaluate the function during compile time,
|
||||||
|
// use this method to pass in the argument and get out a
|
||||||
|
// result. The result should be a constant. If the function
|
||||||
|
// cannot evaluate to a constant, this returns nil.
|
||||||
|
NetExpr* evaluate_function(const LineInfo&loc, const std::vector<NetExpr*>&args) const;
|
||||||
|
|
||||||
void dump(ostream&, unsigned ind) const;
|
void dump(ostream&, unsigned ind) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue