Table of Contents

Language plugins : Implementation

parse, print args

Background

“Args” are the parameters of the device.

Some languages read in args by order, some by name, some either way.

When reading by order, the meaning is determined by the order in the list. A single value, such as resistance of a resistor, specified as just a number, is a simple case of reading by order. There is also a special case that allows you to identify one as the “value” and read the rest by name.

The syntax varies. Some separate by whitespace, some separate by a comma. Some may use “name=value”. Another may use ”.name(value)”.

All of this must be considered in coding these functions. Because of this, we cannot say to “usually” use a particular function.

Some languages and devices use a different method “obsolete_callback” to handle the args. This is legacy code remaining from before there were plugins. Those will be recoded, and eventually obsolete_callback will be removed. It is not otherwise documented here.

parse_args

This functions reads the args from the input and stores the info.

Here is an example from Verilog, which accepts either order dependent or name=value pairs. The whole list is enclosed in parentheses. The port names are separated by commas. The format for a name=value pair is .name(value).

Remember, in the CS stream class “stream » variable” reads into the variable, like the usual C++ iostream. As an extension “stream » constant” reads and consumes only a matching constant from the stream.

While reading by order, the value is set by the function set_param_by_index(index, value). An exception Exception_Too_Many will be thrown if there are too many. Your code must catch the exception, and should print a message, and move on.

Due to the way hierarchy is implemented, the count is backwards. The highest numbered parameter is first. One way to do this is to use an index that starts at 0 and is incremented with every read, and subtract that from x→param_count(). Alternatively, you could start at x→param_count()-1 and count down.

While reading by name, the value is set by the function set_param_by_name(name, value). An exception Exception_No_Match will be thrown if the device type does not have a parameter that matches. Your code must catch the exception. Probably it should print a message, and move on. In some cases, you may want to silently ignore invalid parameters.

/*--------------------------------------------------------------------------*/
static void parse_args_instance(CS& cmd, CARD* x)
{
  assert(x);
 
  if (cmd >> "#(") {
    if (cmd.match1('.')) {
      // by name
      while (cmd >> '.') {
	unsigned here = cmd.cursor();
	std::string name  = cmd.ctos("(", "", "");
	std::string value = cmd.ctos(",)", "(", ")");
	cmd >> ',';
	try{
	  x->set_param_by_name(name, value);
	}catch (Exception_No_Match&) {untested();
	  cmd.warn(bDANGER, here, x->long_label() + ": bad parameter " + name + " ignored");
	}
      }
    }else{
      // by order
      int index = 1;
      while (cmd.is_alnum() || cmd.match1("+-.")) {
	unsigned here = cmd.cursor();
	try{
	  std::string value = cmd.ctos(",)", "", "");
	  x->set_param_by_index(x->param_count() - index++, value, 0/*offset*/);
	}catch (Exception_Too_Many& e) {untested();
	  cmd.warn(bDANGER, here, e.message());
	}
      }
    }
    cmd >> ')';
  }else{
    // no args
  }
}
/*--------------------------------------------------------------------------*/

print_args

Printing the arg list is just a loop.

The print loop prints them in order, the same order as the order dependent readin.

Due to the way hierarchy is implemented, the count is backwards. The highest numbered parameter is first. One way to do this is to use an index that starts at 0 and is incremented with every read, and subtract that from x→param_count(). Alternatively, you could start at x→param_count()-1 and count down.

For a device that uses the “obsolete_callback”, no loop is needed, just call print_args_obsolete_callback and let the device code do the work.

/*--------------------------------------------------------------------------*/
void LANG_VERILOG::print_args(OMSTREAM& o, const MODEL_CARD* x)
{
  assert(x);
  if (x->use_obsolete_callback_print()) {
    x->print_args_obsolete_callback(o, this);  //BUG//callback//
  }else{
    for (int ii = x->param_count() - 1;  ii >= 0;  --ii) {
      if (x->param_is_printable(ii)) {
	std::string arg = " ." + x->param_name(ii) + "=" + x->param_value(ii) + ";";
	o << arg;
      }else{
      }
    }
  }
}
/*--------------------------------------------------------------------------*/