Merge branch 'master' of ssh://steve-icarus@icarus.com/home/u/icarus/steve/git/verilog
This commit is contained in:
commit
f7aef3f966
|
|
@ -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);
|
||||
|
|
|
|||
14
eval_tree.cc
14
eval_tree.cc
|
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
44
verinum.cc
44
verinum.cc
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
Loading…
Reference in New Issue