Skip to content

Commit

Permalink
Add function to define parameter from command line
Browse files Browse the repository at this point in the history
This patch is based on one from "bruce <[email protected]>".
I've applied all but the elaboration code, which I rewrote to
properly work with the elaboration work queue. I also constrained
the implementation so that the parameter name must have exactly
two components: the root scope name and the parameter name. This
is necessary to keep the defparm processing sane. The comments
from bruce's original patch are as follows:
--
This patch would provide function to define parameter from command
line. This serves the same functionality as 'defparam' in Verilog
source code, but provide much more ease for using. Parameter
definition can be write in command file, with following syntax:

    +parameter+<scope>.<parameter>=<val>

*Do not apply any space between them*
The scope name should be full hierachical name with root name at
the begining. The following example would override test.T1 with
new value 2'b01:

    +parameter+test.T1=2'b01

'test' here is the root module name. The parameter value here
should be constant. Parameter definition can also be write in
the command line:

    iverilog -Ptest.T1=2'b01

This serves the same functionality with the previous example.
If we define the same parameter in command file and command line,
the one in command line would over-write all others.
  • Loading branch information
steveicarus committed Aug 6, 2009
1 parent 37b11e0 commit 7b102b1
Show file tree
Hide file tree
Showing 12 changed files with 236 additions and 17 deletions.
2 changes: 2 additions & 0 deletions Module.cc
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
# include "PWire.h"
# include <assert.h>

list<Module::named_expr_t> Module::user_defparms;

