Passing params to function in global, INTERSYSTEM CACHE - intersystems-cache

I have a problem. I can't find a way to pass parameters to the function, inside teh Global:
set ^SERIES(1)="Nombre de Serie#Humor#10#Do ResultadoSerie^KDAobjetos(respuesta)"
.....
CargaMenu1 ;
New Sql,Statement,status,resultSet,resultado,mensaje
Set Sql="select * from SQLUser.Series"
Set Statement=##class(%SQL.Statement).%New()
Set status=Statement.%Prepare(Sql)
If status=1
{
Set resultSet=Statement.%Execute()
While resultSet.%Next()
{
Use 0 Write $J(resultSet.IdSeries,5)_".- "_resultSet.NombreSerie,!
}
}
else
{
// No se ha podido ejecutar la consulta.
set resultado=-1
set mensaje=$$STATUSERROR^SPAHH000(status)
Use 0 Write resultado_" : "_mensaje,!
}
// Condicion de salida
Use 0 Write !,$J(0,5)_".- Salir",!
W !,""
Quit
CargaMenu2(respuesta)
New objSerie,status
set objSerie = ##class(User.Series).%OpenId(respuesta,,.status)
If status = 1
{
Xecute objSerie.XecuteCode(respuesta)
}
else
{
W !,""
Use 0 write "OpciĆ³n no disponible.",!
hang 2
}
Quit
ResultadoSerie(respuesta) ;
set objSerie = ##class(User.Series).%OpenId(respuesta,,.status)
W #,"La serie "objSerie.NombreSerie", es de "objSerie.CategoriaSerie" y tiene "objSerie.TemporadasSerie" temporadas."
W !!, ""
hang 2
Quit
Terminal Result :
<OBJECT DISPATCH>Function2+9^CargaMenu2 *Property 'XecuteCode' in class 'User.Serie' is not MultiDimensional
USER 3d1>

Even after update, still does not explain why you need it this way. It's not very good to execute this way some code stored somewhere in the database. I would recommend finding another way.
Anyway, you have to construct the correct string, with all the parameters inside, and execute it. And loot to the documentation. Maybe you'll find a better answer.

Related

How to run e file one by one? Not in parallel test

I am new to specman, I am now writing a testbench which i want to give many specific test cases to debug a calculator.
For example,
I have two files, the first one called "test1" and the second called "test2".
Here is my code for "test1":
extend instruction_s {
keep cmd_in_1 == ADD;
keep din1_1 < 10;
keep din2_1 < 10;
};
extend driver_u {
keep instructions_to_drive.size() == 10;
};
And here is my code for "test2":
extend instruction_s {
keep cmd_in_1 == SUB;
keep din1_1 < 10;
keep din2_1 < 10;
};
extend driver_u {
keep instructions_to_drive.size() == 10;
};
However, when I tried to test my code, specman shows error, it seems I can't do this like that.
Is there any possible way that I can let specman execute "test1" file first and then run "test2" file?
Or if there is some other way that I can achieve my goal?
Thanks for your helping.
Do you really want to have one test that executes 10 ADD instructions, and run another test that executes 10 SUB instructions?
If so, the common way to do so is to compile your testbench, and run multiple times - each time loading another test file.
For a start, try this:
xrun my_device.v my_testbench.e test1.e
xrun my_device.v my_testbench.e test2.e

How can i tell specman to terminate the test after 5 dut_erros

