How to resolve design.sv:1 : syntax error on the EDA playground for the sillyfunction taken from Digital Design And Computer Architecture? - system-verilog

For understanding SystemVerilog, I have been writing the codes on the Digital Design And the Computer Architecture. So, I wrote the first example and the testbench in the book.
Design
module sillyfunction(input logic a,b,c,
output logic y);
assign y = ~a & ~b & ~c |
a & ~b & ~c |
a & ~b & c;
endmodule
Testbench
module testbench();
input a, b, c;
output y;
sillyfunction dut(a,b,c,y);
initial begin
$dumpfile("file.vcd");
$dumpvars(1);
a = 0; b = 0; c = 0;
#10
c = 1;
#10
b = 1; c = 0;
#10
c = 1;
#10
a = 1; b = 0; c = 0;
#10
c = 1;
#10
b = 1; c = 0;
#10
c = 1;
end
endmodule
The problem is I have encountered the error:
[2021-10-30 14:44:15 EDT] iverilog '-Wall' design.sv testbench.sv && unbuffer vvp a.out
design.sv:1: syntax error
I give up.
Exit code expected: 0, received: 1
Done
I tried to debug it with the changing the input and output variables to reg and wire which has no effect. I also tried to
$dumpvars(1) to $dumvars(0)
Which has no effects on the bug.
How can I resolve the bug?

I also see that error when I run your code on an old version of iverilog on edaplayground. I suspect the version you used only supports the old Verilog standard, but does not have much support for SystemVerilog features; hence, the vague syntax error message. It probably did not recognize the logic keyword, which is specific to SystemVerilog.
You should switch to the latest version there (Icarus Verilog 0.10.0), which has better SystemVerilog support. You will get a different message, but I didn't find that to be very helpful either.
But, switching to another simulator, like Cadence, produces a more helpful message:
input a, b, c;
|
xmvlog: *E,NOPORT (testbench.sv,10|8): input/output/inout 'a' not declared in port list [12.3.2(IEEE)].
Here is the link: edaplayground.
Typically, you don't need ports on a testbench since it is usually the top-level module. Using reg and wire, as you mentioned is one way to fix the error. Another way is to change:
input a, b, c;
output y;
to:
logic a, b, c;
logic y;

Icarus Verilog (aka iverilog) version 0.9.* do not support SysmteVerilog. Version 0.10.* does support a limited subset of SystemVerilog features with the compiler flag -g2012. Note the Compile Options in the image from EDA playground
In your testbench, change:
input a, b, c;
output y;
to:
logic a, b, c; // could also be 'reg' type
wire y; // could also be 'logic' type

The problem seems to be with the port declaration style you have followed for the module testbench.
This is a non-ANSI port declaration style and System-verilog discusses on this under the LRM standard section, 23.2.2.1 Non-ANSI style port declarations. To get this working, you will have to change
module testbench(); -> module testbench(a,b,c,y);
Next, ports a,b,c and y are wires. A wire cannot be assigned like "a = 1;". So you can change a wire to a variable by :
input a, b, c; output y; -> input var a, b, c; output var y;

Related

System Verilog inside operator operands bit length

