Merge branch 'master' of ssh://steve-icarus@icarus.com/home/u/icarus/steve/git/verilog

This commit is contained in:
Stephen Williams 2009-12-09 18:20:19 -08:00
commit f7aef3f966
7 changed files with 110 additions and 22 deletions

View File

@ -239,6 +239,23 @@ static FILE*fopen_safe(const char*path)
}
#endif
#ifdef __MINGW32__
/*
* The MinGW version of getenv() returns the path with a forward
* slash. This should be converted to a back slash to keep every
* thing in the code using a back slash. This function wraps the
* code for this in one place. The conversion can not be done
* directly on the getenv() result since it is const char*.
*/
static void convert_to_MS_path(char *path)
{
char *t;
for (t = path; *t; t++) {
if (*t == '/') *t = '\\';
}
}
#endif
static const char*my_tempfile(const char*str, FILE**fout)
{
FILE*file;
@ -269,6 +286,9 @@ static const char*my_tempfile(const char*str, FILE**fout)
unsigned code = rand();
snprintf(pathbuf, sizeof pathbuf, "%s%c%s%04x",
tmpdir, sep, str, code);
#ifdef __MINGW32__
convert_to_MS_path(pathbuf);
#endif
file = fopen_safe(pathbuf);
retry -= 1;
}
@ -391,7 +411,7 @@ static int t_compile()
#endif
/* Build the ivl command and pipe it to the preprocessor. */
snprintf(tmp, sizeof tmp, " | %s/ivl", base);
snprintf(tmp, sizeof tmp, " | %s%civl", base, sep);
rc = strlen(tmp);
cmd = realloc(cmd, ncmd+rc+1);
strcpy(cmd+ncmd, tmp);
@ -425,16 +445,6 @@ static int t_compile()
strcpy(cmd+ncmd, tmp);
ncmd += rc;
#ifdef __MINGW32__
{
char *t;
for (t = cmd+ncmd_start; *t; t++)
{
if (*t == '/') *t = '\\';
}
}
#endif
if (verbose_flag)
printf("translate: %s\n", cmd);

View File

