Simulating simple System verilog mailbox code using ModelSim - system-verilog

I am new to system verilog and was trying a basic mailbox code using Modelsim Student Version. I was able to compile the code successfully and simulate it but i am not getting the expected result. There is a for loop inside the put and get tasks but the loop is not getting executed.
Foll is the code :
// simple mailbox //
module mailbox_new();
mailbox my_mailbox;
initial begin
my_mailbox =new();
if(my_mailbox)
begin
fork
put_packets();
get_packets();
#1000;
join_any
end
#1000;
$display("END OF PROGRAM");
end
task put_packets();
integer i;
begin
for(i=0;i<10;i++);
begin
#10;
my_mailbox.put(i);
$display("Done putting packet %d #time %d",i, $time);
end
end
endtask
task get_packets();
integer j;
begin
for(j=0;j<10;j++);
begin
#10;
my_mailbox.get(j);
$display("Done getting packet %d #time %d",j, $time);
end
end
endtask
endmodule
// end of code /////
the result being displayed is :
# Done putting packet 10 #time 10
# Done getting packet 10 #time 10
# END OF PROGRAM
That is my for loop is not getting executed properly. Can you pls help me on this. Whether its a coding issue or a tool issue

There are multiple things wrong with your code, but the most obvious one is that you put a semicolon ; after the for statements. This means you'll loop and not do anything and then execute the begin...end block. Remove the extra ;s and you should be fine.

Related

UVM end of test

In case I want to end the simulation from my monitor (I know that it is not the recommended way) how can I do this?
lets say I got this code inside my monitor:
Virtual task monitor_run();
fork
forever begin
.....
end
forever begin
.....
end
forever begin
.....
end
join
endtask : monitor_run
Every forever loop check that outputs of the DUT came on time, in case they doesnt it should stop simulation.
This special monitor should break the simulation in case of mismatch(error) and there is no Scoreboard.
I still want to manage nice end of simulation behaviour. I tried use raise and drop objection but I get an error of OBJT_ZERO sometimes. Does anyone knows a good way to end the simulation in that case?
thanks!
The UVM is set up by default so that uvm_report_fatal ends the test immediately, and uvm_report_error lets the simulation continue until hitting an error limit that you can set. And you can control the actions of each severity for an individual component. See uvm_report_object which is the base class of uvm_component.
Upon ending the test, the UVM calls uvm_report_server::report_summarize() that dumps out all the severity counts. If you insist, you can create a final block in your testbench module that gathers the severity counts from the report server and print the last message. For example:
module top;
initial run_test();
uvm_report_server rs = uvm_report_server::get_server();
final if (rs.get_severity_count(UVM_FATAL) != 0 ||
rs.get_severity_count(UVM_ERROR) !=0 )
$display("Test Failed");
endmodule
But this is really unnecessary and may not catch other non-UVM errors like assertion failures or timing checks. Many tools have a TESTSTATUS exit code that reports the most severe message encounte, UVM or tool.

Delphi - open form on the second monitor

