Merge branch 'v10-branch' of github.com:steveicarus/iverilog into v10-branch

This commit is contained in:
Stephen Williams 2018-07-24 09:37:50 -07:00
commit c831ce0aae
47 changed files with 570 additions and 325 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2011 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2017 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
@ -26,11 +26,6 @@
# include "verinum.h"
# include "netmisc.h"
bool dly_used_no_timescale = false;
bool dly_used_timescale = false;
bool display_ts_dly_warning = true;
PDelays::PDelays()
{
delete_flag_ = true;
@ -80,19 +75,7 @@ static NetExpr*calculate_val(Design*des, NetScope*scope, PExpr*expr)
{
NetExpr*dex = elab_and_eval(des, scope, expr, -1);
/* Print a warning if we find default and `timescale based
* delays in the design, since this is likely an error. */
if (scope->time_from_timescale()) dly_used_timescale = true;
else dly_used_no_timescale = true;
if (display_ts_dly_warning &&
dly_used_no_timescale && dly_used_timescale) {
cerr << "warning: Found both default and "
"`timescale based delays. Use" << endl;
cerr << " -Wtimescale to find the "
"module(s) with no `timescale." << endl;
display_ts_dly_warning = false;
}
check_for_inconsistent_delays(scope);
/* If the delay expression is a real constant or vector
constant, then evaluate it, scale it to the local time

View File

@ -4,7 +4,7 @@
%{
/*
* Copyright (c) 2001-2016 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2017 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
@ -252,7 +252,7 @@ void destroy_lexor(void)
{
# 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
# if YY_FLEX_MINOR_VERSION > 5 || defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9
yylex_destroy();
# endif
# endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2016 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2018 Stephen Williams (steve@icarus.com)
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
@ -1446,6 +1446,13 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope,
return 0;
}
if (!type_is_vectorable(expr_type_)) {
cerr << get_fileline() << ": error: The argument to "
<< name << " must be a vector type." << endl;
des->errors += 1;
return 0;
}
if (debug_elaborate) {
cerr << get_fileline() << ": PECallFunction::elaborate_sfunc_: "
<< name << " expression is the argument cast to expr_wid=" << expr_wid << endl;
@ -3440,29 +3447,41 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
}
if (net == 0) {
cerr << get_fileline() << ": internal error: "
<< "Expecting idents with ntype to be signals." << endl;
cerr << get_fileline() << ": error: Unable to bind variable `"
<< path_ << "' in `" << scope_path(use_scope) << "'" << endl;
des->errors += 1;
return 0;
}
if (! ntype->type_compatible(net->net_type())) {
cerr << get_fileline() << ": internal_error: "
<< "net type doesn't match context type." << endl;
if (const netdarray_t*array_type = dynamic_cast<const netdarray_t*> (ntype)) {
if (array_type->type_compatible(net->net_type())) {
NetESignal*tmp = new NetESignal(net);
tmp->set_line(*this);
return tmp;
}
cerr << get_fileline() << ": : "
<< "net type=";
// Icarus allows a dynamic array to be initialised with a
// single elementary value, so try that next.
ntype = array_type->element_type();
}
if (! ntype->type_compatible(net->net_type())) {
cerr << get_fileline() << ": error: the type of the variable '"
<< path_ << "' doesn't match the context type." << endl;
cerr << get_fileline() << ": : " << "variable type=";
if (net->net_type())
net->net_type()->debug_dump(cerr);
else
cerr << "<nil>";
cerr << endl;
cerr << get_fileline() << ": : "
<< "context type=";
cerr << get_fileline() << ": : " << "context type=";
ivl_assert(*this, ntype);
ntype->debug_dump(cerr);
cerr << endl;
des->errors += 1;
return 0;
}
ivl_assert(*this, ntype->type_compatible(net->net_type()));
@ -5318,9 +5337,8 @@ NetExpr* PENewArray::elaborate_expr(Design*des, NetScope*scope,
// expression. Elaborate the expression as an element
// type. The run-time will assign this value to each element.
const netarray_t*array_type = dynamic_cast<const netarray_t*> (ntype);
ivl_type_t elem_type = array_type->element_type();
init_val = init_->elaborate_expr(des, scope, elem_type, flags);
init_val = init_->elaborate_expr(des, scope, array_type, flags);
}
NetENew*tmp = new NetENew(ntype, size, init_val);
@ -5571,6 +5589,10 @@ unsigned PENumber::test_width(Design*, NetScope*, width_mode_t&mode)
NetExpr* PENumber::elaborate_expr(Design*des, NetScope*, ivl_type_t ntype, unsigned) const
{
// Icarus allows dynamic arrays to be initialised with a single value.
if (const netdarray_t*array_type = dynamic_cast<const netdarray_t*> (ntype))
ntype = array_type->element_type();
const netvector_t*use_type = dynamic_cast<const netvector_t*> (ntype);
if (use_type == 0) {
cerr << get_fileline() << ": internal error: "

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2016 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2017 Stephen Williams (steve@icarus.com)
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
@ -509,8 +509,10 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass)
netclass_t*use_base_class = 0;
if (base_class) {
ivl_assert(*pclass, scope);
use_base_class = scope->find_class(base_class->name);
if (scope)
use_base_class = scope->find_class(base_class->name);
if (use_base_class == 0)
use_base_class = des->find_class(base_class->name);
if (use_base_class == 0) {
cerr << pclass->get_fileline() << ": error: "
<< "Base class " << base_class->name
@ -605,13 +607,9 @@ static void elaborate_scope_classes(Design*des, NetScope*scope,
void elaborate_rootscope_classes(Design*des)
{
if (pform_classes.empty())
return;
for (map<perm_string,PClass*>::iterator cur = pform_classes.begin()
; cur != pform_classes.end() ; ++ cur) {
blend_class_constructors(cur->second);
elaborate_scope_class(des, 0, cur->second);
for (size_t idx = 0 ; idx < pform_classes.size() ; idx += 1) {
blend_class_constructors(pform_classes[idx]);
elaborate_scope_class(des, 0, pform_classes[idx]);
}
}

View File

@ -2374,19 +2374,7 @@ static NetExpr*elaborate_delay_expr(PExpr*expr, Design*des, NetScope*scope)
{
NetExpr*dex = elab_and_eval(des, scope, expr, -1);
/* Print a warning if we find default and `timescale based
* delays in the design, since this is likely an error. */
if (scope->time_from_timescale()) dly_used_timescale = true;
else dly_used_no_timescale = true;
if (display_ts_dly_warning &&
dly_used_no_timescale && dly_used_timescale) {
cerr << "warning: Found both default and "
"`timescale based delays. Use" << endl;
cerr << " -Wtimescale to find the "
"module(s) with no `timescale." << endl;
display_ts_dly_warning = false;
}
check_for_inconsistent_delays(scope);
/* If the delay expression is a real constant or vector
constant, then evaluate it, scale it to the local time
@ -5434,19 +5422,7 @@ void PSpecPath::elaborate(Design*des, NetScope*scope) const
ndelays = delays.size();
if (ndelays > 12) ndelays = 12;
/* Print a warning if we find default and `timescale based
* delays in the design, since this is likely an error. */
if (scope->time_from_timescale()) dly_used_timescale = true;
else dly_used_no_timescale = true;
if (display_ts_dly_warning &&
dly_used_no_timescale && dly_used_timescale) {
cerr << "warning: Found both default and "
"`timescale based delays. Use" << endl;
cerr << " -Wtimescale to find the "
"module(s) with no `timescale." << endl;
display_ts_dly_warning = false;
}
check_for_inconsistent_delays(scope);
/* Elaborate the delay values themselves. Remember to scale
them for the timescale/precision of the scope. */

View File

@ -2100,7 +2100,7 @@ void destroy_lexor(void)
{
# 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
# if YY_FLEX_MINOR_VERSION > 5 || defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9
yylex_destroy();
# endif
# endif

View File

@ -1606,7 +1606,7 @@ 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
# if YY_FLEX_MINOR_VERSION > 5 || defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9
yylex_destroy();
# endif
# endif

View File

@ -32,8 +32,8 @@ static unsigned string_pool_count = 0;
StringHeap::StringHeap()
{
cell_base_ = 0;
cell_ptr_ = HEAPCELL;
cell_count_ = 0;
cell_size_ = 0;
cell_ptr_ = 0;
}
StringHeap::~StringHeap()
@ -45,20 +45,24 @@ StringHeap::~StringHeap()
const char* StringHeap::add(const char*text)
{
unsigned len = strlen(text);
assert((len+1) <= HEAPCELL);
unsigned rem = HEAPCELL - cell_ptr_;
unsigned rem = cell_size_ - cell_ptr_;
if (rem < (len+1)) {
cell_base_ = (char*)malloc(HEAPCELL);
// release any unused memory
if (rem > 0) {
cell_base_ = (char*)realloc(cell_base_, cell_ptr_);
assert(cell_base_ != 0);
}
// start new cell
cell_size_ = (len+1) > DEFAULT_CELL_SIZE ? len+1 : DEFAULT_CELL_SIZE;
cell_base_ = (char*)malloc(cell_size_);
cell_ptr_ = 0;
assert(cell_base_ != 0);
#ifdef CHECK_WITH_VALGRIND
string_pool_count += 1;
string_pool = (char **) realloc(string_pool,
string_pool_count*sizeof(char **));
string_pool[string_pool_count-1] = cell_base_;
#endif
cell_ptr_ = 0;
cell_count_ += 1;
assert(cell_base_ != 0);
}
char*res = cell_base_ + cell_ptr_;
@ -66,7 +70,7 @@ const char* StringHeap::add(const char*text)
cell_ptr_ += len;
cell_base_[cell_ptr_++] = 0;
assert(cell_ptr_ <= HEAPCELL);
assert(cell_ptr_ <= cell_size_);
return res;
}

View File

@ -78,11 +78,11 @@ class StringHeap {
perm_string make(const char*);
private:
enum { HEAPCELL = 0x10000 };
static const unsigned DEFAULT_CELL_SIZE = 0x10000;
char*cell_base_;
unsigned cell_size_;
unsigned cell_ptr_;
unsigned cell_count_;
private: // not implemented
StringHeap(const StringHeap&);

View File

@ -1,5 +1,5 @@
const char COPYRIGHT[] =
"Copyright (c) 1998-2015 Stephen Williams (steve@icarus.com)";
"Copyright (c) 1998-2017 Stephen Williams (steve@icarus.com)";
/*
* This source code is free software; you can redistribute it
@ -1037,9 +1037,8 @@ int main(int argc, char*argv[])
pform_dump(out, cur->second);
}
out << "PFORM DUMP $ROOT CLASSES:" << endl;
for (map<perm_string,PClass*>::iterator cur = pform_classes.begin()
; cur != pform_classes.end() ; ++ cur) {
pform_dump(out, cur->second);
for (size_t idx = 0 ; idx < pform_classes.size() ; idx += 1) {
pform_dump(out, pform_classes[idx]);
}
out << "PFORM DUMP PACKAGES:" << endl;
for (map<perm_string,PPackage*>::iterator pac = pform_packages.begin()

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 2012-2017 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
@ -165,7 +165,8 @@ bool netclass_t::test_for_missing_initializers() const
NetScope*netclass_t::method_from_name(perm_string name) const
{
NetScope*task = class_scope_->child( hname_t(name) );
if (task == 0) return 0;
if ((task == 0) && super_)
task = super_->method_from_name(name);
return task;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2015 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2017 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
@ -2724,12 +2724,27 @@ DelayType NetProc::delay_type() const
DelayType NetBlock::delay_type() const
{
DelayType result = NO_DELAY;
// A join_none has no delay.
if (type() == PARA_JOIN_NONE) return NO_DELAY;
for (const NetProc*cur = proc_first(); cur; cur = proc_next(cur)) {
DelayType dt = cur->delay_type();
if (dt > result) result = dt;
if (dt == DEFINITE_DELAY) break;
DelayType result;
// A join_any has the minimum delay.
if (type() == PARA_JOIN_ANY) {
result = DEFINITE_DELAY;
for (const NetProc*cur = proc_first(); cur; cur = proc_next(cur)) {
DelayType dt = cur->delay_type();
if (dt < result) result = dt;
if (dt == NO_DELAY) break;
}
// A begin or join has the maximum delay.
} else {
result = NO_DELAY;
for (const NetProc*cur = proc_first(); cur; cur = proc_next(cur)) {
DelayType dt = cur->delay_type();
if (dt > result) result = dt;
if (dt == DEFINITE_DELAY) break;
}
}
return result;
@ -2800,9 +2815,10 @@ DelayType NetPDelay::delay_type() const
return DEFINITE_DELAY;
} else {
if (statement_) {
return statement_->delay_type();
return combine_delays(ZERO_DELAY,
statement_->delay_type());
} else {
return NO_DELAY;
return ZERO_DELAY;
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2016 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2017 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
@ -1665,3 +1665,38 @@ NetScope* find_method_containing_scope(const LineInfo&, NetScope*scope)
return scope;
}
/*
* Print a warning if we find a mixture of default and explicit timescale
* based delays in the design, since this is likely an error.
*/
void check_for_inconsistent_delays(NetScope*scope)
{
static bool used_implicit_timescale = false;
static bool used_explicit_timescale = false;
static bool display_ts_dly_warning = true;
if (scope->time_from_timescale())
used_explicit_timescale = true;
else
used_implicit_timescale = true;
if (display_ts_dly_warning &&
used_explicit_timescale &&
used_implicit_timescale) {
if (gn_system_verilog()) {
cerr << "warning: Found both default and explicit "
"timescale based delays. Use" << endl;
cerr << " : -Wtimescale to find the design "
"element(s) with no explicit" << endl;
cerr << " : timescale." << endl;
} else {
cerr << "warning: Found both default and "
"`timescale based delays. Use" << endl;
cerr << " : -Wtimescale to find the "
"module(s) with no `timescale." << endl;
}
display_ts_dly_warning = false;
}
}

View File

@ -1,7 +1,7 @@
#ifndef IVL_netmisc_H
#define IVL_netmisc_H
/*
* Copyright (c) 1999-2016 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2017 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
@ -378,10 +378,6 @@ const char *human_readable_op(const char op, bool unary = false);
enum const_bool { C_NON, C_0, C_1, C_X };
const_bool const_logical(const NetExpr*expr);
extern bool dly_used_no_timescale;
extern bool dly_used_timescale;
extern bool display_ts_dly_warning;
/*
* When scaling a real value to a time we need to do some standard
* processing.
@ -409,4 +405,10 @@ extern void assign_unpacked_with_bufz(Design*des, NetScope*scope,
extern NetPartSelect* detect_partselect_lval(Link&pin);
/*
* Print a warning if we find a mixture of default and explicit timescale
* based delays in the design, since this is likely an error.
*/
extern void check_for_inconsistent_delays(NetScope*scope);
#endif /* IVL_netmisc_H */

29
parse.y
View File

@ -598,7 +598,7 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
%type <tf_ports> function_item function_item_list function_item_list_opt
%type <tf_ports> task_item task_item_list task_item_list_opt
%type <tf_ports> tf_port_declaration tf_port_item tf_port_list tf_port_list_opt
%type <tf_ports> tf_port_declaration tf_port_item tf_port_item_list tf_port_list tf_port_list_opt
%type <named_pexpr> modport_simple_port port_name parameter_value_byname
%type <named_pexprs> port_name_list parameter_value_byname_list
@ -2044,7 +2044,10 @@ task_declaration /* IEEE1800-2005: A.2.7 */
| K_task lifetime_opt IDENTIFIER error K_endtask
{
assert(current_task == 0);
if (current_task) {
pform_pop_scope();
current_task = 0;
}
}
endlabel_opt
{ // Last step: check any closing name. This is done late so
@ -2119,10 +2122,16 @@ tf_port_item /* IEEE1800-2005: A.2.7 */
: port_direction_opt data_type_or_implicit IDENTIFIER dimensions_opt tf_port_item_expr_opt
{ vector<pform_tf_port_t>*tmp;
NetNet::PortType use_port_type = $1==NetNet::PIMPLICIT? NetNet::PINPUT : $1;
NetNet::PortType use_port_type = $1;
if ((use_port_type == NetNet::PIMPLICIT) && (gn_system_verilog() || ($2 == 0)))
use_port_type = port_declaration_context.port_type;
perm_string name = lex_strings.make($3);
list<perm_string>* ilist = list_from_identifier($3);
if (use_port_type == NetNet::PIMPLICIT) {
yyerror(@1, "error: missing task/function port direction.");
use_port_type = NetNet::PINPUT; // for error recovery
}
if (($2 == 0) && ($1==NetNet::PIMPLICIT)) {
// Detect special case this is an undecorated
// identifier and we need to get the declaration from
@ -2134,7 +2143,6 @@ tf_port_item /* IEEE1800-2005: A.2.7 */
port_declaration_context.data_type,
ilist);
} else {
// Otherwise, the decorations for this identifier
// indicate the type. Save the type for any right
@ -2181,8 +2189,15 @@ tf_port_item_expr_opt
;
tf_port_list /* IEEE1800-2005: A.2.7 */
: { port_declaration_context.port_type = gn_system_verilog() ? NetNet::PINPUT : NetNet::PIMPLICIT;
port_declaration_context.data_type = 0;
}
tf_port_item_list
{ $$ = $2; }
;
: tf_port_list ',' tf_port_item
tf_port_item_list
: tf_port_item_list ',' tf_port_item
{ vector<pform_tf_port_t>*tmp;
if ($1 && $3) {
size_t s1 = $1->size();
@ -2208,11 +2223,11 @@ tf_port_list /* IEEE1800-2005: A.2.7 */
{ yyerror(@2, "error: Syntax error in task/function port declaration.");
$$ = $3;
}
| tf_port_list ','
| tf_port_item_list ','
{ yyerror(@2, "error: NULL port declarations are not allowed.");
$$ = $1;
}
| tf_port_list ';'
| tf_port_item_list ';'
{ yyerror(@2, "error: ';' is an invalid port declaration separator.");
$$ = $1;
}

View File

@ -1,7 +1,7 @@
#ifndef IVL_parse_api_H
#define IVL_parse_api_H
/*
* Copyright (c) 2001-2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2017 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
@ -45,7 +45,7 @@ extern std::map<perm_string,PUdp*> pform_primitives;
extern std::map<perm_string,data_type_t*> pform_typedefs;
extern std::set<enum_type_t*> pform_enum_sets;
extern std::map<perm_string,PTaskFunc*> pform_tasks;
extern std::map<perm_string,PClass*> pform_classes;
extern std::vector<PClass*> pform_classes;
extern std::map<perm_string,PPackage*> pform_packages;
extern void pform_dump(std::ostream&out, const PClass*pac);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2016 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2017 Stephen Williams (steve@icarus.com)
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
@ -71,7 +71,7 @@ set<enum_type_t*>pform_enum_sets;
/*
* Class definitions in the $root scope go here.
*/
map<perm_string,PClass*> pform_classes;
vector<PClass*> pform_classes;
/*
* Task and function definitions in the $root scope go here.
@ -467,7 +467,7 @@ PClass* pform_push_class_scope(const struct vlltype&loc, perm_string name,
/* If no scope was found then this is being defined in the
* compilation unit scope. */
if (scopex == 0) {
pform_classes[name] = class_scope;
pform_classes.push_back(class_scope);
lexical_scope = class_scope;
return class_scope;
}

View File

@ -281,6 +281,13 @@ ivl_scope_t dll_target::find_scope(ivl_design_s &des, const NetScope*cur)
return scope;
}
for (map<const NetScope*,ivl_scope_t>::iterator idx = des.root_tasks.begin()
; idx != des.root_tasks.end() ; ++ idx) {
ivl_scope_t scope = find_scope_from_root(idx->second, cur);
if (scope)
return scope;
}
return 0;
}

View File

@ -6,7 +6,7 @@
%{
/*
* Copyright (C) 2011-2013 Stephen Williams (steve@icarus.com)
* Copyright (C) 2011-2017 Stephen Williams (steve@icarus.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -79,11 +79,14 @@ void init_fp_lexor(FILE*fd)
yyrestart(fd);
}
/*
* Modern version of flex (>=2.5.9) can clean up the scanner data.
*/
void destroy_fp_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
# if YY_FLEX_MINOR_VERSION > 5 || defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9
yylex_destroy();
# endif
# endif

View File

@ -82,6 +82,7 @@ static int eval_darray_new(ivl_expr_t ex)
unsigned idx;
switch (ivl_type_base(element_type)) {
case IVL_VT_BOOL:
case IVL_VT_LOGIC:
for (idx = 0 ; idx < ivl_expr_parms(init_expr) ; idx += 1) {
draw_eval_vec4(ivl_expr_parm(init_expr,idx));
fprintf(vvp_out, " %%ix/load 3, %u, 0;\n", idx);
@ -110,6 +111,11 @@ static int eval_darray_new(ivl_expr_t ex)
errors += 1;
break;
}
} else if (init_expr && (ivl_expr_value(init_expr) == IVL_VT_DARRAY)) {
ivl_signal_t sig = ivl_expr_signal(init_expr);
fprintf(vvp_out, " %%load/obj v%p_0;\n", sig);
fprintf(vvp_out, " %%scopy;\n");
} else if (init_expr && number_is_immediate(size_expr,32,0)) {
/* In this case, there is an init expression, the
expression is NOT an array_pattern, and the size

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2018 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
@ -22,6 +22,7 @@
# include "verinum.h"
# include <iostream>
# include <cassert>
# include <climits>
# include <cmath> // Needed to get pow for as_double().
# include <cstdio> // Needed to get snprintf for as_string().
# include <algorithm>
@ -1444,7 +1445,8 @@ verinum operator / (const verinum&left, const verinum&right)
if (use_len <= (8*sizeof(long) - 1)) {
long l = left.as_long();
long r = right.as_long();
long v = l / r;
bool overflow = (l == LONG_MIN) && (r == -1);
long v = overflow ? LONG_MIN : l / r;
for (unsigned idx = 0 ; idx < use_len ; idx += 1) {
result.set(idx, (v & 1)? verinum::V1 : verinum::V0);
v >>= 1;
@ -1518,7 +1520,8 @@ verinum operator % (const verinum&left, const verinum&right)
/* Use native signed modulus to do the work. */
long l = left.as_long();
long r = right.as_long();
long v = l % r;
bool overflow = (l == LONG_MIN) && (r == -1);
long v = overflow ? 0 : l % r;
for (unsigned idx = 0 ; idx < use_len ; idx += 1) {
result.set(idx, (v & 1)? verinum::V1 : verinum::V0);
v >>= 1;

View File

@ -6,7 +6,7 @@
%{
/*
* Copyright (c) 2011 Stephen Williams (steve@icarus.com)
* Copyright (c) 2011-2017 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
@ -751,7 +751,16 @@ yyscan_t prepare_lexor(FILE*fd)
return scanner;
}
/*
* Modern version of flex (>=2.5.9) can clean up the scanner data.
*/
void destroy_lexor(yyscan_t scanner)
{
# ifdef FLEX_SCANNER
# if YY_FLEX_MAJOR_VERSION >= 2 && YY_FLEX_MINOR_VERSION >= 5
# if YY_FLEX_MINOR_VERSION > 5 || defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9
yylex_destroy(scanner);
# endif
# endif
# endif
}

View File

@ -1,5 +1,5 @@
/*
* Copyright CERN 2015
* Copyright CERN 2016-2018
* @author Maciej Suminski (maciej.suminski@cern.ch)
*
* This source code is free software; you can redistribute it
@ -120,7 +120,7 @@ void preload_std_funcs(void)
std::list<InterfacePort*>*fn_integer_args = new std::list<InterfacePort*>();
fn_integer_args->push_back(new InterfacePort(&primitive_INTEGER));
fn_integer = new SubprogramBuiltin(perm_string::literal("integer"),
perm_string::literal("$signed"),
perm_string::literal("int'"),
fn_integer_args, &primitive_INTEGER);
std_subprograms[fn_integer->name()] = fn_integer;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2009-2015 Tony Bybell.
* Copyright (c) 2009-2018 Tony Bybell.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@ -128,6 +128,7 @@ void **JenkinsIns(void *base_i, const unsigned char *mem, uint32_t length, uint3
#include <sys/sysctl.h>
#endif
#define FST_APIMESS "FSTAPI | "
/***********************/
/*** ***/
@ -193,7 +194,7 @@ if(nam) /* cppcheck warning fix: nam is always defined, so this is not needed */
dwRetVal = GetTempPath(MAX_PATH, lpTempPathBuffer);
if((dwRetVal > MAX_PATH) || (dwRetVal == 0))
{
fprintf(stderr, "GetTempPath() failed in "__FILE__" line %d, exiting.\n", __LINE__);
fprintf(stderr, FST_APIMESS"GetTempPath() failed in "__FILE__" line %d, exiting.\n", __LINE__);
exit(255);
}
else
@ -201,7 +202,7 @@ if(nam) /* cppcheck warning fix: nam is always defined, so this is not needed */
uRetVal = GetTempFileName(lpTempPathBuffer, TEXT("FSTW"), 0, szTempFileName);
if (uRetVal == 0)
{
fprintf(stderr, "GetTempFileName() failed in "__FILE__" line %d, exiting.\n", __LINE__);
fprintf(stderr, FST_APIMESS"GetTempFileName() failed in "__FILE__" line %d, exiting.\n", __LINE__);
exit(255);
}
else
@ -803,7 +804,7 @@ if(rc<0)
{
xc->fseek_failed = 1;
#ifdef FST_DEBUG
fprintf(stderr, "Seek to #%"PRId64" (whence = %d) failed!\n", offset, whence);
fprintf(stderr, FST_APIMESS"Seek to #%"PRId64" (whence = %d) failed!\n", offset, whence);
perror("Why");
#endif
}
@ -1663,7 +1664,7 @@ if(zerocnt)
/* fpos += */ fstWriterVarint(f, (zerocnt << 1)); /* scan-build */
}
#ifdef FST_DEBUG
fprintf(stderr, "value chains: %d\n", cnt);
fprintf(stderr, FST_APIMESS"value chains: %d\n", cnt);
#endif
xc->vchg_mem[0] = '!';
@ -1738,7 +1739,7 @@ if(xc->dump_size_limit)
xc2->size_limit_locked = 1;
xc2->is_initial_time = 1; /* to trick emit value and emit time change */
#ifdef FST_DEBUG
fprintf(stderr, "<< dump file size limit reached, stopping dumping >>\n");
fprintf(stderr, FST_APIMESS"<< dump file size limit reached, stopping dumping >>\n");
#endif
}
}
@ -2478,7 +2479,7 @@ if(xc)
#ifndef FST_WRITER_PARALLEL
if(xc->parallel_enabled)
{
fprintf(stderr, "ERROR: fstWriterSetParallelMode(), FST_WRITER_PARALLEL not enabled during compile, exiting.\n");
fprintf(stderr, FST_APIMESS"fstWriterSetParallelMode(), FST_WRITER_PARALLEL not enabled during compile, exiting.\n");
exit(255);
}
#endif
@ -2760,7 +2761,7 @@ if((xc) && (handle <= xc->maxhandle))
xc->vchg_mem = realloc(xc->vchg_mem, xc->vchg_alloc_siz);
if(!xc->vchg_mem)
{
fprintf(stderr, "FATAL ERROR, could not realloc() in fstWriterEmitValueChange, exiting.\n");
fprintf(stderr, FST_APIMESS"Could not realloc() in fstWriterEmitValueChange, exiting.\n");
exit(255);
}
}
@ -2874,7 +2875,7 @@ if((xc) && (handle <= xc->maxhandle))
xc->vchg_mem = realloc(xc->vchg_mem, xc->vchg_alloc_siz);
if(!xc->vchg_mem)
{
fprintf(stderr, "FATAL ERROR, could not realloc() in fstWriterEmitVariableLengthValueChange, exiting.\n");
fprintf(stderr, FST_APIMESS"Could not realloc() in fstWriterEmitVariableLengthValueChange, exiting.\n");
exit(255);
}
}
@ -3119,7 +3120,7 @@ if(rc<0)
{
xc->fseek_failed = 1;
#ifdef FST_DEBUG
fprintf(stderr, "Seek to #%"PRId64" (whence = %d) failed!\n", offset, whence);
fprintf(stderr, FST_APIMESS"Seek to #%"PRId64" (whence = %d) failed!\n", offset, whence);
perror("Why");
#endif
}
@ -3748,6 +3749,10 @@ if(!xc->fh)
else /* FST_BL_SKIP */
{
pass_status = 0;
if(xc->fh)
{
fclose(xc->fh); xc->fh = NULL; /* needed in case .hier file is missing and there are no hier sections */
}
}
free(mem);
@ -4435,7 +4440,7 @@ if(gzread_pass_status)
if(rc != Z_OK)
{
printf("geom uncompress rc = %d\n", rc);
fprintf(stderr, FST_APIMESS"fstReaderInit(), geom uncompress rc = %d, exiting.\n", rc);
exit(255);
}
@ -4726,7 +4731,7 @@ for(;;)
if((sectype == EOF) || (sectype == FST_BL_SKIP))
{
#ifdef FST_DEBUG
fprintf(stderr, "<< EOF >>\n");
fprintf(stderr, FST_APIMESS"<< EOF >>\n");
#endif
break;
}
@ -4765,9 +4770,9 @@ for(;;)
mem_required_for_traversal = fstReaderUint64(xc->f);
mem_for_traversal = malloc(mem_required_for_traversal + 66); /* add in potential fastlz overhead */
#ifdef FST_DEBUG
fprintf(stderr, "sec: %u seclen: %d begtim: %d endtim: %d\n",
fprintf(stderr, FST_APIMESS"sec: %u seclen: %d begtim: %d endtim: %d\n",
secnum, (int)seclen, (int)beg_tim, (int)end_tim);
fprintf(stderr, "\tmem_required_for_traversal: %d\n", (int)mem_required_for_traversal);
fprintf(stderr, FST_APIMESS"mem_required_for_traversal: %d\n", (int)mem_required_for_traversal);
#endif
/* process time block */
{
@ -4785,7 +4790,7 @@ for(;;)
tsec_clen = fstReaderUint64(xc->f);
tsec_nitems = fstReaderUint64(xc->f);
#ifdef FST_DEBUG
fprintf(stderr, "\ttime section unc: %d, com: %d (%d items)\n",
fprintf(stderr, FST_APIMESS"time section unc: %d, com: %d (%d items)\n",
(int)tsec_uclen, (int)tsec_clen, (int)tsec_nitems);
#endif
if(tsec_clen > seclen) break; /* corrupted tsec_clen: by definition it can't be larger than size of section */
@ -4805,7 +4810,7 @@ for(;;)
if(rc != Z_OK)
{
printf("tsec uncompress rc = %d\n", rc);
fprintf(stderr, FST_APIMESS"fstReaderIterBlocks2(), tsec uncompress rc = %d, exiting.\n", rc);
exit(255);
}
@ -4881,7 +4886,7 @@ for(;;)
rc = uncompress(mu, &destlen, mc, sourcelen);
if(rc != Z_OK)
{
printf("rc: %d\n", rc);
fprintf(stderr, FST_APIMESS"fstReaderIterBlocks2(), frame uncompress rc: %d, exiting.\n", rc);
exit(255);
}
free(mc);
@ -5044,9 +5049,9 @@ for(;;)
packtype = fgetc(xc->f);
#ifdef FST_DEBUG
fprintf(stderr, "\tframe_uclen: %d, frame_clen: %d, frame_maxhandle: %d\n",
fprintf(stderr, FST_APIMESS"frame_uclen: %d, frame_clen: %d, frame_maxhandle: %d\n",
(int)frame_uclen, (int)frame_clen, (int)frame_maxhandle);
fprintf(stderr, "\tvc_maxhandle: %d, packtype: %c\n", (int)vc_maxhandle, packtype);
fprintf(stderr, FST_APIMESS"vc_maxhandle: %d, packtype: %c\n", (int)vc_maxhandle, packtype);
#endif
indx_pntr = blkpos + seclen - 24 -tsec_clen -8;
@ -5054,7 +5059,7 @@ for(;;)
chain_clen = fstReaderUint64(xc->f);
indx_pos = indx_pntr - chain_clen;
#ifdef FST_DEBUG
fprintf(stderr, "\tindx_pos: %d (%d bytes)\n", (int)indx_pos, (int)chain_clen);
fprintf(stderr, FST_APIMESS"indx_pos: %d (%d bytes)\n", (int)indx_pos, (int)chain_clen);
#endif
chain_cmem = malloc(chain_clen);
if(!chain_cmem) goto block_err;
@ -5173,7 +5178,7 @@ for(;;)
}
#ifdef FST_DEBUG
fprintf(stderr, "\tdecompressed chain idx len: %"PRIu32"\n", idx);
fprintf(stderr, FST_APIMESS"decompressed chain idx len: %"PRIu32"\n", idx);
#endif
mc_mem_len = 16384;
@ -5241,7 +5246,7 @@ for(;;)
if(rc != Z_OK)
{
printf("\tfac: %d clen: %d (rc=%d)\n", (int)i, (int)val, rc);
fprintf(stderr, FST_APIMESS"fstReaderIterBlocks2(), fac: %d clen: %d (rc=%d), exiting.\n", (int)i, (int)val, rc);
exit(255);
}
@ -5793,9 +5798,9 @@ mem_required_for_traversal =
fstReaderUint64(xc->f);
#ifdef FST_DEBUG
fprintf(stderr, "rvat sec: %u seclen: %d begtim: %d endtim: %d\n",
fprintf(stderr, FST_APIMESS"rvat sec: %u seclen: %d begtim: %d endtim: %d\n",
secnum, (int)seclen, (int)beg_tim, (int)end_tim);
fprintf(stderr, "\tmem_required_for_traversal: %d\n", (int)mem_required_for_traversal);
fprintf(stderr, FST_APIMESS"mem_required_for_traversal: %d\n", (int)mem_required_for_traversal);
#endif
/* process time block */
@ -5814,7 +5819,7 @@ tsec_uclen = fstReaderUint64(xc->f);
tsec_clen = fstReaderUint64(xc->f);
tsec_nitems = fstReaderUint64(xc->f);
#ifdef FST_DEBUG
fprintf(stderr, "\ttime section unc: %d, com: %d (%d items)\n",
fprintf(stderr, FST_APIMESS"time section unc: %d, com: %d (%d items)\n",
(int)tsec_uclen, (int)tsec_clen, (int)tsec_nitems);
#endif
ucdata = malloc(tsec_uclen);
@ -5831,7 +5836,7 @@ if(tsec_uclen != tsec_clen)
if(rc != Z_OK)
{
printf("tsec uncompress rc = %d\n", rc);
fprintf(stderr, FST_APIMESS"fstReaderGetValueFromHandleAtTime(), tsec uncompress rc = %d, exiting.\n", rc);
exit(255);
}
@ -5879,7 +5884,7 @@ if(frame_uclen == frame_clen)
rc = uncompress(xc->rvat_frame_data, &destlen, mc, sourcelen);
if(rc != Z_OK)
{
printf("decompress rc: %d\n", rc);
fprintf(stderr, FST_APIMESS"fstReaderGetValueFromHandleAtTime(), frame decompress rc: %d, exiting.\n", rc);
exit(255);
}
free(mc);
@ -5890,9 +5895,9 @@ xc->rvat_vc_start = ftello(xc->f); /* points to '!' character */
xc->rvat_packtype = fgetc(xc->f);
#ifdef FST_DEBUG
fprintf(stderr, "\tframe_uclen: %d, frame_clen: %d, frame_maxhandle: %d\n",
fprintf(stderr, FST_APIMESS"frame_uclen: %d, frame_clen: %d, frame_maxhandle: %d\n",
(int)frame_uclen, (int)frame_clen, (int)xc->rvat_frame_maxhandle);
fprintf(stderr, "\tvc_maxhandle: %d\n", (int)xc->rvat_vc_maxhandle);
fprintf(stderr, FST_APIMESS"vc_maxhandle: %d\n", (int)xc->rvat_vc_maxhandle);
#endif
indx_pntr = blkpos + seclen - 24 -tsec_clen -8;
@ -5900,7 +5905,7 @@ fstReaderFseeko(xc, xc->f, indx_pntr, SEEK_SET);
chain_clen = fstReaderUint64(xc->f);
indx_pos = indx_pntr - chain_clen;
#ifdef FST_DEBUG
fprintf(stderr, "\tindx_pos: %d (%d bytes)\n", (int)indx_pos, (int)chain_clen);
fprintf(stderr, FST_APIMESS"indx_pos: %d (%d bytes)\n", (int)indx_pos, (int)chain_clen);
#endif
chain_cmem = malloc(chain_clen);
fstReaderFseeko(xc, xc->f, indx_pos, SEEK_SET);
@ -6011,7 +6016,7 @@ for(i=0;i<idx;i++)
}
#ifdef FST_DEBUG
fprintf(stderr, "\tdecompressed chain idx len: %"PRIu32"\n", idx);
fprintf(stderr, FST_APIMESS"decompressed chain idx len: %"PRIu32"\n", idx);
#endif
xc->rvat_data_valid = 1;
@ -6071,7 +6076,7 @@ if(!xc->rvat_chain_mem)
if(rc != Z_OK)
{
printf("\tclen: %d (rc=%d)\n", (int)xc->rvat_chain_len, rc);
fprintf(stderr, FST_APIMESS"fstReaderGetValueFromHandleAtTime(), rvat decompress clen: %d (rc=%d), exiting.\n", (int)xc->rvat_chain_len, rc);
exit(255);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2009-2015 Tony Bybell.
* Copyright (c) 2009-2017 Tony Bybell.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@ -168,7 +168,11 @@ enum fstHierType {
FST_HT_ATTRBEGIN = 3,
FST_HT_ATTREND = 4,
FST_HT_MAX = 4
/* FST_HT_TREEBEGIN and FST_HT_TREEEND are not yet used by FST but are currently used when fstHier bridges other formats */
FST_HT_TREEBEGIN = 5,
FST_HT_TREEEND = 6,
FST_HT_MAX = 6
};
enum fstAttrType {

View File

@ -825,7 +825,7 @@ _next_match:
/* Match description too long : reduce it */
matchLength = (15-1) + (oMaxMatch-op) * 255;
}
//printf("offset %5i, matchLength%5i \n", (int)(ip-match), matchLength + MINMATCH);
/*printf("offset %5i, matchLength%5i \n", (int)(ip-match), matchLength + MINMATCH);*/
ip += MINMATCH + matchLength;
if (matchLength>=ML_MASK)

View File

@ -5,7 +5,7 @@
%{
/*
* Copyright (c) 2007-2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 2007-2017 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
@ -217,7 +217,7 @@ static void destroy_sdf_lexor(void)
{
# 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
# if YY_FLEX_MINOR_VERSION > 5 || defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9
yylex_destroy();
# endif
# endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2015 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2017 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
@ -1887,6 +1887,8 @@ static const char *pts_convert(int value)
{
const char *string;
switch (value) {
case 2: string = "100s"; break;
case 1: string = "10s"; break;
case 0: string = "1s"; break;
case -1: string = "100ms"; break;
case -2: string = "10ms"; break;

View File

@ -4,7 +4,7 @@
%{
/*
* Copyright (c) 1999-2009 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2017 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
@ -199,7 +199,7 @@ void destroy_readmem_lexor(void)
{
# 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
# if YY_FLEX_MINOR_VERSION > 5 || defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9
yylex_destroy();
# endif
# endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007-2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 2007-2017 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
@ -289,7 +289,10 @@ static PLI_INT32 sys_sdf_annotate_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
FILE *sdf_fd;
char *fname = get_filename(callh, name, vpi_scan(argv));
if (fname == 0) return 0;
if (fname == 0) {
vpi_free_object(argv);
return 0;
}
sdf_fd = fopen(fname, "r");
if (sdf_fd == 0) {
@ -297,6 +300,8 @@ static PLI_INT32 sys_sdf_annotate_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
(int)vpi_get(vpiLineNo, callh));
vpi_printf("Unable to open SDF file \"%s\"."
" Skipping this annotation.\n", fname);
vpi_free_object(argv);
free(fname);
return 0;
}

View File

@ -6,7 +6,7 @@
%{
/*
* Copyright (C) 2011-2013 Cary R. (cygcary@yahoo.com)
* Copyright (C) 2011-2017 Cary R. (cygcary@yahoo.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -154,7 +154,7 @@ void destroy_tblmod_lexor(void)
{
# 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
# if YY_FLEX_MINOR_VERSION > 5 || defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9
yylex_destroy();
# endif
# endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008-2012 Stephen Williams (steve@icarus.com)
* Copyright (c) 2008-2018 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
@ -45,14 +45,14 @@ struct vvp_island_branch_tran : public vvp_island_branch {
vvp_island_branch_tran(vvp_net_t*en__, bool active_high__,
unsigned width__, unsigned part__,
unsigned offset__);
unsigned offset__, bool resistive__);
bool run_test_enabled();
void run_resolution();
void run_output();
vvp_net_t*en;
unsigned width, part, offset;
bool active_high;
bool active_high, resistive;
tran_state_t state;
};
@ -60,9 +60,10 @@ vvp_island_branch_tran::vvp_island_branch_tran(vvp_net_t*en__,
bool active_high__,
unsigned width__,
unsigned part__,
unsigned offset__)
unsigned offset__,
bool resistive__)
: en(en__), width(width__), part(part__), offset(offset__),
active_high(active_high__)
active_high(active_high__), resistive(resistive__)
{
state = en__ ? tran_disabled : tran_enabled;
}
@ -235,7 +236,8 @@ bool vvp_island_branch_tran::run_test_enabled()
// input is 'x' or 'z'. We use the rules that are given for MOS switches.
inline vvp_vector8_t resolve_ambiguous(const vvp_vector8_t&a,
const vvp_vector8_t&b,
tran_state_t state)
tran_state_t state,
unsigned str_map[8])
{
assert(a.size() == b.size());
vvp_vector8_t out (a.size());
@ -243,6 +245,9 @@ inline vvp_vector8_t resolve_ambiguous(const vvp_vector8_t&a,
for (unsigned idx = 0 ; idx < out.size() ; idx += 1) {
vvp_scalar_t a_bit = a.value(idx);
vvp_scalar_t b_bit = b.value(idx);
b_bit = vvp_scalar_t(b_bit.value(),
str_map[b_bit.strength0()],
str_map[b_bit.strength1()]);
if (state == tran_unknown) {
switch (b_bit.value()) {
case BIT4_0:
@ -293,8 +298,8 @@ static void push_value_through_branch(const vvp_vector8_t&val,
// previously collected (and resolved) for the port.
if (branch->width == 0) {
// There are no part selects.
dst_port->value = resolve_ambiguous(dst_port->value, val,
branch->state);
dst_port->value = resolve_ambiguous(dst_port->value, val, branch->state,
vvp_switch_strength_map[branch->resistive]);
} else if (dst_ab == 1) {
// The other side is a strict subset (part select)
@ -413,7 +418,7 @@ void compile_island_tranif(int sense, char*island, char*pa, char*pb, char*pe)
vvp_island_branch_tran*br = new vvp_island_branch_tran(en,
sense ? true :
false,
0, 0, 0);
0, 0, 0, false);
use_island->add_branch(br, pa, pb);
@ -430,7 +435,7 @@ void compile_island_tranvp(char*island, char*pa, char*pb,
free(island);
vvp_island_branch_tran*br = new vvp_island_branch_tran(NULL, false,
wid, par, off);
wid, par, off, false);
use_island->add_branch(br, pa, pb);

View File

@ -4,7 +4,7 @@
%{
/*
* Copyright (c) 2001-2012 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2017 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
@ -334,7 +334,7 @@ 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
# if YY_FLEX_MINOR_VERSION > 5 || defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9
yylex_destroy();
# endif
# endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005-2016 Stephen Williams (steve@icarus.com)
* Copyright (c) 2005-2018 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
@ -19,9 +19,10 @@
# include "npmos.h"
vvp_fun_pmos_::vvp_fun_pmos_(bool enable_invert)
vvp_fun_pmos_::vvp_fun_pmos_(bool enable_invert, bool resistive)
{
inv_en_ = enable_invert;
resistive_ = resistive;
}
@ -58,12 +59,18 @@ void vvp_fun_pmos_::recv_vec8_pv(vvp_net_ptr_t ptr, const vvp_vector8_t&bit,
void vvp_fun_pmos_::generate_output_(vvp_net_ptr_t ptr)
{
const unsigned*strength_map = vvp_switch_strength_map[resistive_];
vvp_vector8_t out (bit_.size());
for (unsigned idx = 0 ; idx < out.size() ; idx += 1) {
vvp_bit4_t b_en = en_.value(idx);
vvp_scalar_t b_bit = bit_.value(idx);
b_bit = vvp_scalar_t(b_bit.value(),
strength_map[b_bit.strength0()],
strength_map[b_bit.strength1()]);
switch (b_en) {
case BIT4_0:
out.set_bit(idx, b_bit);
@ -93,7 +100,7 @@ void vvp_fun_pmos_::generate_output_(vvp_net_ptr_t ptr)
vvp_fun_pmos::vvp_fun_pmos(bool enable_invert)
: vvp_fun_pmos_(enable_invert)
: vvp_fun_pmos_(enable_invert, false)
{
}
@ -112,7 +119,7 @@ void vvp_fun_pmos::recv_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&bit)
}
vvp_fun_rpmos::vvp_fun_rpmos(bool enable_invert)
: vvp_fun_pmos_(enable_invert)
: vvp_fun_pmos_(enable_invert, true)
{
}
@ -126,7 +133,7 @@ void vvp_fun_rpmos::recv_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&bit)
if (ptr.port() != 0)
return;
bit_ = resistive_reduction(bit);
bit_ = bit;
generate_output_(ptr);
}
@ -135,8 +142,9 @@ void vvp_fun_rpmos::recv_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&bit)
* CMOS primitive.
*/
vvp_fun_cmos_::vvp_fun_cmos_()
vvp_fun_cmos_::vvp_fun_cmos_(bool resistive)
{
resistive_ = resistive;
}
void vvp_fun_cmos_::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t &bit,
@ -175,6 +183,8 @@ void vvp_fun_cmos_::recv_vec8_pv(vvp_net_ptr_t ptr, const vvp_vector8_t&bit,
void vvp_fun_cmos_::generate_output_(vvp_net_ptr_t ptr)
{
const unsigned*strength_map = vvp_switch_strength_map[resistive_];
vvp_vector8_t out (bit_.size());
for (unsigned idx = 0 ; idx < out.size() ; idx += 1) {
@ -182,6 +192,10 @@ void vvp_fun_cmos_::generate_output_(vvp_net_ptr_t ptr)
vvp_bit4_t b_p_en = p_en_.value(idx);
vvp_scalar_t b_bit = bit_.value(idx);
b_bit = vvp_scalar_t(b_bit.value(),
strength_map[b_bit.strength0()],
strength_map[b_bit.strength1()]);
if (b_n_en == BIT4_1 || b_p_en == BIT4_0) {
out.set_bit(idx, b_bit);
} else if (b_n_en == BIT4_0 && b_p_en == BIT4_1) {
@ -206,7 +220,7 @@ void vvp_fun_cmos_::generate_output_(vvp_net_ptr_t ptr)
}
vvp_fun_cmos::vvp_fun_cmos()
: vvp_fun_cmos_()
: vvp_fun_cmos_(false)
{
}
@ -225,7 +239,7 @@ void vvp_fun_cmos::recv_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&bit)
}
vvp_fun_rcmos::vvp_fun_rcmos()
: vvp_fun_cmos_()
: vvp_fun_cmos_(true)
{
}
@ -239,6 +253,6 @@ void vvp_fun_rcmos::recv_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&bit)
if (ptr.port() != 0)
return;
bit_ = resistive_reduction(bit);
bit_ = bit;
generate_output_(ptr);
}

View File

@ -1,7 +1,7 @@
#ifndef IVL_npmos_H
#define IVL_npmos_H
/*
* Copyright (c) 2005-2016 Stephen Williams (steve@icarus.com)
* Copyright (c) 2005-2018 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
@ -46,7 +46,7 @@
class vvp_fun_pmos_ : public vvp_net_fun_t {
public:
explicit vvp_fun_pmos_(bool enable_invert);
explicit vvp_fun_pmos_(bool enable_invert, bool resistive);
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
vvp_context_t);
@ -62,7 +62,7 @@ class vvp_fun_pmos_ : public vvp_net_fun_t {
vvp_vector8_t bit_;
vvp_vector4_t en_;
bool inv_en_;
bool inv_en_, resistive_;
};
class vvp_fun_pmos : public vvp_fun_pmos_ {
@ -109,7 +109,7 @@ class vvp_fun_rpmos : public vvp_fun_pmos_ {
class vvp_fun_cmos_ : public vvp_net_fun_t {
public:
explicit vvp_fun_cmos_();
explicit vvp_fun_cmos_(bool resistive);
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t &bit,
vvp_context_t);
@ -126,6 +126,7 @@ class vvp_fun_cmos_ : public vvp_net_fun_t {
vvp_vector8_t bit_;
vvp_vector4_t n_en_;
vvp_vector4_t p_en_;
bool resistive_;
};
class vvp_fun_cmos : public vvp_fun_cmos_ {

View File

@ -648,78 +648,42 @@ static void schedule_event_(struct event_s*cur, vvp_time64_t delay,
receive the event at hand. Put the event in to the
appropriate list for the kind of assign we have at hand. */
switch (select_queue) {
struct event_s** q = 0;
switch (select_queue) {
case SEQ_START:
if (ctim->start == 0) {
ctim->start = cur;
} else {
cur->next = ctim->active->next;
ctim->active->next = cur;
ctim->active = cur;
}
q = &ctim->start;
break;
case SEQ_ACTIVE:
if (ctim->active == 0) {
ctim->active = cur;
} else {
/* Put the cur event on the end of the active list. */
cur->next = ctim->active->next;
ctim->active->next = cur;
ctim->active = cur;
}
q = &ctim->active;
break;
case SEQ_NBASSIGN:
if (ctim->nbassign == 0) {
ctim->nbassign = cur;
} else {
/* Put the cur event on the end of the active list. */
cur->next = ctim->nbassign->next;
ctim->nbassign->next = cur;
ctim->nbassign = cur;
}
q = &ctim->nbassign;
break;
case SEQ_RWSYNC:
if (ctim->rwsync == 0) {
ctim->rwsync = cur;
} else {
/* Put the cur event on the end of the active list. */
cur->next = ctim->rwsync->next;
ctim->rwsync->next = cur;
ctim->rwsync = cur;
}
q = &ctim->rwsync;
break;
case SEQ_ROSYNC:
if (ctim->rosync == 0) {
ctim->rosync = cur;
} else {
/* Put the cur event on the end of the active list. */
cur->next = ctim->rosync->next;
ctim->rosync->next = cur;
ctim->rosync = cur;
}
q = &ctim->rosync;
break;
case DEL_THREAD:
if (ctim->del_thr == 0) {
ctim->del_thr = cur;
} else {
/* Put the cur event on the end of the active list. */
cur->next = ctim->del_thr->next;
ctim->del_thr->next = cur;
ctim->del_thr = cur;
}
q = &ctim->del_thr;
break;
}
if (q) {
if (*q) {
/* Put the cur event on the end of the queue. */
cur->next = (*q)->next;
(*q)->next = cur;
}
*q = cur;
}
}
static void schedule_event_push_(struct event_s*cur)

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2018 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
@ -780,6 +780,15 @@ void vvp_signal_value::get_signal_value(struct t_vpi_value*vp)
}
}
static double vlg_round(double rval)
{
if (rval >= 0.0) {
return floor(rval + 0.5);
} else {
return ceil(rval - 0.5);
}
}
static void real_signal_value(struct t_vpi_value*vp, double rval)
{
char*rbuf = (char *) need_result_buf(64 + 1, RBUF_VAL);
@ -797,31 +806,26 @@ static void real_signal_value(struct t_vpi_value*vp, double rval)
if (rval != rval || (rval && (rval == 0.5*rval))) {
rval = 0.0;
} else {
if (rval >= 0.0) rval = floor(rval + 0.5);
else rval = ceil(rval - 0.5);
rval = vlg_round(rval);
}
vp->value.integer = (PLI_INT32)rval;
break;
case vpiDecStrVal:
#if !defined(__GNUC__)
if (isnan(rval))
sprintf(rbuf, "%s", "nan");
else
sprintf(rbuf, "%0.0f", rval);
#else
sprintf(rbuf, "%0.0f", rval);
#endif
if (isnan(rval))
sprintf(rbuf, "%s", "nan");
else
sprintf(rbuf, "%0.0f", vlg_round(rval));
vp->value.str = rbuf;
break;
case vpiHexStrVal:
sprintf(rbuf, "%lx", (long)rval);
sprintf(rbuf, "%lx", (long)vlg_round(rval));
vp->value.str = rbuf;
break;
case vpiBinStrVal: {
unsigned long val = (unsigned long)rval;
unsigned long val = (unsigned long)vlg_round(rval);
unsigned len = 0;
while (val > 0) {
@ -829,7 +833,7 @@ static void real_signal_value(struct t_vpi_value*vp, double rval)
val /= 2;
}
val = (unsigned long)rval;
val = (unsigned long)vlg_round(rval);
for (unsigned idx = 0 ; idx < len ; idx += 1) {
rbuf[len-idx-1] = (val & 1)? '1' : '0';
val /= 2;

View File

@ -339,7 +339,8 @@ extern vpiHandle vpip_make_int4(const char*name, int msb, int lsb,
vvp_net_t*vec);
extern vpiHandle vpip_make_var4(const char*name, int msb, int lsb,
bool signed_flag, vvp_net_t*net);
extern vpiHandle vpip_make_net4(const char*name, int msb, int lsb,
extern vpiHandle vpip_make_net4(__vpiScope*scope,
const char*name, int msb, int lsb,
bool signed_flag, vvp_net_t*node);
/*
@ -506,7 +507,9 @@ struct __vpiRealVar : public __vpiHandle {
};
extern struct __vpiScope* vpip_scope(__vpiRealVar*sig);
extern vpiHandle vpip_make_real_var(const char*name, vvp_net_t*net, bool is_wire);
extern vpiHandle vpip_make_real_var(const char*name, vvp_net_t*net);
extern vpiHandle vpip_make_real_net(__vpiScope*scope,
const char*name, vvp_net_t*net);
class __vpiBaseVar : public __vpiHandle {

View File

@ -178,7 +178,8 @@ vpiHandle __vpiRealVar::vpi_handle(int code)
vpiHandle __vpiRealVar::vpi_iterate(int code)
{ return real_var_iterate(code, this); }
vpiHandle vpip_make_real_var(const char*name, vvp_net_t*net, bool is_wire)
static vpiHandle vpip_make_real_(__vpiScope*scope, const char*name,
vvp_net_t*net, bool is_wire)
{
struct __vpiRealVar*obj = new __vpiRealVar;
@ -187,11 +188,22 @@ vpiHandle vpip_make_real_var(const char*name, vvp_net_t*net, bool is_wire)
obj->is_wire = is_wire;
obj->net = net;
obj->within.scope = vpip_peek_current_scope();
obj->within.scope = scope;
return obj;
}
vpiHandle vpip_make_real_var(const char*name, vvp_net_t*net)
{
return vpip_make_real_(vpip_peek_current_scope(), name, net, false);
}
vpiHandle vpip_make_real_net(__vpiScope*scope,
const char*name, vvp_net_t*net)
{
return vpip_make_real_(scope, name, net, true);
}
#ifdef CHECK_WITH_VALGRIND
void real_delete(vpiHandle item)
{

View File

@ -132,9 +132,19 @@ char *generic_get_str(int code, vpiHandle ref, const char *name, const char *ind
return res;
}
static vpiHandle fill_in_net4(struct __vpiSignal*obj,
const char*name, int msb, int lsb,
bool signed_flag, vvp_net_t*node);
static vpiHandle fill_in_net4(struct __vpiSignal*obj, __vpiScope*scope,
const char*name, int msb, int lsb,
bool signed_flag, vvp_net_t*node);
static vpiHandle fill_in_var4(struct __vpiSignal*obj,
const char*name, int msb, int lsb,
bool signed_flag, vvp_net_t*node)
{
// Variable declarations are always resolved immediately,
// so we can assume they belong in the current scope.
return fill_in_net4(obj, vpip_peek_current_scope(),
name, msb, lsb, signed_flag, node);
}
/*
* The standard formatting/conversion routines.
@ -972,7 +982,7 @@ struct signal_longint : public __vpiSignal {
vpiHandle vpip_make_int4(const char*name, int msb, int lsb, vvp_net_t*vec)
{
__vpiSignal*obj = new signal_integer;
return fill_in_net4(obj, name, msb, lsb, true, vec);
return fill_in_var4(obj, name, msb, lsb, true, vec);
}
/*
@ -1011,7 +1021,7 @@ vpiHandle vpip_make_int2(const char*name, int msb, int lsb, bool signed_flag,
}
}
return fill_in_net4(obj, name, msb, lsb, signed_flag, vec);
return fill_in_var4(obj, name, msb, lsb, signed_flag, vec);
}
/*
@ -1021,7 +1031,7 @@ vpiHandle vpip_make_var4(const char*name, int msb, int lsb,
bool signed_flag, vvp_net_t*vec)
{
__vpiSignal*obj = new signal_reg;
return fill_in_net4(obj, name, msb, lsb, signed_flag, vec);
return fill_in_var4(obj, name, msb, lsb, signed_flag, vec);
}
#ifdef CHECK_WITH_VALGRIND
@ -1116,7 +1126,7 @@ void signal_pool_delete()
* The name is the PLI name for the object. If it is an array it is
* <name>[<index>].
*/
static vpiHandle fill_in_net4(struct __vpiSignal*obj,
static vpiHandle fill_in_net4(struct __vpiSignal*obj, __vpiScope*scope,
const char*name, int msb, int lsb,
bool signed_flag, vvp_net_t*node)
{
@ -1130,18 +1140,19 @@ static vpiHandle fill_in_net4(struct __vpiSignal*obj,
// Place this object within a scope. If this object is
// attached to an array, then this value will be replaced with
// the handle to the parent.
obj->within.scope = vpip_peek_current_scope();
obj->within.scope = scope;
count_vpi_nets += 1;
return obj;
}
vpiHandle vpip_make_net4(const char*name, int msb, int lsb,
vpiHandle vpip_make_net4(__vpiScope*scope,
const char*name, int msb, int lsb,
bool signed_flag, vvp_net_t*node)
{
struct __vpiSignal*obj = new signal_net;
return fill_in_net4(obj, name, msb, lsb, signed_flag, node);
return fill_in_net4(obj, scope, name, msb, lsb, signed_flag, node);
}
static int PV_get_base(struct __vpiPV*rfp)

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2015 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2018 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001 Stephan Boettcher <stephan@nevis.columbia.edu>
*
* This source code is free software; you can redistribute it
@ -80,6 +80,15 @@ static int vthr_word_get(int code, vpiHandle ref)
}
}
static double vlg_round(double rval)
{
if (rval >= 0.0) {
return floor(rval + 0.5);
} else {
return ceil(rval - 0.5);
}
}
static void vthr_real_get_value(vpiHandle ref, s_vpi_value*vp)
{
struct __vpiVThrWord*obj = dynamic_cast<__vpiVThrWord*>(ref);
@ -108,31 +117,31 @@ static void vthr_real_get_value(vpiHandle ref, s_vpi_value*vp)
if (val != val || (val && (val == 0.5*val))) {
val = 0.0;
} else {
if (val >= 0.0) val = floor(val + 0.5);
else val = ceil(val - 0.5);
val = vlg_round(val);
}
vp->value.integer = (PLI_INT32)val;
break;
case vpiDecStrVal:
#if !defined(__GNUC__)
if (isnan(val))
sprintf(rbuf, "%s", "nan");
else
sprintf(rbuf, "%0.0f", val);
#else
sprintf(rbuf, "%0.0f", val);
#endif
if (isnan(val))
sprintf(rbuf, "%s", "nan");
else
sprintf(rbuf, "%0.0f", vlg_round(val));
vp->value.str = rbuf;
break;
case vpiOctStrVal:
sprintf(rbuf, "%lo", (long)vlg_round(val));
vp->value.str = rbuf;
break;
case vpiHexStrVal:
sprintf(rbuf, "%lx", (long)val);
sprintf(rbuf, "%lx", (long)vlg_round(val));
vp->value.str = rbuf;
break;
case vpiBinStrVal: {
unsigned long vali = (unsigned long)val;
unsigned long vali = (unsigned long)vlg_round(val);
unsigned len = 0;
while (vali > 0) {
@ -140,7 +149,7 @@ static void vthr_real_get_value(vpiHandle ref, s_vpi_value*vp)
vali /= 2;
}
vali = (unsigned long)val;
vali = (unsigned long)vlg_round(val);
for (unsigned idx = 0 ; idx < len ; idx += 1) {
rbuf[len-idx-1] = (vali & 1)? '1' : '0';
vali /= 2;
@ -279,6 +288,7 @@ class __vpiVThrVec4Stack : public __vpiHandle {
void vpi_get_value_int_ (p_vpi_value vp, const vvp_vector4_t&val);
void vpi_get_value_real_ (p_vpi_value vp, const vvp_vector4_t&val);
void vpi_get_value_strength_(p_vpi_value vp, const vvp_vector4_t&val);
void vpi_get_value_octstr_(p_vpi_value vp, const vvp_vector4_t&val);
void vpi_get_value_hexstr_(p_vpi_value vp, const vvp_vector4_t&val);
void vpi_get_value_vector_(p_vpi_value vp, const vvp_vector4_t&val);
private:
@ -346,6 +356,9 @@ void __vpiVThrVec4Stack::vpi_get_value(p_vpi_value vp)
case vpiDecStrVal:
vpi_get_value_decstr_(vp, val);
break;
case vpiOctStrVal:
vpi_get_value_octstr_(vp, val);
break;
case vpiHexStrVal:
vpi_get_value_hexstr_(vp, val);
break;
@ -396,6 +409,48 @@ void __vpiVThrVec4Stack::vpi_get_value_decstr_(p_vpi_value vp, const vvp_vector4
vp->value.str = rbuf;
}
void __vpiVThrVec4Stack::vpi_get_value_octstr_(p_vpi_value vp, const vvp_vector4_t&val)
{
unsigned wid = val.size();
unsigned owid = (wid + 2) / 3;
char*rbuf = (char*) need_result_buf(owid+1, RBUF_VAL);
rbuf[owid] = 0;
unsigned oval = 0;
for (unsigned idx = 0; idx < wid ; idx += 1) {
unsigned tmp = 0;
switch (val.value(idx)) {
case BIT4_0:
tmp = 0;
break;
case BIT4_1:
tmp = 1;
break;
case BIT4_X:
tmp = 2;
break;
case BIT4_Z:
tmp = 3;
break;
}
oval = oval | (tmp << 2*(idx%3));
if (idx%3 == 2) {
owid -= 1;
rbuf[owid] = oct_digits[oval];
oval = 0;
}
}
if (owid > 0) {
owid -= 1;
rbuf[owid] = oct_digits[oval];
oval = 0;
}
vp->value.str = rbuf;
}
void __vpiVThrVec4Stack::vpi_get_value_hexstr_(p_vpi_value vp, const vvp_vector4_t&val)
{
unsigned wid = val.size();

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2015 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2018 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
@ -2200,7 +2200,7 @@ static bool do_disable(vthread_t thr, vthread_t match)
}
vthread_t parent = thr->parent;
if (parent && parent->i_am_joining) {
if (parent && parent->i_am_joining && test_joinable(parent, thr)) {
// If a parent is waiting in a %join, wake it up. Note
// that it is possible to be waiting in a %join yet
// already scheduled if multiple child threads are
@ -2210,8 +2210,7 @@ static bool do_disable(vthread_t thr, vthread_t match)
if (! parent->i_have_ended)
schedule_vthread(parent, 0, true);
// Let the parent do the reaping.
vthread_reap(thr);
do_join(parent, thr);
} else if (parent) {
/* If the parent is yet to %join me, let its %join
@ -2518,6 +2517,10 @@ bool of_DIV_S(vthread_t thr, vvp_code_t)
if (bp[0] == 0) {
vvp_vector4_t tmp(wid, BIT4_X);
vala = tmp;
} else if (((long)ap[0] == LONG_MIN) && ((long)bp[0] == -1)) {
vvp_vector4_t tmp(wid, BIT4_0);
tmp.set_bit(wid-1, BIT4_1);
vala = tmp;
} else {
long tmpa = (long) ap[0];
long tmpb = (long) bp[0];
@ -2614,7 +2617,7 @@ bool of_END(vthread_t thr, vvp_code_t)
/* If I have a parent who is waiting for me, then mark that I
have ended, and schedule that parent. Also, finish the
%join for the parent. */
if (thr->parent && thr->parent->i_am_joining) {
if (!thr->i_am_detached && thr->parent && thr->parent->i_am_joining) {
vthread_t tmp = thr->parent;
assert(! thr->i_am_detached);
@ -3768,6 +3771,9 @@ bool of_MOD_S(vthread_t thr, vvp_code_t)
if (rv == 0)
goto x_out;
if ((lv == LONG_LONG_MIN) && (rv == -1))
goto zero_out;
/* Sign extend the signed operands when needed. */
if (wid < 8*sizeof(long long)) {
if (lv & (1LL << (wid-1)))
@ -3799,6 +3805,9 @@ bool of_MOD_S(vthread_t thr, vvp_code_t)
x_out:
vala = vvp_vector4_t(wid, BIT4_X);
return true;
zero_out:
vala = vvp_vector4_t(wid, BIT4_0);
return true;
}
/*

View File

@ -67,6 +67,11 @@ void vvp_darray::get_word(unsigned, vvp_object_t&)
cerr << "XXXX get_word(vvp_object_t) not implemented for " << typeid(*this).name() << endl;
}
void vvp_darray::shallow_copy(const vvp_object*)
{
cerr << "XXXX shallow_copy(vvp_object_t) not implemented for " << typeid(*this).name() << endl;
}
template <class TYPE> vvp_darray_atom<TYPE>::~vvp_darray_atom()
{
}
@ -101,6 +106,16 @@ template <class TYPE> void vvp_darray_atom<TYPE>::get_word(unsigned adr, vvp_vec
value = tmp;
}
template <class TYPE> void vvp_darray_atom<TYPE>::shallow_copy(const vvp_object*obj)
{
const vvp_darray_atom<TYPE>*that = dynamic_cast<const vvp_darray_atom<TYPE>*>(obj);
assert(that);
unsigned num_items = min(array_.size(), that->array_.size());
for (unsigned idx = 0 ; idx < num_items ; idx += 1)
array_[idx] = that->array_[idx];
}
template class vvp_darray_atom<uint8_t>;
template class vvp_darray_atom<uint16_t>;
template class vvp_darray_atom<uint32_t>;
@ -140,6 +155,16 @@ void vvp_darray_vec4::get_word(unsigned adr, vvp_vector4_t&value)
assert(value.size() == word_wid_);
}
void vvp_darray_vec4::shallow_copy(const vvp_object*obj)
{
const vvp_darray_vec4*that = dynamic_cast<const vvp_darray_vec4*>(obj);
assert(that);
unsigned num_items = min(array_.size(), that->array_.size());
for (unsigned idx = 0 ; idx < num_items ; idx += 1)
array_[idx] = that->array_[idx];
}
vvp_darray_vec2::~vvp_darray_vec2()
{
}
@ -173,6 +198,15 @@ void vvp_darray_vec2::get_word(unsigned adr, vvp_vector4_t&value)
}
}
void vvp_darray_vec2::shallow_copy(const vvp_object*obj)
{
const vvp_darray_vec2*that = dynamic_cast<const vvp_darray_vec2*>(obj);
assert(that);
unsigned num_items = min(array_.size(), that->array_.size());
for (unsigned idx = 0 ; idx < num_items ; idx += 1)
array_[idx] = that->array_[idx];
}
vvp_darray_object::~vvp_darray_object()
{
@ -200,6 +234,16 @@ void vvp_darray_object::get_word(unsigned adr, vvp_object_t&value)
value = array_[adr];
}
void vvp_darray_object::shallow_copy(const vvp_object*obj)
{
const vvp_darray_object*that = dynamic_cast<const vvp_darray_object*>(obj);
assert(that);
unsigned num_items = min(array_.size(), that->array_.size());
for (unsigned idx = 0 ; idx < num_items ; idx += 1)
array_[idx] = that->array_[idx];
}
vvp_darray_real::~vvp_darray_real()
{
}
@ -226,6 +270,16 @@ void vvp_darray_real::get_word(unsigned adr, double&value)
value = array_[adr];
}
void vvp_darray_real::shallow_copy(const vvp_object*obj)
{
const vvp_darray_real*that = dynamic_cast<const vvp_darray_real*>(obj);
assert(that);
unsigned num_items = min(array_.size(), that->array_.size());
for (unsigned idx = 0 ; idx < num_items ; idx += 1)
array_[idx] = that->array_[idx];
}
vvp_darray_string::~vvp_darray_string()
{
}
@ -252,6 +306,16 @@ void vvp_darray_string::get_word(unsigned adr, string&value)
value = array_[adr];
}
void vvp_darray_string::shallow_copy(const vvp_object*obj)
{
const vvp_darray_string*that = dynamic_cast<const vvp_darray_string*>(obj);
assert(that);
unsigned num_items = min(array_.size(), that->array_.size());
for (unsigned idx = 0 ; idx < num_items ; idx += 1)
array_[idx] = that->array_[idx];
}
vvp_queue::~vvp_queue()
{
}

View File

@ -44,6 +44,8 @@ class vvp_darray : public vvp_object {
virtual void set_word(unsigned adr, const vvp_object_t&value);
virtual void get_word(unsigned adr, vvp_object_t&value);
virtual void shallow_copy(const vvp_object*obj);
};
template <class TYPE> class vvp_darray_atom : public vvp_darray {
@ -55,6 +57,7 @@ template <class TYPE> class vvp_darray_atom : public vvp_darray {
size_t get_size(void) const;
void set_word(unsigned adr, const vvp_vector4_t&value);
void get_word(unsigned adr, vvp_vector4_t&value);
void shallow_copy(const vvp_object*obj);
private:
std::vector<TYPE> array_;
@ -70,6 +73,7 @@ class vvp_darray_vec4 : public vvp_darray {
size_t get_size(void) const;
void set_word(unsigned adr, const vvp_vector4_t&value);
void get_word(unsigned adr, vvp_vector4_t&value);
void shallow_copy(const vvp_object*obj);
private:
std::vector<vvp_vector4_t> array_;
@ -86,6 +90,7 @@ class vvp_darray_vec2 : public vvp_darray {
size_t get_size(void) const;
void set_word(unsigned adr, const vvp_vector4_t&value);
void get_word(unsigned adr, vvp_vector4_t&value);
void shallow_copy(const vvp_object*obj);
private:
std::vector<vvp_vector2_t> array_;
@ -101,6 +106,7 @@ class vvp_darray_real : public vvp_darray {
size_t get_size(void) const;
void set_word(unsigned adr, double value);
void get_word(unsigned adr, double&value);
void shallow_copy(const vvp_object*obj);
private:
std::vector<double> array_;
@ -115,6 +121,7 @@ class vvp_darray_string : public vvp_darray {
size_t get_size(void) const;
void set_word(unsigned adr, const std::string&value);
void get_word(unsigned adr, std::string&value);
void shallow_copy(const vvp_object*obj);
private:
std::vector<std::string> array_;
@ -129,6 +136,7 @@ class vvp_darray_object : public vvp_darray {
size_t get_size(void) const;
void set_word(unsigned adr, const vvp_object_t&value);
void get_word(unsigned adr, vvp_object_t&value);
void shallow_copy(const vvp_object*obj);
private:
std::vector<vvp_object_t> array_;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2004-2015 Stephen Williams (steve@icarus.com)
* Copyright (c) 2004-2018 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
@ -3421,7 +3421,8 @@ unsigned vvp_wide_fun_core::port_count() const
vvp_vector4_t& vvp_wide_fun_core::value(unsigned idx)
{
assert(idx < nports_);
assert(port_values_);
if (port_values_ == 0)
port_values_ = new vvp_vector4_t [nports_];
return port_values_[idx];
}
@ -3685,31 +3686,28 @@ vvp_scalar_t fully_featured_resolv_(vvp_scalar_t a, vvp_scalar_t b)
return res;
}
vvp_vector8_t resistive_reduction(const vvp_vector8_t&that)
{
static unsigned rstr[8] = {
0, /* Hi-Z --> Hi-Z */
1, /* Small capacitance --> Small capacitance */
1, /* Medium capacitance --> Small capacitance */
2, /* Weak drive --> Medium capacitance */
2, /* Large capacitance --> Medium capacitance */
3, /* Pull drive --> Weak drive */
5, /* Strong drive --> Pull drive */
5 /* Supply drive --> Pull drive */
};
vvp_vector8_t res (that.size());
for (unsigned idx = 0 ; idx < res.size() ; idx += 1) {
vvp_scalar_t bit = that.value(idx);
bit = vvp_scalar_t(bit.value(),
rstr[bit.strength0()],
rstr[bit.strength1()]);
res.set_bit(idx, bit);
unsigned vvp_switch_strength_map[2][8] = {
{ // non-resistive
0, /* High impedance --> High impedance */
1, /* Small capacitor --> Small capacitor */
2, /* Medium capacitor --> Medium capacitor */
3, /* Weak drive --> Weak drive */
4, /* Large capacitor --> Large capacitor */
5, /* Pull drive --> Pull drive */
6, /* Strong drive --> Strong drive */
6 /* Supply drive --> Strong drive */
},
{ // resistive
0, /* High impedance --> High impedance */
1, /* Small capacitor --> Small capacitor */
1, /* Medium capacitor --> Small capacitor */
2, /* Weak drive --> Medium capacitor */
2, /* Large capacitor --> Medium capacitor */
3, /* Pull drive --> Weak drive */
5, /* Strong drive --> Pull drive */
5 /* Supply drive --> Pull drive */
}
return res;
}
};
vvp_vector4_t reduce4(const vvp_vector8_t&that)
{

View File

@ -1,7 +1,7 @@
#ifndef IVL_vvp_net_H
#define IVL_vvp_net_H
/*
* Copyright (c) 2004-2016 Stephen Williams (steve@icarus.com)
* Copyright (c) 2004-2018 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
@ -954,9 +954,11 @@ inline vvp_vector8_t resolve(const vvp_vector8_t&a, const vvp_vector8_t&b)
return out;
}
/* This function implements the strength reduction implied by
Verilog standard resistive devices. */
extern vvp_vector8_t resistive_reduction(const vvp_vector8_t&a);
/* This lookup tabke implements the strength reduction implied by
Verilog standard switch devices. The major dimension selects
between non-resistive and resistive devices. */
extern unsigned vvp_switch_strength_map[2][8];
/* The reduce4 function converts a vector8 to a vector4, losing
strength information in the process. */
extern vvp_vector4_t reduce4(const vvp_vector8_t&that);

View File

@ -48,7 +48,7 @@ static void __compile_var_real(char*label, char*name,
define_functor_symbol(label, net);
vpiHandle obj = vpip_make_real_var(name, net, false);
vpiHandle obj = vpip_make_real_var(name, net);
compile_vpi_symbol(label, obj);
if (name) {
@ -350,7 +350,7 @@ static void do_compile_net(vvp_net_t*node, vvp_array_t array,
vpiHandle obj = 0;
if (! local_flag) {
/* Make the vpiHandle for the reg. */
obj = vpip_make_net4(name, msb, lsb, signed_flag, node);
obj = vpip_make_net4(scope, name, msb, lsb, signed_flag, node);
/* This attaches the label to the vpiHandle */
compile_vpi_symbol(my_label, obj);
}
@ -481,7 +481,7 @@ static void __compile_real_net2(vvp_net_t*node, vvp_array_t array,
vpiHandle obj = 0;
if (!local_flag) {
obj = vpip_make_real_var(name, node, true);
obj = vpip_make_real_net(scope, name, node);
compile_vpi_symbol(my_label, obj);
}
#ifdef CHECK_WITH_VALGRIND