Reason for difference in number of reachable states - hardware

I verify an 8-bit adder with this code. When I print the number of reachable states are 1 if the main module is empty and 2^32 if the entire main module is included. What makes this difference in reported number of reachable states? For a 4-bit adder the reported number of reachable states were 2^16. It seems logical that the input states are 2^n if n is the number of bits. Where do all the other states come from? I noticed it is when I add the line a : adder (in1, in2); that the states increase, but that was only experimentally verified that this is what increasese the number of states and not the adder module itself. Why?
MODULE bit-adder (in1, in2, cin)
VAR
sum : boolean;
cout : boolean;
ASSIGN
next (sum) := (in1 xor in2) xor cin;
next (cout) := (in1 & in2) | ((in1 | in2) & cin);
MODULE adder (in1, in2)
VAR
bit0 : bit-adder (in1[0], in2[0], FALSE);
bit1 : bit-adder (in1[1], in2[1], bit0.cout);
bit2 : bit-adder (in1[2], in2[2], bit1.cout);
bit3 : bit-adder (in1[3], in2[3], bit2.cout);
bit4 : bit-adder (in1[4], in2[4], bit3.cout);
bit5 : bit-adder (in1[5], in2[5], bit4.cout);
bit6 : bit-adder (in1[6], in2[6], bit5.cout);
bit7 : bit-adder (in1[7], in2[7], bit6.cout);
DEFINE
sum0 := bit0.sum;
sum1 := bit1.sum;
sum2 := bit2.sum;
sum3 := bit3.sum;
sum4 := bit4.sum;
sum5 := bit5.sum;
sum6 := bit6.sum;
sum7 := bit7.sum;
overflow := bit7.cout;
MODULE main
VAR
in1 : array 0 .. 7 of boolean;
in2 : array 0 .. 7 of boolean;
a : adder (in1, in2);
ASSIGN
next (in1[0]) := in1[0];
next (in1[1]) := in1[1];
next (in1[2]) := in1[2];
next (in1[3]) := in1[3];
next (in1[4]) := in1[4];
next (in1[5]) := in1[5];
next (in1[6]) := in1[6];
next (in1[7]) := in1[7];
next (in2[0]) := in2[0];
next (in2[1]) := in2[1];
next (in2[2]) := in2[2];
next (in2[3]) := in2[3];
next (in2[4]) := in2[4];
next (in2[5]) := in2[5];
next (in2[6]) := in2[6];
next (in2[7]) := in2[7];
DEFINE
op1 := toint (in1[0]) + 2 * toint (in1[1]) + 4 * toint (in1[2]) + 8 * toint
(in1[3]) + 16 * toint (in1[4]) + 32 * toint (in1[5]) + 64 * toint (in1[6]) + 128 * toint
(in1[7]);
op2 := toint (in2[0]) + 2 * toint (in2[1]) + 4 * toint (in2[2]) + 8 * toint
(in2[3]) + 16* toint (in2[4]) + 32 * toint (in2[5]) + 64 * toint (in2[6]) + 128 * toint
(in2[7]);
sum := toint (a.sum0) + 2 * toint (a.sum1) + 4 * toint (a.sum2) + 8 * toint
(a.sum3) +16 * toint (a.sum4) + 32 * toint (a.sum5) + 64 * toint (a.sum6) + 128 * toint
(a.sum7) + 256 * toint (a.overflow);
LTLSPEC F op1 + op2 = sum