I need help with this solution.
There is application with several forms. One of this forms need to be opened on selected monitor. For example:
Solution 1. OnCreate form cheks if there are more than one monitor used, and open on the last one. I try this code, but with no luck:
Application.CreateForm(TfrmDashboard, frmDashboard);
for I := 0 to Screen.MonitorCount -1 do
begin
// Checking Screen Position
ShowMessageFmt('%d, %d, %d, %d',
[Screen.Monitors[i].BoundsRect.Left,
Screen.Monitors[i].BoundsRect.Top,
Screen.Monitors[i].BoundsRect.Right,
Screen.Monitors[i].BoundsRect.Bottom]);
end;
if Screen.MonitorCount > 1 then
begin
frmDashboard.Top:= Screen.Monitors[i].BoundsRect.Top;
frmDashboard.Top:= Screen.Monitors[i].BoundsRect.Left;
end;
Solution 2. Form is dragged to the selected monitor and OnDestroy event Top and Left position are written to the INI file. Next time form opens on the same monitor and same position. I try this code, but also with no luck:
procedure TfrmDashboard.FormCreate(Sender: TObject);
var
ini: TIniFile;
begin
ini:= TIniFile.Create(extractfilepath(paramstr(0))+'Dashboard.ini');
Left:= StrToInt(ini.ReadString('Left', 'Form_Left', '0'));
Top:= StrToInt(ini.ReadString('Top', 'Form_Top', '0'));
ini.Free;
end;
procedure TfrmDashboard.FormDestroy(Sender: TObject);
var
ini: TIniFile;
begin
ini:= TIniFile.Create(extractfilepath(paramstr(0))+'Dashboard.ini');
ini.WriteString('Left', 'Form_Left', IntToStr(Left));
ini.WriteString('Top', 'Form_Top', IntToStr(Top));
ini.Free;
end;
frmDashboard.Top:= ...
frmDashboard.Top:= ...
This appears to be a simple copy paste error. You set Top both times. Presumably you mean:
frmDashboard.Top:= ...
frmDashboard.Left:= ...
This code makes the same mistake:
if Screen.MonitorCount > 1 then
begin
frmDashboard.Top:= Screen.Monitors[i].BoundsRect.Top;
frmDashboard.Top:= Screen.Monitors[i].BoundsRect.Left;
end;
Furthermore, it refers to i when it is ill-defined. The compiler will warn about this. I hope you have compiler warnings and hints enabled, and do take heed of them.
Your OnCreate event handler will raise an exception if the INI file contains invalid data. For instance, if the user edits the position values to be non-numeric, then StrToInt will raise an exception. Your program should be resilient to that.
Both the OnCreate and OnDestroy event handlers don't manage the lifetime of the INI file object correctly. If the INI file access fails, or the calls to StrToInt fail (see above) then you will leak the object. This is the pattern to be followed:
obj := TMyObject.Create;
try
// do things with obj
finally
obj.Free;
end;

inout signal doesn't change in simulation

Let's say I have an entity called "HostToDevice" which has a "ps2c" inout signal (VHDL). In this entity I only set this signal to 'Z' (high impedance) because I want an other entity to control it.
I created a test bench to check the behavior and something strange (for me) happens. In the test bench I have this code:
ps2ctemp_process :process
begin
ps2ctemp <= '0';
wait for ps2c_period/2;
ps2ctemp <= '1';
wait for ps2c_period/2;
end process;
And after:
stim_proc: process
begin
ps2c <= ps2ctemp;
wait;
end process;
When I run the simulation (behavioral) the "ps2c" inout signal is just low and doesn't change like ps2ctemp signal does.
Instead if I drive manually the ps2c signal without using another signal it works fine; like this:
ps2c <= '1';
wait for 10 ns;
ps2c <= '0';
wait for 10 ns;
ps2c <= '1';
Your "stim_proc" has no sensitivity list, and one "wait" without event or timeout, so it is intended to run once and wait forever. This seems to be what the sim is doing, so, good.
Now I'll make a wild guess here, that you actually want it to wake up every time ps2ctemp changes, and pass on the new value to ps2c.
There are two ways to do that:
(1) with a sensitivity list
stim_proc: process(psc2temp)
begin
ps2c <= ps2ctemp;
--wait;
-- no, we want the process to complete, so it can be woken up
-- and run from the start again
end process;
(2) with a wait for a specific event...
stim_proc: process
begin
ps2c <= ps2ctemp;
wait until ps2ctemp'event;
-- any activity at all on ps2ctemp should wake this process,
-- in case there is something it ought to be doing...
end process;
In this simple case, these two forms are essentially equivalent. So the simpler one (sensitivity list) is to be preferred...

How to restart matlab script from where it left off?