/* n is a permallocated string. */
Module::Module(perm_string n)
: PScope(n)
Expand Down
1 change: 1 addition & 0 deletions Module.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ class Module : public PScope, public LineInfo {
instantiated modules. */
typedef pair<pform_name_t,PExpr*> named_expr_t;
list<named_expr_t>defparms;
static list<named_expr_t>user_defparms;

/* Parameters may be overridden at instantiation time;
the overrides do not contain explicit parameter names,
Expand Down
2 changes: 2 additions & 0 deletions driver/cflexor.lex
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ int cmdfile_stack_ptr = 0;
\n { cflloc.first_line += 1; }


"+parameter+" { BEGIN(PLUS_ARGS); return TOK_PARAMETER; }

"+define+" { BEGIN(PLUS_ARGS); return TOK_DEFINE; }

"+incdir+" { BEGIN(PLUS_ARGS); return TOK_INCDIR; }
Expand Down
9 changes: 8 additions & 1 deletion driver/cfparse.y
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ static void translate_file_name(char*text)
};

%token TOK_Da TOK_Dc TOK_Dv TOK_Dy
%token TOK_DEFINE TOK_INCDIR TOK_LIBDIR TOK_LIBDIR_NOCASE TOK_LIBEXT
%token TOK_DEFINE TOK_INCDIR TOK_LIBDIR TOK_LIBDIR_NOCASE TOK_LIBEXT TOK_PARAMETER
%token TOK_INTEGER_WIDTH
%token <text> TOK_PLUSARG TOK_PLUSWORD TOK_STRING

Expand Down Expand Up @@ -135,6 +135,13 @@ item
free(tmp);
}

| TOK_PARAMETER TOK_PLUSARG
{ char*tmp = substitutions($2);
process_parameter(tmp);
free($2);
free(tmp);
}

| TOK_DEFINE TOK_PLUSARG
{ process_define($2);
free($2);
Expand Down
5 changes: 4 additions & 1 deletion driver/globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,10 @@ extern void process_include_dir(const char*name);

/* Add a new -D define. */
extern void process_define(const char*name);


/* Add a new parameter definition */
extern void process_parameter(const char*name);

/* -v */
extern int verbose_flag;

Expand Down
27 changes: 26 additions & 1 deletion driver/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,12 @@ typedef struct t_command_file {
p_command_file cmd_file_head = NULL; /* The FIFO head */
p_command_file cmd_file_tail = NULL; /* The FIFO tail */

/* Temprarily store parameter definition from command line and
* parse it after we have delt with command file
*/
static const char** defparm_base = 0;
static int defparm_size = 0;

/* Function to add a command file name to the FIFO. */
void add_cmd_file(const char* filename)
{
Expand Down Expand Up @@ -530,6 +536,11 @@ void process_define(const char*name)
fprintf(defines_file,"D:%s\n", name);
}

void process_parameter(const char*name)
{
fprintf(iconfig_file,"defparam:%s\n", name);
}

/*
* This function is called while processing a file name in a command
* file, or a file name on the command line. Look to see if there is a
Expand Down Expand Up @@ -774,7 +785,7 @@ int main(int argc, char **argv)
}
}

while ((opt = getopt(argc, argv, "B:c:D:d:Ef:g:hI:M:m:N::o:p:Ss:T:t:vVW:y:Y:")) != EOF) {
while ((opt = getopt(argc, argv, "B:c:D:d:Ef:g:hI:M:m:N::o:P:p:Ss:T:t:vVW:y:Y:")) != EOF) {

switch (opt) {
case 'B':
Expand All @@ -798,6 +809,11 @@ int main(int argc, char **argv)
case 'E':
e_flag = 1;
break;
case 'P':
defparm_size += 1;
defparm_base = (const char**)realloc(defparm_base, defparm_size*sizeof(char*));
defparm_base[defparm_size-1] = optarg;
break;
case 'p':
fprintf(iconfig_file, "flag:%s\n", optarg);
break;
Expand Down Expand Up @@ -966,6 +982,15 @@ int main(int argc, char **argv)
fprintf(defines_file, "M:%s\n", depfile);
}

/* Process parameter definition from command line. The last
defined would override previous ones. */
int pitr;
for (pitr = 0; pitr < defparm_size; pitr++)
process_parameter(defparm_base[pitr]);
free(defparm_base);
defparm_base = 0;
defparm_size = 0;

/* Finally, process all the remaining words on the command
line as file names. */
for (idx = optind ; idx < argc ; idx += 1)
Expand Down
19 changes: 17 additions & 2 deletions elaborate.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4226,8 +4226,23 @@ class elaborate_root_scope_t : public elaborator_work_item_t {

virtual void elaborate_runrun()
{
Module::replace_t stub;
if (! rmod_->elaborate_scope(des, scope_, stub))
Module::replace_t root_repl;
for (list<Module::named_expr_t>::iterator cur = Module::user_defparms.begin()
; cur != Module::user_defparms.end() ; cur++) {

pform_name_t tmp_name = cur->first;
if (peek_head_name(tmp_name) != scope_->basename())
continue;

tmp_name.pop_front();
if (tmp_name.size() != 1)
continue;

NetExpr*tmp_expr = cur->second->elaborate_pexpr(des, scope_);
root_repl[peek_head_name(tmp_name)] = tmp_expr;
}

if (! rmod_->elaborate_scope(des, scope_, root_repl))
des->errors += 1;
}

Expand Down
20 changes: 10 additions & 10 deletions lexor.lex
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,11 @@ void reset_lexor();
static void line_directive();
static void line_directive2();

static verinum*make_unsized_binary(const char*txt);
static verinum*make_undef_highz_dec(const char*txt);
static verinum*make_unsized_dec(const char*txt);
static verinum*make_unsized_octal(const char*txt);
static verinum*make_unsized_hex(const char*txt);
verinum*make_unsized_binary(const char*txt);
verinum*make_undef_highz_dec(const char*txt);
verinum*make_unsized_dec(const char*txt);
verinum*make_unsized_octal(const char*txt);
verinum*make_unsized_hex(const char*txt);

static int dec_buf_div2(char *buf);

Expand Down Expand Up @@ -667,7 +667,7 @@ void lex_end_table()
BEGIN(INITIAL);
}

static verinum*make_unsized_binary(const char*txt)
verinum*make_unsized_binary(const char*txt)
{
bool sign_flag = false;
const char*ptr = txt;
Expand Down Expand Up @@ -725,7 +725,7 @@ static verinum*make_unsized_binary(const char*txt)
}


static verinum*make_unsized_octal(const char*txt)
verinum*make_unsized_octal(const char*txt)
{
bool sign_flag = false;
const char*ptr = txt;
Expand Down Expand Up @@ -792,7 +792,7 @@ static verinum*make_unsized_octal(const char*txt)
}


static verinum*make_unsized_hex(const char*txt)
verinum*make_unsized_hex(const char*txt)
{
bool sign_flag = false;
const char*ptr = txt;
Expand Down Expand Up @@ -919,7 +919,7 @@ static int dec_buf_div2(char *buf)
}

/* Support a single x, z or ? as a decimal constant (from 1364-2005). */
static verinum* make_undef_highz_dec(const char* ptr)
verinum* make_undef_highz_dec(const char* ptr)
{
bool signed_flag = false;

Expand Down Expand Up @@ -972,7 +972,7 @@ static verinum* make_undef_highz_dec(const char* ptr)
* hard to calculate.
*/

static verinum*make_unsized_dec(const char*ptr)
verinum*make_unsized_dec(const char*ptr)
{
char buf[4096];
bool signed_flag = false;
Expand Down
5 changes: 3 additions & 2 deletions main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -528,8 +528,9 @@ static void read_iconfig_file(const char*ipath)
<< endl;
flag_errors += 1;
}

}
} else if (strcmp(buf,"defparam") == 0) {
parm_to_defparam_list(cp);
}
}
fclose(ifile);
}
Expand Down
10 changes: 10 additions & 0 deletions parse_misc.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,14 @@ extern UCDriveType uc_drive;
extern bool have_timeunit_decl;
extern bool have_timeprec_decl;

/*
* Export there functions because we have to generate PENumber class
* in pform.cc for user defparam definition from command file.
*/
extern verinum*make_unsized_dec(const char*txt);
extern verinum*make_undef_highz_dec(const char*txt);
extern verinum*make_unsized_binary(const char*txt);
extern verinum*make_unsized_octal(const char*txt);
extern verinum*make_unsized_hex(const char*txt);

#endif
145 changes: 145 additions & 0 deletions pform.cc
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,151 @@
map<perm_string,Module*> pform_modules;
map<perm_string,PUdp*> pform_primitives;