Empty Main Module. If you don't include (directly or indirectly) something in the main module, then it is simply ignored. You can think of it like defining a class in C++ and never instantiating/using it anywhere else: it can be optimised away by the compiler without affecting the execution of the system.
8-bit adder.
nuXmv > print_reachable_states
######################################################################
system diameter: 1
reachable states: 4.29497e+09 (2^32) out of 4.29497e+09 (2^32)
######################################################################
This is my take on the example:
Module bit-adder has two boolean variables, both of these are free to take any legal value in the domain of a boolean variable, depending on the specific inputs of the Module (i.e. the values in in1, in2 and cin).
Module adder has eight bit-adder sub-modules and a number of defined fields, which don't really count when the purpose is to estimate the state space. This module does not add any particular constraint on the possible states assumed by the variables in the bit-adders, so the only thing that matters is that by combining eight bit-adders together it has a potential space of 2^16 states.
Module main has one adder module and two 8-bit arrays which model the inputs. These inputs are arbitrarily chosen in the first state and remain fixed forever, so they add 2^16 possible initial states to the system. The adder itself overall has 2^16 reachable states. The combination of both things yields a space of 2^32 states.
Addendum. In the above output, nuXmv warns you that the system diameter is only 1. This is due to the fact that both sum and cout can assume an arbitrary value in the initial state, so for any choice of in1 and in2, there exists at least one initial state in which the values of sum and cout of each bit-adder in the system coincide with the correct sum, without any computation being necessary. This is obviously an unrealistic stretch. A better approach would be to force both sum and cout being initialised to FALSE:
nuXmv > print_reachable_states
######################################################################
system diameter: 9
reachable states: 259539 (2^17.9856) out of 4.29497e+09 (2^32)
######################################################################
You can see that this time around the system diameter has increased to 9. This is obviously due to the fact that in this very simple encoding of a circuit adder the carry-bit is propagated along the diagonal, and each propagation step takes one transition. The number of reachable states has also been reduced thanks to the fact we have discarded some configurations by fixing the values of cout and sum.

Related

How should you calculate partial derivative ∂f/∂x using first the chain rule & directly in MAPLE?

If f(u,v) = vsinu+v^2, u(x,y)=tan^−1􏰀(y􏰁/x), v=sqrt(􏰂x^2 + y^2)
Calculate using chain rule and directly substituting for u(x,y), v(x,y).
Your syntax is not altogether clear to me, but I am guessing you are trying to achieve something like this:
uveqs := [u(x,y)=arctan(y/x), v(x,y)=sqrt(x^2+y^2)]:
f := v(x,y)*sin(u(x,y))+v(x,y)^2:
Differentiate f with respect to x (noticing the effect of the chain-rule),
K := diff(f,x):
diff(v(x,y),x) * sin(u(x,y))
+ v(x,y) * diff(u(x,y),x) * cos(u(x,y))
+ 2*v(x,y) * diff(v(x,y),x)
Now substitute for u(x,y) and v(x,u), and simplify,
S1 := eval(K,uveqs):
simplify(S1);
2 x
Alternatively, first substitute for u(x,y) and v(x,y) into f itself,
fxy := eval(f,uveqs):
(x^2+y^2)^(1/2)*y/x/(1+y^2/x^2)^(1/2)+x^2+y^2
And then differentiate with respect to x, and simplify,
S2 := diff(fxy,x):
simplify(S2);
2 x
If you have trouble understanding the mechanisms, you might also compare these two pairs of operations,
diff( v(x,y), x );
eval( %, uveqs );
and,
eval( v(x,y), uveqs );
diff( %, x );

Difference between 1 and 1'b1 in Verilog