I have a matlab script which executes 5 algorithm sequentially. All these 5 algorithms needs to run for 10 different initialization.
Whenever there is an error in i-th initialization, the script exit with an error message. I fix the issue(say, data issue) and start running the script again which executes from the first initialization.
I dont want to my code to run for previously executed initialization. ( from 1 run to i-1 the run)
One way is to reassign the value of index to start from i, which in turn require to modify the scrip everytime again and again.
Is there any way to restart the script from the i-th initialization onwards which dont require to modify the script?
I suggest that you use try and catch, and check which indexes succeeded.
function errorIndexes = myScript(indexes)
errorIndexes = [];
errors = {};
for i = indexes
try
%Do something
catch me
errorIndexes(end+1) = i;
errors{end+1} = me;
end
end
end
On the outside you should have a main file like that:
function RunMyScript()
if exist('unRunIndexes.mat','file')
unRunIndexes= load('unRunIndexes.mat');
else
unRunIndexes= 1:n;
end
unRunIndexes= myScript( indexes)
save('unRunIndexes.mat',unRunIndexes);
end
Another technique you might like to consider is checkpointing. I've used something similar with long-running (more than one day) loops operating in an environment where the machine could become unavailable at any time, e.g. distributed clusters of spare machines in a lab.
Basically, you check to see if a 'checkpoint' file exists before you start your loop. If it does than that suggests the loop did not finish successfully last time. It contains information on where the loop got up to as well as any other state that you need to get going again.
Here's a simplified example:
function myFunction()
numIter = 10;
startIter = 1;
checkpointFilename = 'checkpoint.mat';
% Check for presence of checkpoint file suggesting the last run did not
% complete
if exist(checkpointFilename, 'file')
s = load(checkpointFilename);
startIter = s.i;
fprintf('Restarting from iteration %d\n', startIter);
end
for i = startIter:numIter
fprintf('Starting iteration %d\n', i);
expensiveComputation();
save(checkpointFilename, 'i');
end
% We succefully finished. Let's delete our checkpoint file
delete(checkpointFilename);
function expensiveComputation()
% Pretend to do lots of work!
pause(1);
end
end
Running and breaking out with ctrl-c part way through looks like this:
>> myFunction
Starting iteration 1
Starting iteration 2
Starting iteration 3
Starting iteration 4
Operation terminated by user during myFunction/expensiveComputation (line 27)
In myFunction (line 18)
expensiveComputation();
>> myFunction
Restarting from iteration 4
Starting iteration 4
Starting iteration 5
...
You can type (in the command line):
for iter=l:n,
%%% copy - paste your code inside the loop
end

Controlling a matlab script (Pause, Reset)