/*
* Parse configuration file with format <key>=<value>, where key
* is the hierarchical name of a valid parameter name, and value
* is the value user wants to assign to. The value should be constant.
*/
void parm_to_defparam_list(const string&param)
{
const char* key;
const char* value;
unsigned off = param.find('=');
if (off > param.size()) {
key = strdup(param.c_str());
value = "";

} else {
key = strdup(param.substr(0, off).c_str());
value = strdup(param.substr(off+1).c_str());
}

// Resolve hierarchical name for defparam. Remember
// to deal with bit select for generate scopes. Bit
// select expression should be constant interger.
pform_name_t name;
const char *nkey = key;
char *ptr = strchr(key, '.');
while (ptr != 0) {
*ptr++ = '\0';
// Find if bit select is applied, this would be something
// like - scope[2].param = 10
char *bit_l = strchr(nkey, '[');
if (bit_l !=0) {
*bit_l++ = '\0';
char *bit_r = strchr(bit_l, ']');
if (bit_r == 0) {
cerr << "<command line>: error: missing ']' for defparam: " << nkey << endl;
return;
}
*bit_r = '\0';
int i = 0;
while (*(bit_l+i) != '\0')
if (!isdigit(*(bit_l+i++))) {
cerr << "<command line>: error: scope index expression is not constant: " << nkey << endl;
return;
}
name_component_t tmp(lex_strings.make(nkey));
index_component_t index;
index.sel = index_component_t::SEL_BIT;
verinum *seln = new verinum(atoi(bit_l));
PENumber *sel = new PENumber(seln);
index.msb = sel;
index.lsb = sel;
tmp.index.push_back(index);
name.push_back(tmp);
}
else // no bit select
name.push_back(name_component_t(lex_strings.make(nkey)));

nkey = ptr;
ptr = strchr(nkey, '.');
}
name.push_back(name_component_t(lex_strings.make(nkey)));

// Resolve value to PExpr class. Should support all kind of constant
// format including based number, dec number, real number and string.
if (*value == '"') { // string type
char *buf = strdup (value);
char *buf_ptr = buf+1;
// Parse untill another '"' or '\0'
while (*buf_ptr != '"' && *buf_ptr != '\0') {
buf_ptr++;
// Check for escape, especially '\"', which does not mean the
// end of string.
if (*buf_ptr == '\\' && *(buf_ptr+1) != '\0')
buf_ptr += 2;
}
if (*buf_ptr == '\0') // String end without '"'
cerr << "<command line>: error: missing close quote of string for defparam: " << name << endl;
else if (*(buf_ptr+1) != 0) { // '"' appears within string with no escape
cerr << buf_ptr << endl;
cerr << "<command line>: error: \'\"\' appears within string value for defparam: " << name
<< ". Ignore characters after \'\"\'" << endl;
}

*buf_ptr = '\0';
buf_ptr = buf+1;
// Remember to use 'new' to allocate string for PEString
// because 'delete' is used by its destructor.
char *nchar = strcpy(new char [strlen(buf_ptr)+1], buf_ptr);
PEString* ndec = new PEString(nchar);
Module::user_defparms.push_back( make_pair(name, ndec) );
free(buf);
}
else { // number type
char *num = strchr(value, '\'');
if (num != 0) {
verinum *val;
// BASED_NUMBER, somthing like - scope.parameter='b11
// make sure to check 'h' first because 'b'&'d' may be included
// in hex format
if (strchr(num, 'h') || strchr(num, 'H'))
val = make_unsized_hex(num);
else if (strchr(num, 'd') || strchr(num, 'D'))
if (strchr(num, 'x') || strchr(num, 'X') || strchr(num, 'z') || strchr(num, 'Z'))
val = make_undef_highz_dec(num);
else
val = make_unsized_dec(num);
else if (strchr(num, 'b') || strchr(num, 'B')) {
val = make_unsized_binary(num);
}
else if (strchr(num, 'o') || strchr(num, 'O'))
val = make_unsized_octal(num);
else {
cerr << "<command line>: error: value specify error for defparam: " << name << endl;
return;
}

// BASED_NUMBER with size, something like - scope.parameter=2'b11
if (num != value) {
*num = 0;
verinum *siz = make_unsized_dec(value);
val = pform_verinum_with_size(siz, val, "<command line>", 0);
}

PENumber* ndec = new PENumber(val);
Module::user_defparms.push_back( make_pair(name, ndec) );

}
else {
// REALTIME, something like - scope.parameter=1.22 or scope.parameter=1e2
if (strchr(value, '.') || strchr(value, 'e') || strchr(value, 'E')) {
verireal *val = new verireal(value);
PEFNumber* nreal = new PEFNumber(val);
Module::user_defparms.push_back( make_pair(name, nreal) );
}
else {
// DEC_NUMBER, something like - scope.parameter=3
verinum *val = make_unsized_dec(value);
PENumber* ndec = new PENumber(val);
Module::user_defparms.push_back( make_pair(name, ndec) );
}
}
}
}

/*
* The lexor accesses the vl_* variables.
*/
Expand Down
Loading

0 comments on commit 7b102b1

Please sign in to comment.