I need to specify to specman a maximal amount of dut_errors in the test, which after that limit the test should be terminated.
Currently i have the option to terminate the test when an error accord or never.
You can also change the check_effect to ERROR, so it will cause the run to stop. For example (I am taking here Thorsten's example, and modify it):
extend sn_util {
!count_errors: uint;
};
extend dut_error_struct {
pre_error() is also {
util.count_errors += 1;
if util.count_errors > 5 {
set_check_effect(ERROR);
};
};
};
AFAIK this does not work out of the box. You could count the errors by using a global variable and extending the error struct, something in the line of
extend sn_util {
!count_errors: uint;
count() is {
count_errors += 1;
if count_errors > 5 { stop_run() };
};
};
extend dut_error_struct {
write() is also { util.count() };
};
There might even be an object in global that does the counting already, but probably not documented.

Test if property exists on a class at runtime

Something like this:
##class(MyApp.MyClass).%HasProperty("SomeProperty").
I looked into doing something like this:
set classDefinition = ##class(%Dictionary.CompiledClass).%OpenId(%class.Name)
and then looping through the Properties, however, I need to be able to use any class, not just %class
For a simple OO approach, you can use the following API:
Set tPropExists = ##class(%Dictionary.CompiledProperty).IDKEYExists("SomeClass","SomeProperty")
This should have much less runtime cost than loading the class definition data and looping over its properties (and thus loading the data for those properties as well).
If you still want to create a %HasProperty() helper method for your application classes, you can use the following base method (assuming you are on Cache 2010.2 or higher - I believe the $this special variable and the $classname() function were added in 2010.2, but that may have been in 2010.1.):
ClassMethod %HasProperty(pPropName As %String = "") As %Boolean
{
Set tHasProp = 0
If (pPropName '= "") {
Set tHasProp = ##class(%Dictionary.CompiledProperty).IDKEYExists($classname($this),pPropName)
}
Quit tHasProp
}
You also might want to use a generator method (one of the really nice features in Cache objects) if run-time speed is important to you.
For example:
Method PropertyExists(Name) As %Boolean [ CodeMode = generator, ProcedureBlock = 1, ServerOnly = 1 ]
{
Set %code=0
S ClassDef=##class(%Dictionary.CompiledClass).%OpenId(%class)
i '$IsObject(ClassDef) $$$GENERATE(" Q 0") Q $$$OK
I '$IsObject(ClassDef.Properties) $$$GENERATE(" Q 0") Q $$$OK
S Key="" F S Key=ClassDef.Properties.Next(Key) Q:Key="" D
. S CompiledProperty=ClassDef.Properties.GetAt(Key)
. $$$GENERATE(" I Name="""_CompiledProperty.Name_""" Q 1" )
$$$GENERATE(" Q 0")
q $$$OK
}

Retrieving variable name in order to print them in specman

I wish to do the following in Specman:
my_task() is {
var my_var : int;
my_var = 5;
message(LOW,appendf("%s=[%d]",my_var.to_name(),my_var));
};
Currently, I'm in search of the internal task to_name(). I do not want to create a struct for this. I wish to only use Specman internals.
I'm not sure how you'd do this unless you somehow have the collection of all the fields, which would give you the name of all the fields.
So, I'm going to branch predict and assume that you want all the fields of a given struct/unit:
extend sys {
A : list of uint;
B : int;
cee : string;
run() is also {
var rf_sys: rf_struct = rf_manager.get_exact_subtype_of_instance(sys);
for each (field) in rf_sys.get_declared_fields() {
print field;
print field.get_long_name(); // <-- Here's your "get_name()" function
};
};
};
On version 8.2, this yields:
Usage: . env.sh [-32bit|-64bit] [-v] [[VAR=value]...]
Welcome to Specman Elite(64) (09.20.482-d) - Linked on Wed Mar 2 13:32:19
2011
Protected by U.S. Patents 6,141,630 ;6,182,258; 6,219,809; 6,347,388;
6,487,704; 6,499,132; 6,502,232; 6,519,727; 6,530,054; 6,675,138; 6,684,359;
6,687,662; 6,907,599; 6,918,076; 6,920,583; Other Patents Pending.
1 notification was modified by command 'set notify -severity=WARNING
DEPR_START_TCM_ARG_BY_REF'
Checking license ... OK
Loading /nfs/pdx/home/rbroger1/tmp.e ...
read...parse...update...patch...h code...code...clean...GC(sys)...
Doing setup ...
Generating the test using seed 1...
Starting the test ...
Running the test ...
field = rf_field 'time', Specman's private modules
field.get_long_name() = "time"
field = rf_field 'logger', Specman's private modules
field.get_long_name() = "logger"
field = rf_field 'A', line 5 in #tmp
field.get_long_name() = "A"
field = rf_field 'B', line 6 in #tmp
field.get_long_name() = "B"
field = rf_field 'cee', line 7 in #tmp
field.get_long_name() = "cee"
No actual running requested.
Checking the test ...
Checking is complete - 0 DUT errors, 0 DUT warnings.
If that doesn't quite answer your question, look more into Specman's introspection or reflection interface in the documentation for your version of Specman. Warning, details are a bit scarce from Cadence. Also, see my answer to "Specman: how to retrieve values of var which is stored in another var".. Finally, in specview you can use the data browser to browse the rf_manger itself ( introspection at its best). Then you can find all the functions that Cadence doesn't tell you about in their documentation.
You can't get the string name of a variable. Although you can get the name of a field using get_name().
This makes some sense, because the variable is only known at the location it is declared. You can't even access the variable in a later extension of my_task(). So if you are already editing the code at the location where the variable was declared, just say "my_var" rather than my_var.to_name(). (Yes, typos and cut and paste errors can happen.)
I think this is what you are looking for:
define <dump'action> "dump <exp>" as {
out("<exp>","=[",<exp>,"]");
};
you can use this macro in the specman command line or inside functions, for example:
foo() is {
var a : int = 5;
dump a;
};
will give:
a=[5]

Problem reading Serial Port C#.net 2.0 to get Weighing machine output

I'm trying to read weight from Sartorius Weighing Scale model No BS2202S using the following code in C#.net 2.0 on a Windows XP machine:
public string readWeight()
{
string lastError = "";
string weightData = "";
SerialPort port = new SerialPort();
port.PortName = "COM1";
port.BaudRate = 9600;
port.Parity = Parity.Even;
port.DataBits = 7;
port.StopBits = StopBits.One;
port.Handshake = Handshake.RequestToSend;
try {
port.Open();
weightData = port.ReadExisting();
if(weightData == null || weightData.Length == 0) {
lastError = "Unable to read weight. The data returned form weighing machine is empty or null.";
return lastError;
}
}
catch(TimeoutException) {
lastError = "Operation timed out while reading weight";
return lastError;
}
catch(Exception ex) {
lastError = "The following exception occurred while reading data." + Environment.NewLine + ex.Message;
return lastError;
}
finally {
if(port.IsOpen == true) {
port.Close();
port.Dispose();
}
}
return weightData;
}
I'm able to read the weight using Hyperterminal application (supplied with Windows XP) with the same serial port parameters given above for opening the port. But from the above code snippet, I can open the port and each time it is returning empty data.
I tried opening port using the code given this Stack Overflow thread, still it returns empty data.
Kindly assist me.
I know this is probably old now ... but for future reference ...
Look at the handshaking. There is both hardware handshaking and software handshaking. Your problem could be either - so you need to try both.
For hardware handshaking you can try:
mySerialPort.DtrEnable = True
mySerialPort.RtsEnable = True
Note that
mySerialPort.Handshake = Handshake.RequestToSend
I do not think sets the DTR line which some serial devices might require
Software handshaking is also known as XON/XOFF and can be set with
mySerialPort.Handshake = Handshake.XOnXOff
OR
mySerialPort.Handshake = Handshake.RequestToSendXOnXOff
You may still need to enable DTR
When all else fails - dont forget to check all of these combinations of handshaking.
Since someone else will probably have trouble with this in the future, hand shaking is a selectable option.
In most of the balances you will see the options for Software, Hardware 2 char, Hardware 1 char. The default setting for the Sartorius balances is Hardware 2 Char. I usually recommend changing to Software.
Also if it stops working all together it can often be fixed by defaulting the unit using the 9 1 1 parameter. And then resetting the communication settings.
An example of how to change the settings can be found on the manual on this page:
http://www.dataweigh.com/products/sartorius/cpa-analytical-balances/