What is the difference between just giving 1 and giving 1'b1 in verilog code?
The 1 is 32 bits wide, thus is the equivalent of 32'b00000000_00000000_00000000_00000001
The 1'b1 is one bit wide.
There are several places where you should be aware of the difference in length but the one most likely to catch you out is in concatenations. {}
reg [ 7:0] A;
reg [ 8:0] B;
assign A = 8'b10100101;
assign B = {1'b1,A}; // B is 9'b110100101
assign B = {1,A}; // B is 9'b110100101
assign B = {A,1'b1}; // B is 9'b101001011
assign B = {A,1}; // B is 9'b000000001 !!!!
So, what's the difference between, say,
logic [7:0] count;
...
count <= count + 1'b1;
and
logic [7:0] count;
...
count <= count + 1;
Not a lot. In the first case your simulator/synthesiser will do this:
i) expand the 1'b1 to 8'b1 (because count is 8 bits wide)
ii) do all the maths using 8 bits (because now everything is 8 bits wide).
In the second case your simulator/synthesiser will do this:
i) do all the maths using 32 bits (because 1 is 32 bits wide)
ii) truncate the 32-bit result to 8 bits wide (because count is 8 bits wide)
The behaviour will be the same. However, that is not always the case. This:
count <= (count * 8'd255) >> 8;
and this:
count <= (count * 255) >> 8;
will behave differently. In the first case, 8 bits will be used for the multiplication (the width of the 8 in the >> 8 is irrelevant) and so the multiplication will overflow; in the second case, 32 bits will be used for the multiplication and so everything will be fine.
1'b1 is an binary, unsigned, 1-bit wide integral value. In the original verilog specification, 1 had the same type as integer. It was signed, but its width was unspecified. A tool could choose the width base on its host implementation of the int type.
Since Verilog 2001 and SystemVerilog 2005, the width of integer and int was fixed at 32-bits. However, because of this original unspecified width, and the fact that so many people write 0 or 1 without realizing that it is now 32-bits wide, the standard does not allow you to use an unbased literal inside a concatenation. {A,1} is illegal.

AMPL adding min max constraints to items in set

I have recently been introduced to AMPL in a class and I am currently working on an optimization problem that requires me to find the minimal cost for the demands required. The actual lines I have in question are these:
1. This is in my model file:
minimize Total_Cost:
sum{i in GENS, j in LOADS} cost[i,j] * Allocate[i,j];
subject to GenConst {i in GENS}:
sum {j in LOADS} Allocate[i,j] <= Generation[i];
subject to DemConst {j in LOADS}:
sum {i in GENS} Allocate [i,j] >= Demand[j];
in my data file:
param: GENS:
GenerationMin GenerationMax := #defines set "GENS" and param "Generation"
GEN1 10 90
GEN2 10 100
GEN3 5 85 ;
We have only ever worked with having problems where our demand=generation, but none with having minimum, maximum along with demand != supply. I get the following error when running my data file within ampl GenerationMin is not a subscripted param . When running this script with only the max value it runs fine. The issue, and I am only guessing, are with the lines above. Could someone explain to me where I am going wrong and how to fix this issue?
EDIT: I can include all of my code, although in case anyone wants to reproduce the problem. .mod file:
set GENS;
set LOADS;
param Generation {GENS} >=0;
param Demand {LOADS} >=0;
param cost {GENS, LOADS} >= 0;
var Allocate {GENS, LOADS} >= 0; #{GEN1, LOAD1}, {GEN1, LOAD2... etc}
minimize Total_Cost:
sum{i in GENS, j in LOADS} cost[i,j] * Allocate[i,j];
subject to GenConst {i in GENS}:
sum {j in LOADS} Allocate[i,j] <= Generation[i];
subject to DemConst {j in LOADS}:
sum {i in GENS} Allocate [i,j] >= Demand[j];
.data file:
data;
param: GENS:
GenerationMin GenerationMax := #defines set "GENS" and param "Generation"
GEN1 10 90
GEN2 10 100
GEN3 5 85 ;
param: LOADS: Demand := #Defining set "LOADS" and param "Demand"
Load1 70
Load2 20
Load3 30
Load4 60;
param cost:
Load1 Load2 Load3 Load4 :=
GEN1 39 14 11 14
GEN2 27 9 12 9
GEN3 24 14 17 13;
option solver cplex;
solve;
display Allocate;
display Allocate, Total_Cost > Output.txt
The correct AMPL syntax is:
set GENS;
param GenerationMin {GENS} >=0;
param GenerationMax {GENS} >=0;
data;
param: GENS:
GenerationMin GenerationMax :=
GEN1 10 90
GEN2 10 100
GEN3 5 85 ;
display GENS,GenerationMin,GenerationMax;
i.e. use both GenerationMin,GenerationMax in the model and in the data section.

VHDL testbench report error

working on a project with a self checking test bench and having a problem I do not understand.
The problem for the following code is an error in the simulation. I will point to where the error is coming from in the code:
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
ENTITY TestBenchAutomated IS
-- Generics passed in
generic (m: integer := 3; n: integer := 5; h: integer := 4; DATA_SIZE: integer :=5);
END TestBenchAutomated;
ARCHITECTURE behavior OF TestBenchAutomated IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT TopLevelM_M
generic (m: integer := 3; n: integer := 5; h: integer := 4; DATA_SIZE: integer :=5);
PORT(
clk : IN std_logic;
next_in : IN std_logic; --User input
rst_in : IN std_logic; --User input
OUTPUT : OUT SIGNED((DATA_SIZE+DATA_SIZE)+(m-1)-1 downto 0) --Calculated DATA output
);
END COMPONENT;
--Inputs
signal clk : std_logic := '0';
signal next_in : std_logic := '0';
signal rst_in : std_logic := '0';
--Outputs
signal OUTPUT : SIGNED((DATA_SIZE+DATA_SIZE)+(m-1)-1 downto 0);
-- Clock period definitions
constant clk_period : time := 10 ns;
--Variable to be used in assert section
type Vector is record
OUTPUT_test : SIGNED((DATA_SIZE+DATA_SIZE)+(m-1)-1 downto 0);
end record;
type VectorArray is array (natural range <>) of Vector;
constant Vectors : VectorArray := (
-- Values to be compaired to calculated output
(OUTPUT_test =>"000000110000"), -- 48
(OUTPUT_test =>"000011110110"), -- 246
(OUTPUT_test =>"000101001000"), -- 382 <--- Purposefully incorrect value, Should be '000100001000' = 264
(OUTPUT_test =>"111111010011"), -- -45
(OUTPUT_test =>"111101001100"), -- -180
(OUTPUT_test =>"111111001111"), -- -49
(OUTPUT_test =>"000000101011"), -- 43 Purposefully incorrect value, Should be '000010101011' = 171
(OUTPUT_test =>"000000010011"), -- 19
(OUTPUT_test =>"111111100101"), -- -27
(OUTPUT_test =>"111110111011"), -- -69
(OUTPUT_test =>"111110111011"), -- -69
(OUTPUT_test =>"000000101101"), -- 45
(OUTPUT_test =>"111011011110"), -- -290
(OUTPUT_test =>"000001010110"), -- 86
(OUTPUT_test =>"000011110010"), -- 242
(OUTPUT_test =>"00000111110"), -- 125
(OUTPUT_test =>"111111001001"), -- -55
(OUTPUT_test =>"000100010101"), -- 277
(OUTPUT_test =>"111111100011"), -- -29
(OUTPUT_test =>"111101111101"));-- -131
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: TopLevelM_M PORT MAP (
clk => clk,
next_in => next_in,
rst_in => rst_in,
OUTPUT => OUTPUT
);
-- Clock process definitions
clk_process :process
begin
clk <= '0';
wait for clk_period/2;
clk <= '1';
wait for clk_period/2;
end process;
-- Process to simulate user input and to check output is correct
Test :process
variable i : integer;
begin
wait for 100 ns;
rst_in <= '1';
wait for clk_period*3;
rst_in <= '0';
--Loops through enough times to cover matrix and more to show it freezes in S_Wait state
for i in 0 to 50 loop
for i in Vectors'range loop
next_in <= '1';
wait for clk_period*5;
next_in <= '0';
wait for clk_period*4; --Appropriate amount of clock cycles needed for calculations to be displayed at output
--Check the output is the same as expected
assert OUTPUT = Vectors(i).OUTPUT_test
report "Incorrect Output on vector line" & integer'image(i) &
lf & "Expected:" & integer'image(i)(to_integer((Vectors(i).OUTPUT_test))) --& lf &
--"But got" & integer'image(i)(to_integer(signed(OUTPUT)))
severity error;
end loop;
end loop;
wait;
end process;
END;
As you can see in the vector, I have inserted two incorrect values to make sure the code works. I there for expect an error in the simulation telling me that there is an error on address 2 of the vector and what integer it is. However, the simulation stops and i get this:
ERROR: Index 328 out of bound 1 to 1.
ERROR: In process TestBenchAutomated.vhd:Test
INFO: Simulator is stopped.
Obviously the integer 328 that is represented by the binary number in the vector causes this error, but I dont understand why it causes THIS error instead of the one I have coded. What is this index out of bound OF?
Any help would be much appreciated.
Thanks
This:
report "Incorrect Output on vector line" & integer'image(i) &
lf & "Expected:" & integer'image(i)(to_integer((Vectors(i).OUTPUT_test)))
Should be:
report "Incorrect Output on vector line" & integer'image(i) &
lf & "Expected:" & integer'image(to_integer((Vectors(i).OUTPUT_test)))
It's complaining that the value (to_integer((Vectors(i).OUTPUT_test))) is out of range for a character when it should have been used as parameter to 'IMAGE, which you supplied already as i.
For a simplified test case:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity foo is
constant m: integer := 3;
constant n: integer := 5;
constant h: integer := 4;
constant DATA_SIZE: integer :=5;
end entity;
architecture fum of foo is
signal OUTPUT : SIGNED((DATA_SIZE+DATA_SIZE)+(m-1)-1 downto 0) := "000011110110" ;
type Vector is record
OUTPUT_test : SIGNED((DATA_SIZE+DATA_SIZE)+(m-1)-1 downto 0);
end record;
type VectorArray is array (natural range <>) of Vector;
constant Vectors : VectorArray := (
-- Values to be compaired to calculated output
(OUTPUT_test =>"000011110110"), -- 246 (CORRECT)
(OUTPUT_test =>"000101001000") -- 382 (INCORRECT)
);
begin
TEST:
process
begin
for i in Vectors'RANGE loop
assert OUTPUT = Vectors(i).OUTPUT_test
report "Incorrect Output on vector line " & integer'image(i) &
-- lf & "Expected:" & integer'image(i)(to_integer((Vectors(i).OUTPUT_test)))
lf & "Expected:" & integer'image(to_integer((Vectors(i).OUTPUT_test)))
severity error;
end loop;
wait;
end process;
end architecture;
And the incorrect usage, Nick Gasson's nvc gave:
david_koontz#Macbook: nvc -a foo.vhdl
** Error: expected 2 parameters for attribute IMAGE but have 3
File foo.vhdl, Line 34
lf & "Expected:" & integer'image(i)(to_integer((Vectors(i).OUTPUT_t ...
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
With the correct number of arguments to `'IMAGE' (shown in the example):
david_koontz#Macbook: nvc -r foo
** Fatal: 0ms+0: Assertion Error: Incorrect Output on vector line 1
Expected:328
Process :foo:test
File foo.vhdl, Line 32
Found a ghdl bug not reporting this when it likely should. It worked either way (this should be a run time error). An integer value of 382 isn't a character eligible for concatenation.
Addendum:
Tristan Gingold (ghdl author) pointed out that the expression is an element index to the string output of the 'IMAGE function.
Further analysis reveals the basis for the error message on the original code for the question:
& integer'image(i)(to_integer((Vectors(i).OUTPUT_test)))
T'IMAGE(X)
Kind: Function.
Prefix: Any scalar type or subtype T.
Parameter: An expression whose type is the base type of T.
Result Type: Type String.
Result: The string representation of the parameter value, without
leading or trailing whitespace.
No concatenation operator following.
(to_integer( ( Vectors(i).OUTPUT ) ) ) returns the integer value for the record element OUTPUT, type signed. (superfluous parentheses aside).
The contents of Vectors(i).OUTPUT is
constant Vectors : VectorArray := (
(OUTPUT_test =>"000011110110"), -- 246 (CORRECT)
(OUTPUT_test =>"000101001000") -- 382 (INCORRECT)
);
The 382 should be 328, its 0x148. Dyslexia is hard to spell.
And in this case for i = 1 (Vectors'RANGE is (0 to 1), is
"000101001000" which to_integer is 328, out of range for an element of a string (element type character).
An integer, value 328 or not is not an element index type for a record (while OUTPUT is).
The subtype for the unnamed string output of 'IMAGE is the length of the string for i, whose value is 1, the length is 1, the range is 1 to 1. 328 is out of range.
Notice the ISIM message said exactly that in the original model:
ERROR: Index 328 out of bound 1 to 1. ERROR: In process TestBenchAutomated.vhd:Test
This still looks like a ghdl error. It does also make nvc's error message suspect however.

MathProg (AMPL) - Variable Array Sized by Another Variable

I am writing my first GNU MathProg (AMPL) program to find the minimum switch (vertex) count instances of a HyperX topology (graph) for a given radix, number of hosts, and bisection bandwidth. This is a simple first program because all of the equations have been described in the following paper: http://cal.snu.ac.kr/files/2009.sc.hyperx.pdf
I have read the specification and example programs, but I am stuck on a very simple syntax error. I need to have the following two variables: L, the number of dimensions in the network, and an array S of length L, where each element of S is the number of switches in each dimension. In my MathProg program, I express this as:
var L >= 1, integer;
var S{1 .. L} >= 2, integer;
However, when I run $ glpsol --check --math hyperx.mod, I get the following error:
hyperx.mod:28: operand following .. has invalid type
Context: ...isec ; param radix ; var L >= 1 , integer ; var S { 1 .. L }
If anybody can help explain how I should properly express this relationship, I will be grateful. Also, I am including the entire program I have written for reference and extra help. I expect there to be many syntax errors in my program, but until I fix the first one, I have no way of finding the rest.
/*
* A MathProg linear program to find an optimal HyperX topology of a
* given network size, switch radix, and bisection bandwidth. Optimal
* is simplistically defined as minimum switch count network.
*
* A HyperX topology is a multi-dimensional network (graph) where, in
* each dimension, the switches are fully connected. Every switch
* (vertex) is a point in an L-dimensional integer lattic. Each switch
* is identified by a multi-index I = (I_1, ..., I_L) where 0 <= I_k <
* S_k for each k = 1..L, where S_k is the number of switches in each
* dimension. A switch connects to all others whose multi-index is the
* same in all but one coordinate.
*/
/* Network size in number of hosts. */
param hosts;
/* Desired bisection bandwidth. */
param bisec;
/* Maximum switch radix. */
param radix;
/* The number of dimensions in the HyperX. */
var L >= 1, integer;
/* The number of switches in each dimension. */
var S{1 .. L} >= 2, integer;
/*
* Relative bandwidth of the dimension, i.e., the number of links in a
* given dimension.
*/
var K{1 .. L} >= 1, integer;
/* The number Terminals (hosts) per switch */
var T >= 1, integer;
/* Minimize the total number of switches. */
minimize cost: prod{i in 1..L} S[i];
/* The total number of links must be less than the switch radix. */
s.t. Radix: T + sum{i in 1..L} K[i] * (S[i] - 1) <= radix;
/* There must be enough hosts in the network. */
s.t. Hosts: T * prod{i in 1..L} S[i] >= hosts;
/* There must be enough bandwidth. */
s.t. Bandwidth: min{K[i]*S[i]} / (2 * T) >= bisec;
/* The order of the dimensions doesn't matter, so constrain them */
s.t. SwitchDimen: forall{i in 1..(L-1)} S[i] <= S[i+1];
/*
* Bisection bandwidth depends on the smallest S_i * K_i, so we know
* that the smallest switch count dimension needs the most links.
*/
s.t. LinkDimen: forall{i in 1..(L-1)} K[i] >= K[i+1];
# TODO: I would like to constrain the search such that the number of
# terminals, T, is bounded to T >= (hosts / O), where O is the switch
# count of the smallest switch count topology discovered so far, but I
# don't know how to do this.
/* Data section */
data;
param hosts := 32
param bisec := 0.5
param radix := 64
end;
Fixed number of variables in a problem is a common assumption in solvers and algebraic modelling languages including AMPL/MathProg. Therefore you can only use constant expressions, in particular parameters, not variables in indexing expressions. One possible solution is to make L a parameter, resolve your problem for different values of L and select the one that gives the best objective value. This can be done with a simple AMPL script.