How "inside" sub-expressions bit lengths are supposed to be computed in System Verilog?
It appears that the type of an expression depends on whether an operand is a numeric literal or a variable.
The following System Verilog program:
`define M( x ) $display( `"x -- %b`", x )
module top ();
bit [3:0] a, b;
initial begin
// (a+b) could be evaluated either to 0 or 16, depending on the bit length of the expression.
a = 15;
b = 1;
`M(4'd1 inside { [(a+b):17] } ); // 0
`M(4'd1);
`M( b inside { [(a+b):17] } ); // 1
`M( b);
end
endmodule
outputs:
Chronologic VCS simulator copyright 1991-2019
Contains Synopsys proprietary information.
Compiler version P-2019.06-SP1-1_Full64; Runtime version P-2019.06-SP1-1_Full64; May 8 20:27 2020
4'd1 inside { [(a+b):17] } -- 0
4'd1 -- 0001
b inside { [(a+b):17] } -- 1
b -- 0001
V C S S i m u l a t i o n R e p o r t
Time: 0
CPU Time: 0.250 seconds; Data structure size: 0.0Mb
Fri May 8 20:27:08 2020
PS: Verific interprets the standard differently from Synopsys.
It's definitely a tool bug that it produces different results for two different operands of the same value and width.
However, the correct answer is slightly ambiguous because the inside operator was left out of Table 11-21—Bit lengths resulting from self-determined expressions in the IEEE 1800-2017 LRM. This is a reported issue for the LRM, and the consensus is that is should behave the same as the case inside statement in that all operands get sized to the largest size operand before doing any comparisons. In this example, the literal 17 is 32-bits wide and has the largest width. So the result of the inside operator should be 1'b0.

Chisel UInt negative value error

I have recently started work in scala, and am required to create an implementation of MD5. It is my understanding that MD5 requires unsigned types, which scala does not come with. As I will soon begin Chisel, which does have unsigned types, I decided to implement its library. Everything appears good so far, except when doing the below bitwise operations, my F value becomes -271733879, which causes an error "Caused by: java.lang.IllegalArgumentException: requirement failed: UInt literal -271733879 is negative" as UInts can't be negative.
if(i<16){
F = ((B & C) | ((~B) & D))
g = i
}
There is more to the error message, but it is just the trace list of different libraries and classes that had an error because of this error, and thus I did not post it because I didn't think it was important. If it was, I can edit this and post it all.
My B, C, and D values are equal to the lower case equivalents listed below, and it is the first time through the for loop so they have not yet updated.
var a0 : UInt = UInt(0x67452301)
var b0 : UInt = UInt(0xefcdab89)
var c0 : UInt = UInt(0x98badcfe)
var d0 : UInt = UInt(0x10325476)
Any Help would be greatly appreciated.
For the sake of my answer, I am using the Chisel 3 preferred 123.U style for specifying literals rather than the Chisel 2 UInt(123) style, but this answer works for either.
There are several ways you could do this:
Use Scala Long (put L at end of literal)
val myUInt = 0x98badcfeL.U
This obviously won't work for larger than 64-bit
Use Scala BigInt
val myUInt = BigInt("98badcfe", 16).U
Use Chisel's shorthand for constructing BigInts from Strings
val myUInt = "x98badcfe".U
hex = x | h, dec = d, oct = o, bin = b

How to access generate block elements hierarchically

Consider code in SV interface:
genvar i;
generate
for (i = 0; i < 2; i++) begin : g1
task ab ();
///< something here
endtask
end
endgenerate
According to LRM 1800-2012 section 27.6 I should technically be able to access this task by (consider in monitor vif is a virtual instance of interface):
vif.g1[i].ab();
Is this correct? If yes then simulators have issue supporting it since it reports vif.g1 can't be found (elaboration time)
I've tried it without named block as well it just suppose to be:
vif.genblk1[i].ab();
but no luck.
What is the issue here? I think monitor or any other classes have handles created run time, however interface still should be static time compiled and all elements of interface should be available.
You cannot use a variable inside the []'s to reference the task.
A generate loop gets flattened out at elaboration before simulation starts. So you would need to call the task with
vif.g1[0].ab;
Here is a complete self contained example. Please try posting your questions with the same.
interface itf;
for (genvar ii = 0; ii < 2; ii++) begin : g1
task ab ();
$display("%m");
endtask // ab
end : g1
endinterface : itf
module top;
itf i1();
virtual itf vif;
initial begin
vif = i1;
vif.g1[0].ab;
end
endmodule : top

How do you join several input wires into one wire in systemverilog (all wires except one hi-Z)

Suppose that all input wires except one is supposed to be in Hi-Z. We want to connect these wires into a single wire (e.g. data bus). How can this be done in SystemVerilog?
If you mean module inputs, the alias construct can do this:
module a(input wire a,b,c);
wire bus; // use if you want a different internal name
alias a = b = c = bus;
endmodule
I'm sure this will not be synthesizable.
Assuming your condition that only one input is not Z holds true then we could just loop through and find the last non-Z input and assign its value to the output. No idea if this would synthesize.
module merge_bus
#(parameter BUSW = 8)
(
input [BUSW-1:0] bus_in,
output wire_out
);
always_comb begin
wire_out = 1'bz;
for(int i = 0; i<BUSW; i++) begin
if(bus_in[i] !== 1'bz) wire_out = bus_in[i];
end
end
endmodule
You can make use of wor/wand data types from verilog.

How to compile Matlab class into C lib?

The origin of this question is from here How to use "global static" variable in matlab function called in c.
I'm trying to encapsulate the "global variable" into an object. However I don't know how to export the matlab class to c++ using MATLAB Compiler (mcc)
To do this I just tried the standard command
Matlab Command
mcc -W cpplib:Vowel4 -T link:lib Vowel4.m
Matlab Script
classdef Vowel4
properties
x
y
end
methods
Vowel4
A
B
end
end
The generated lib is actually stand-alone functions rather than c++ class.
How can I compile classes in Matlab into c++ classes?
I've been searching for an answer but didn't find one.
Obviously the matlab command is not suitable for this scenario. However I cannot find any information on building Matlab classes into c++ classes.
========================== Edit ========================
The actual cpp code is as follows: #Alan
mclInitializeApplication(NULL, 0);
loadDataInitialize();
soundByCoefInitialize();
loadData();
mwArray F(4, 1, mxDOUBLE_CLASS);
float test[4];
for ( ;; ){
const Frame frame = controller.frame();
const FingerList fingers = frame.fingers();
if ( !fingers.empty() ){
for ( int i = 0; i < 4; i ++ ){
double v = fingers.count() > i ? (fingers[i].tipPosition().y / 50) - 2 : 0;
F(i+1,1) = v;
test[i] = v;
cout << v << ' ';
}
cout << endl;
soundByCoef(F);
}
}
Here the matlabA() corresponds to the loadData(), which loads the data, and soundByCoef(F) corresponds to the matlabB(), which do the job in the main loop.
As noted by Alan, I was only suggesting using handle class as a container for your global variables (with the benefit that such an object would be passed by reference). The created object is not intended to be directly manipulated by your C++ code (it will be stored in the generic mxArray/mwArray C/C++ struct).
As far as I know, you cannot directly compile classdef-style MATLAB classes into proper C++ classes when building shared libraries using the MATLAB Compiler. It only supports building regular functions. You could create functional interfaces to MATLAB class member methods, but that's a different story...
Perhaps a complete example would help illustrate the idea I had in mind. First lets define the code on the MATLAB side:
GlobalData.m
This is the handle class used to store the global vars.
classdef GlobalData < handle
%GLOBALDATA Handle class to encapsulate all global state data.
%
% Note that we are not taking advantage of any object-oriented programming
% concept in this code. This class acts only as a container for publicly
% accessible properties for the otherwise global variables.
%
% To manipulate these globals from C++, you should create the class API
% as normal MATLAB functions to be compiled and exposed as regular C
% functions by the shared library.
% For example: create(), get(), set(), ...
%
% The reason we use a handle-class instead of regular variables/structs
% is that handle-class objects get passed by reference.
%
properties
val
end
end
create_globals.m
A wrapper function that acts as a constructor to the above class
function globals = create_globals()
%CREATE_GLOBALS Instantiate and return global state
globals = GlobalData();
globals.val = 2;
end
fcn_add.m, fcn_times.m
MATLAB functions to be exposed as C++ functions
function out = fcn_add(globals, in)
% receives array, and return "input+val" (where val is global)
out = in + globals.val;
end
function out = fcn_times(globals, in)
% receives array, and return "input*val" (where val is global)
out = in .* globals.val;
end
With the above files stored in current directory, lets build the C++ shared library using the MATLAB Compiler:
>> mkdir out
>> mcc -W cpplib:libfoo -T link:lib -N -v -d ./out create_globals.m fcn_add.m fcn_times.m
You should expect the following generated files among others (I'm on a Windows machine):
./out/libfoo.h
./out/libfoo.dll
./out/libfoo.lib
Next, we could create a sample C++ program to test the library:
main.cpp
// Sample program that calls a C++ shared library created using
// the MATLAB Compiler.
#include <iostream>
using namespace std;
// include library header generated by MATLAB Compiler
#include "libfoo.h"
int run_main(int argc, char **argv)
{
// initialize MCR
if (!mclInitializeApplication(NULL,0)) {
cerr << "Failed to init MCR" << endl;
return -1;
}
// initialize our library
if( !libfooInitialize() ) {
cerr << "Failed to init library" << endl;
return -1;
}
try {
// create global variables
mwArray globals;
create_globals(1, globals);
// create input array
double data[] = {1,2,3,4,5,6,7,8,9};
mwArray in(3, 3, mxDOUBLE_CLASS, mxREAL);
in.SetData(data, 9);
// create output array, and call library functions
mwArray out;
fcn_add(1, out, globals, in);
cout << "Added matrix:\n" << out << endl;
fcn_times(1, out, globals, in);
cout << "Multiplied matrix:\n" << out << endl;
} catch (const mwException& e) {
cerr << e.what() << endl;
return -1;
} catch (...) {
cerr << "Unexpected error thrown" << endl;
return -1;
}
// destruct our library
libfooTerminate();
// shutdown MCR
mclTerminateApplication();
return 0;
}
int main()
{
mclmcrInitialize();
return mclRunMain((mclMainFcnType)run_main, 0, NULL);
}
Lets build the standalone program:
>> mbuild -I./out main.cpp ./out/libfoo.lib -outdir ./out
And finally run the executable:
>> cd out
>> !main
Added matrix:
3 6 9
4 7 10
5 8 11
Multiplied matrix:
2 8 14
4 10 16
6 12 18
HTH
Following on from the thread in the previous post, the suggestion wasn't to wrap your functions in a class, but rather to use a class to pass about the global variable which compiling leaves you unable to use.
classdef Foo < handle
properties
value
end
methods
function obj = Foo(value)
obj.value = value;
end
end
end
Note: the class Foo extends the handle class in order to make it pass by reference, rather than pass by value. See: the comparison between handle and value classes.
function foo = matlabA()
foo = new Foo(1);
end
function matlabB(foo)
foo.value
end
As far as I know, the matlab compiler doesn't compile the code as such, but rather packages it with a copy of the MATLAB Component Runtime and writes some wrapper functions to handle invoking said runtime on the code from c/c++.
I would recommend avoiding jumping back and forth between matlab and c/c++ too much; there is bound to be some overhead to converting the datatypes and invoking the MCR. All I really use it for is wrapping up a complex but self-contained matlab script (i.e.: doesn't need to interact with the c/c++ code mid way through said script) as a function, or packaging up code for deployment to environments which don't have a full copy of matlab.
As an interesting side note: if you are calling C++ from within Matlab, and that C++ code needs access to a global variable, things are much easier. You can simply do this by wrapping your C++ code into a mexFunction and compiling that. In the places you need to access a variable which is in the Matlab workspace, you can do so using the mexGetVariablePtr which will return a read-only pointer to the data. The variable you are accessing can be in either the global workspace, or that of the function which called your mexFunction.
With this approach I would suggest liberally comment the variable that you are getting in both the C++ and Matlab code, as the link between them may not be obvious from the Matlab side; you wouldn't want someone to come along later, edit the script and wonder why it had broken.
In this case it seems that the C++ side doesn't really need access to the data, so you could refactor it to have matlab do the calling by wrapping the "get current position of fingers" code into a mexFunction, then have matlab do the loop:
data = loadData();
while(~stop) {
position = getFingerPositionMex();
soundByCoef(position, data);
}
Assuming you don't modify the data within soundByCoef Matlab will use pass by reference, so there will be no copying of the large dataset.