@ -996,6 +996,11 @@ NetExpr* NetEBPow::eval_tree_real_()
NetECReal*res = new NetECReal( pow(lval,rval) );
res->set_line(*this);
if (debug_eval_tree)
cerr << get_fileline() << ": debug: Evaluate (real) "
<< lval << " ** " << rval << " --> " << *res << endl;
return res;
}
@ -1016,7 +1021,14 @@ NetExpr* NetEBPow::eval_tree(int prune_to_width)
verinum lval = lc->value();
verinum rval = rc->value();
return new NetEConst( pow(lval,rval) );
NetEConst*res = new NetEConst( pow(lval,rval) );
res->set_line(*this);
if (debug_eval_tree)
cerr << get_fileline() << ": debug: Evaluate "
<< lval << " ** " << rval << " --> " << *res << endl;
return res;
}
/*

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2008 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2009 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
@ -746,7 +746,7 @@ verinum::V operator == (const verinum&left, const verinum&right)
right_pad = right.get(right.len()-1);
if (left_pad == verinum::V1 && right_pad == verinum::V0)
return verinum::V1;
return verinum::V0;
if (left_pad == verinum::V0 && right_pad == verinum::V1)
return verinum::V0;
}
@ -1051,9 +1051,45 @@ verinum operator * (const verinum&left, const verinum&right)
verinum pow(const verinum&left, const verinum&right)
{
verinum result = left;
unsigned pow_count = right.as_ulong();
long pow_count = right.as_long();
for (unsigned idx = 1 ; idx < pow_count ; idx += 1)
// We need positive and negative one in a few places.
verinum one (verinum::V0, left.len(), left.has_len());
one.has_sign(left.has_sign());
one.set(0, verinum::V1);
verinum m_one (verinum::V1, left.len(), left.has_len());
m_one.has_sign(true);
// If either the right or left values are undefined we return 'bx.
if (!right.is_defined() || !left.is_defined()) {
result = verinum(verinum::Vx, left.len(), left.has_len());
result.has_sign(left.has_sign());
// If the right value is zero we need to set the result to 1.
} else if (pow_count == 0) {
result = one;
} else if (pow_count < 0) {
// 0 ** <negative> is 'bx.
if (left.is_zero()) {
result = verinum(verinum::Vx, left.len(), left.has_len());
result.has_sign(left.has_sign());
// 1 ** <negative> is 1.
} else if (left == one) {
result = one;
// -1 ** <negative> is 1 or -1.
} else if (left.has_sign() && left == m_one) {
if (pow_count%2 == 0) {
result = one;
} else {
result = m_one;
}
// Everything else is 0.
} else {
result = verinum(verinum::V0, left.len(), left.has_len());
result.has_sign(left.has_sign());
}
}
for (long idx = 1 ; idx < pow_count ; idx += 1)
result = result * left;
return result;

View File

@ -17,6 +17,8 @@
#ifndef alloca
#define alloca __builtin_alloca
#endif
#else
#include <malloc.h>
#endif
#elif defined(_MSC_VER)
#include <malloc.h>
@ -26,8 +28,11 @@
#endif
/*
* $Id: wavealloca.h,v 1.2 2007/08/26 21:35:50 gtkwave Exp $
* $Id: wavealloca.h,v 1.3 2009/12/06 00:10:17 gtkwave Exp $
* $Log: wavealloca.h,v $
* Revision 1.3 2009/12/06 00:10:17 gtkwave
* mingw compatibility fix from icarus
*
* Revision 1.2 2007/08/26 21:35:50 gtkwave
* integrated global context management from SystemOfCode2007 branch
*

View File

@ -753,6 +753,9 @@ void schedule_generic(vvp_gen_event_t obj, vvp_time64_t delay,
cur->delete_obj_when_done = delete_when_done;
schedule_event_(cur, delay,
sync_flag? (ro_flag?SEQ_ROSYNC:SEQ_RWSYNC) : SEQ_ACTIVE);
if (sync_flag)
vthread_delay_delete();
}
void schedule_at_start_of_simtime(vvp_gen_event_t obj, vvp_time64_t delay)

View File

@ -112,6 +112,7 @@ struct vthread_s {
unsigned i_have_ended :1;
unsigned waiting_for_event :1;
unsigned is_scheduled :1;
unsigned delay_delete :1;
unsigned fork_count :8;
/* This points to the sole child of the thread. */
struct vthread_s*child;
@ -425,6 +426,7 @@ vthread_t vthread_new(vvp_code_t pc, struct __vpiScope*scope)
thr->schedule_parent_on_end = 0;
thr->is_scheduled = 0;
thr->i_have_ended = 0;
thr->delay_delete = 0;
thr->waiting_for_event = 0;
thr->fork_count = 0;
thr->event = 0;
@ -512,7 +514,10 @@ static void vthread_reap(vthread_t thr)
if ((thr->is_scheduled == 0) && (thr->waiting_for_event == 0)) {
assert(thr->fork_count == 0);
assert(thr->wait_next == 0);
schedule_del_thr(thr);
if (thr->delay_delete)
schedule_del_thr(thr);
else
vthread_delete(thr);
}
}
@ -531,6 +536,12 @@ void vthread_mark_scheduled(vthread_t thr)
}
}
void vthread_delay_delete()
{
if (running_thread)
running_thread->delay_delete = 1;
}
/*
* This function runs each thread by fetching an instruction,
* incrementing the PC, and executing the instruction. The thread may
@ -4504,9 +4515,12 @@ bool of_XOR(vthread_t thr, vvp_code_t cp)
bool of_ZOMBIE(vthread_t thr, vvp_code_t)
{
thr->pc = codespace_null();
if ((thr->parent == 0) && (thr->child == 0))
schedule_del_thr(thr);
if ((thr->parent == 0) && (thr->child == 0)) {
if (thr->delay_delete)
schedule_del_thr(thr);
else
vthread_delete(thr);
}
return false;
}

View File

@ -1,7 +1,7 @@
#ifndef __vthread_H
#define __vthread_H
/*
* Copyright (c) 2001-2008 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2009 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
@ -48,6 +48,14 @@ extern vthread_t vthread_new(vvp_code_t sa, struct __vpiScope*scope);
*/
extern void vthread_mark_scheduled(vthread_t thr);
/*
* This function causes deletion of the currently running thread to
* be delayed until after all sync events have been processed for the
* time step in which the thread terminates. It is only used by the
* schedule_generic function.
*/
extern void vthread_delay_delete();
/*
* Cause this thread to execute instructions until in is put to sleep
* by executing some sort of delay or wait instruction.