( ESNUG 342 Item 8 ) --------------------------------------------- [2/03/00]
Subject: ( ESNUG 340 #5 341 #13 ) Sample PLI To Force FF's To 1's Or 0's
> So, do what the real hardware does, power up everything 1 or 0.
>
> How do you get rid of them? Write a simple PLI ACC program that loops
> through every reg in the design, fetches the value, and if X sets it to
> 0. You call this routine during reset, and all X's are gone. You then
> run an entire regression.
>
> - Wilson Snyder
> Maker Communications Framingham, MA
From: Thorsten Lutscher <thorsten.lutscher@force.de>
To: Wilson Snyder <wsnyder@maker.com>
Hi Wilson,
Such a PLI function to pre-set the default values of FFs at simulation
start time would be very helpful for us to fix the usual reset problems.
Unfortunately I have never written a PLI function and I would like to
ask you to provide it for other ESNUG readers as well.
- Thorsten Lutscher
FORCE Computers GmbH
---- ---- ---- ---- ---- ---- ----
From: Wilson Snyder <wsnyder@maker.com>
To: Thorsten Lutscher <thorsten.lutscher@force.de>
Hi, Thorsten,
I thought of submitting the code, but it's part of our whole enviornment
and thus doesn't use the "normal" PLI routines. Here is what I have.
#ident "$Id: gate.c,v 1.12 2000/01/31 14:43:21 wsnyder Exp $"
/
* This module contains free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
**********************************************************************
* gate.c - Gate level randomization
**********************************************************************
*/
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
#include <strings.h>
#include <fcntl.h>
#include <ctype.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/un.h>
#include <sys/uio.h>
#include <sys/time.h>
#include "pli.h"
#include <ehi.h>
/* Local Module defines */
/* Globals */
/* Prototypes */
/**** Internal code begin */
static int gate_sets;
void gate_randomize_net (
handle net_handle,
int value)
{
static s_setval_delay accdelay = {{accRealTime},accNoDelay};
static s_setval_value accvalue = {accBinStrVal};
char *val = acc_fetch_value (net_handle, "%b");
char *bit;
/* Look bit by bit, set any x to 0/1.... if chg... */
for (bit=val; *bit; bit++) {
if (*bit=='x') break;
}
//UTIL_PRINTF ("\tnet %s = %s\n", acc_fetch_fullname (net_handle), val);
if (*bit) {
if (!strcmp (acc_fetch_name(net_handle), "notifier")) {
/* Skip notifier nets */
return;
}
/* Have a x */
for (bit=val; *bit; bit++) {
if (*bit=='x') {
if (value==2) *bit='0';
else if (value==1) *bit='1';
else if (value==3) {
*bit = (lrand48() & 1)?'1':'0';
}
}
}
UTIL_PRINTF ("\tnet %s <= %s\n", acc_fetch_fullname (net_handle), val);
accvalue.value.str = val;
acc_error_flag = 0;
acc_set_value (net_handle, &accvalue, &accdelay);
gate_sets++;
if (acc_error_flag) {
UTIL_WARN ("Problem setting net %s = %s\n", acc_fetch_fullname (net_handle), val);
}
}
}
void gate_randomize_recurse (
handle mod_handle,
int value)
{
handle net_handle;
static regs[3] = {accRegister, accIntegerVar, 0};
static mods[3] = {accModuleInstance, accCellInstance, 0};
if (ehi_debug_level) UTIL_PRINTF ("Module %s %s\n", acc_fetch_fullname (mod_handle), acc_fetch_defname (mod_handle));
for (net_handle=NULL;
(net_handle = acc_next (regs, mod_handle, net_handle));) {
gate_randomize_net (net_handle, value);
}
for (net_handle=NULL;
(net_handle = acc_next (mods, mod_handle, net_handle));) {
gate_randomize_recurse (net_handle, value);
}
/*Can't look inside primitives */
/*
for (net_handle=NULL;
(net_handle = acc_next_primitive (mod_handle, net_handle));) {
UTIL_PRINTF (" subpr %s %s\n", acc_fetch_fullname (net_handle), acc_fetch_defname (net_handle));
}
*/
}
/* $gate_randomize ("bench.board.c0.mxt4400_shell.mxt4400", 1/2/3, #set);
* First parameter is top level module name to be initialized
* Second parameter 0, don't initialize.
* Second parameter 1, X's -> 1's
* Second parameter 2, X's -> 0's
* Second parameter 3, X's -> random 1 or 0
* Third parameter is output net set when something was changed.
* This is generally used to call gate_randomize every cycle till nothing
* is left in a X.
* Note that memories are NOT reset (as Verilog doesn't provide access to them),
* you need to do that in Verilog code. */
void gate_randomize_pli (void)
{
handle mod_handle;
char * hier = pli_getsp(1);
int value = pli_getp(2); /* 0=0, 1=all 1s, else randomize */
pli_info (0, "Starting gate randomization... (%s)\n",
((value==2)?"zeros"
:((value==1)?"ones"
:((value==3)?"random":"no change"))));
acc_initialize ();
/*acc_configure (accDisplayWarnings, "true");*/
mod_handle = acc_handle_object (hier);
if (acc_error_flag) {
UTIL_FATAL ("Can't find %s\n", hier);
}
gate_sets = 0;
gate_randomize_recurse (mod_handle, value);
acc_close ();
pli_info (0, "Completed gate randomization, %d X's.\n", gate_sets);
pli_putp (3, gate_sets);
}
You need to change the pli_ calls to the tf_getp and tf_putp parameters,
then have a pli.tab that maps $gate_randomize to the gate_randomize_pli
function. John, maybe you could talk one of your readers into tweaking
this PLI code sample into something more modular and useable for the general
ESNUG community? I don't have time to do this myself, but I'm glad to
volunteer this PLI code to get it started.
- Wilson Snyder
Maker Communications Framingham, MA
|
|