I am trying to create a matlab script (m-file) which shall be controlled by an external VBA script.
The matlab script shall do the same operation every time (even params change, but this is not the matter in this case) for a certain number of loops.
If I see it right, I can use matlab funktions in VBA like this: http://www.mathworks.de/help/techdoc/matlab_external/f135590.html#f133975
My main problem is how to implement the matlab part of this problem...at the moment my control part looks like this:
start.m:
run = 1;
reset = 0;
while run ~= 0 % Loop until external reset of 'run' to '0'
if reset ~= 0
doReset(); % Reset the parameters for the processing
reset = 0;
disp('I did a reset');
end
disp('I am processing');
doProcess();
pause(1)
end
disp('I am done');
The reset part works very fine while changing the value by the script, but when I manually try to change the value of 'run' or 'reset' to any other value in my workspace, nothing happens...my script doen't abort, neither does the reset-if do it's work...
this seems to me that the script doesn't recognize any changes in the workspace?!
later the variables 'run' and 'reset' shall be set or unset by the VBA script.
Is there any plausible reason why I can't abort the loop by hand?
Thanks for any advice!
greets, poeschlorn
Edit:
It seems that the script loads the variables once before starting and never again during runtime...is there a possibility to have explicit access to a workspace variable?
Edit 2:
I use Matlab 2010b with no additional Toolboxes at the moment
Edit 3:
I found out, that there are several 'workspaces' or RAMs in Matlab. If my function is running, the variables are stored in 'base' (?) workspace, which is not the matlab workspace on which you can click and change every value. So I have to get access to this ominous 'base' space and change the flag 'run' to zero.
I assume your problem is simply that your loop is blocking execution of the external interface. While the loop runs you cannot access the other interfaces.
I wanted to do a similar thing -- allow control of a matlab loop by an external program (either Ruby or another matlab instance). The most flexible solution by far was using UDP. There is a great toolbox called PNET for matlab, and I assume VB must have a socket library too. I simply open a UDP port on both sides, and use simple text commands to control and give feedback.
obj.conn = pnet('udpsocket', 9999);
command = '';
while run ~= 0
nBytes = pnet(obj.conn, 'readpacket');
if nBytes > 0
command = pnet(obj.conn, 'read', nBytes, 'string');
end
switch command
case '--reset--'
doReset(); % Reset the parameters for the processing
reset = 0;
disp('I did a reset');
case '--abort--'
run = 0;
disp('Going to abort');
case '--echo--'
pnet(obj.conn, 'write', '--echo--');
pnet(obj.conn, 'writepacket', remoteAddress, remotePort);
end
doProcess();
end
This way I can build my own extensible control interface without worrying about blocking from the loop, it can work cross-platform and cross-language, can work within a machine or across the network.
UPDATE:
To talk between two UDP clients, you need to set up two complimentary UDP ports, both are clients (this example is all in matlab, pretend obj here is a structure, in my case it is a class i wrap around the pnet functionality):
obj = struct();
obj.success = 0;
obj.client1Port = 9999;
obj.client2Port = 9998;
obj.client1Address = '127.0.0.1';
obj.client2Address = '127.0.0.1';
obj.conn1 = pnet('udpsocket', obj.client1Port);
obj.conn2 = pnet('udpsocket', obj.client2Port);
pnet(obj.conn1, 'write', '--echo--')
pnet(obj.conn1, 'writepacket', obj.client2Address, obj.client2Port);
nBytes = pnet(obj.conn2, 'readpacket');
if nBytes > 0
command = pnet(obj.conn2, 'read', nBytes, 'string');
if regexpi(command,'--echo--')
obj.success = obj.success+1;
fprintf('Client 2 recieved this message: %s\n',command);
pnet(obj.conn2, 'write', '--echo--')
pnet(obj.conn2, 'writepacket', obj.client1Address, obj.client1Port);
end
end
nBytes = pnet(obj.conn1, 'readpacket');
if nBytes > 0
command = pnet(obj.conn1, 'read', nBytes, 'string');
if regexpi(command,'--echo--')
obj.success = obj.success+1;
fprintf('Client 1 got this back: %s\n',command);
end
end
if obj.success == 2
fprintf('\nWe both sent and received messages!\n');
end
Is your script a script m-file or a function?
If it's a function, you'll be losing the scope of the workspace variables which is why it's not working. I'd turn your code into a function like this:
function processRun(run,reset)
while run ~= 0 % Loop until external reset of 'run' to '0'
if reset ~= 0
doReset; % Reset the parameters for the processing
reset = 0;
disp('I did a reset');
end
disp('I am processing');
[run,reset] = doProcess;
pause(1)
end
You can then set the values of run and reset evertime you call the function from VBA.
If you have a script, try removing the run and reset lines from the top, and set their values in the workspace before you run the script. I think you're overwriting your workspace values by running the script file.
Sorry, I don't have enough rep to make a comment so I'll quote it here:
#Adam Leadbetter: Thanks, this makes sense. The only thing I habe trouble with is how to pause (after this reset and then resume) the script when it has been started by run=1 as param... – poeschlorn Feb 25 at 7:17
If you want to break out of the loop once reset has been set to one, and then wait for the loop to continue again once run = 1 that is pretty much the same as just starting over again?
function processRun()
run = 1;
while run ~= 1
run = doProcess();
end
if doProcess() returns 0 then the function processRun() will end (like the behaviour you want to have when reset), the next time processRun is called it starts over, with "reset"/default values.
Or am I missing something?