I have a graph in a form of an adjacency list. I want to draw it vertically and specify the root to be AA. I want to order the nodes in the levels by their BFS distance from the node AA (so in this case AA is on lavel 0 alone, JW HX MA KO are on level 1 etc...). How do I do that? Is there any automatic way? I don't want to specify levels manually by {rank=same; JW; HX; MA; KO;}...
The graph is below:
strict graph {
NV -- {ZV CG YB HX OY};
NU -- {DA MA OA DK};
VU -- {PS FX};
JW -- {AA MD};
RI -- {OY DG};
DG -- {TG RI DF EV KW};
PH -- {KW OW LT LZ};
KZ -- {ET QV CK MS};
IX -- {TS DO};
MS -- {LZ KZ};
IL -- {DO ET};
EJ -- {AV JY};
DK -- {NU CG};
YB -- {NV PS};
OA -- {YA NU};
DA -- {NU RG};
KO -- {AA TG};
RG -- {DF DA ZV MD LB};
MA -- {AA NU};
OW -- {DO PH};
KW -- {DG PH};
DO -- {IX IL CZ OW};
DF -- {RG DG};
TG -- {DG KO};
LB -- {RG FX};
HX -- {AA NV};
GB -- {AV XK};
CG -- {DK NV};
LT -- {AO PH};
FX -- {LB HY VU};
ET -- {IL KZ};
CK -- {UX KZ};
LZ -- {PH MS};
YA -- {JY OA};
TS -- {NO IX};
NO -- {TS};
XK -- {GB};
PS -- {EV VU YB};
AA -- {JW HX MA KO};
MD -- {JW RG};
JM -- {QV HY AO};
AV -- {EJ GB};
AO -- {JM LT};
JY -- {YA EJ};
OY -- {NV RI};
UX -- {CZ CK};
HY -- {JM FX};
EV -- {PS DG};
CZ -- {UX DO};
ZV -- {NV RG};
QV -- {JM KZ};
}
Unfortunately, dot on its own can't produce the graph you want. Dot's ranking algorithm is (almost) based on longest path instead of shortest path.
However, the Graphviz system also includes the dijkstra program (http://www.graphviz.org/pdf/dijkstra.1.pdf) that will annotate a graph with a distance attribute an a previous node attribute (along the shortest path) (Although the dijkstra algorithm differs from the BFS algorithm, I expect the results to be the same.)
As dot does not allow explicitly setting ranks (except for source and sink, some extra coding is needed to:
create subgraphs for the rank=same groupings
identify the "top" node - rank=source
set constraint=false on most edges (bidirectional graph causes dot to confuse ranks
set constraint=true on those edges that comprise shortest paths
The programming is done in gvpr (http://www.graphviz.org/pdf/gvpr.1.pdf), also included in the Graphviz package.
The gvpr program shortestPath.gvpr:
E{
$.constraint="false"; // default to false
}
BEG_G{
graph_t SG;
node_t aNode;
edge_t anEdge;
int D, oD, i, cnt;
float Df;
string tmpStr, pref="__addedSubg__";
string sameRank[], tok[int];
}
N{
if (hasAttr($, "dist") && $.dist!=""){
Df=(float)$.dist;
D=(int)Df; // convert to integer
$.Dist=D;
sameRank[D]=sprintf("%s %s", sameRank[D], $.name);
//print("// dist ", $.name, " ", $.dist, " ", D, " ", sameRank[D]);
if (hasAttr($, "prev") && $.prev!=""){
aNode=node($G, $.prev);
anEdge=edge(aNode, $, "");
// anEdge.constraint="true";
}
}
}
BEG_G{
}
N{
if (hasAttr($, "prev") && $.prev!=""){
aNode=node($G, $.prev);
if ($.Dist==aNode.Dist+1){
anEdge=edge(aNode, $, "");
anEdge.constraint="true";
}
}
}
END_G{
for (sameRank[D]){
print("// D SAME ", D, " ", sameRank[D]);
tmpStr=sprintf("%s%i", pref, D);
SG=subg($G, tmpStr);
if (D==0)
SG.rank="source";
else
SG.rank="same";
unset(tok);
cnt=tokens(sameRank[D], tok);
for (tok[i]){
aNode=node($G, tok[i]);
subnode(SG, aNode);
}
}
}
And a (Linux) command line of:
dijkstra -p AA autoRank0.gv|gvpr -c -f shortestPath.gvpr|dot -Tpng >oo.png
Giving:
I'm trying to draw a tree but have a problem with the following approach:
Use of 'invisible' nodes to connect levels of tree,
Use 'rank same' to draw nodes on the same level
Using this code I get following result
graph G{
edge [arrowhead = none];
splines = ortho;
rankdir = LR;
node [ shape="box" fixedsize = true width = 4 height = 1];
{ rank = same; "C" }
{ rank = same;
"B"
"A"
}
{ rank = same;
"F"
"D"
"E"
}
node [ shape="cricle" width = 0 height = 0 style=invis];
{ rank = same;
"B_Inv_Parent_1"
"C_Inv_Even_Children_0"
"A_Inv_Parent_1"
}
{ rank = same;
"F_Inv_Parent_2"
"D_Inv_Parent_2"
"A_Inv_Even_Children_1"
"E_Inv_Parent_2"
}
"C" -- "C_Inv_Even_Children_0";
"B_Inv_Parent_1" -- "C_Inv_Even_Children_0" -- "A_Inv_Parent_1";
"B_Inv_Parent_1" -- "B";
"A_Inv_Parent_1" -- "A";
"B" -- "F_Inv_Parent_2";
"F_Inv_Parent_2" -- "F";
"A" -- "A_Inv_Even_Children_1";
"D_Inv_Parent_2" -- "A_Inv_Even_Children_1" -- "E_Inv_Parent_2";
"D_Inv_Parent_2" -- "D";
"E_Inv_Parent_2" -- "E";
}
I have a problem in the 3rd level: D is drawn on top of the picture thus making a connection with E not ideal.
I would like to have the same results as with C, B and A.
I think the problem is with the order of nodes definition however, I can't manage to get it working whatever order I define them in.
Can anyone spot another problem with my code and suggest a fix?
I have cleaned up your code and re-arranged a few lines - after all, I think that introducing
F_Inv_Parent_2 -- D_Inv_Parent_2 -- A_Inv_Even_Children_1 -- E_Inv_Parent_2;
has been the key. You don't need to define edge arrows since you don't have a directed graph, and there is a typo in shape="cricle".
Here my edited version
graph G
{
splines = ortho;
rankdir = LR;
// node definitions
node [ shape="box" fixedsize = true width = 4 height = 1];
C
{ rank = same; B A }
{ rank = same; F D E }
node [ shape="point" width = 0 height = 0 ];
{ rank = same;
B_Inv_Parent_1
C_Inv_Even_Children_0
A_Inv_Parent_1 }
{ rank = same;
F_Inv_Parent_2
D_Inv_Parent_2
A_Inv_Even_Children_1
E_Inv_Parent_2 }
// edges
C -- C_Inv_Even_Children_0;
B_Inv_Parent_1 -- C_Inv_Even_Children_0 -- A_Inv_Parent_1;
B_Inv_Parent_1 -- B -- F_Inv_Parent_2;
A_Inv_Parent_1 -- A -- A_Inv_Even_Children_1;
F_Inv_Parent_2 -- D_Inv_Parent_2 -- A_Inv_Even_Children_1 -- E_Inv_Parent_2;
F_Inv_Parent_2 -- F;
D_Inv_Parent_2 -- D;
E_Inv_Parent_2 -- E;
}
and the result:
EDIT: I may have misunderstood your intention how you want to connect the third level - if so, replace
F_Inv_Parent_2 -- D_Inv_Parent_2 -- A_Inv_Even_Children_1 -- E_Inv_Parent_2;
with
F_Inv_Parent_2 -- D_Inv_Parent_2[ style = invis ];
D_Inv_Parent_2 -- A_Inv_Even_Children_1 -- E_Inv_Parent_2;
which gives you
EDIT No. 2, in response to yr comment:
Adding weight to the edge helps straightening it - I give the full code even though only two lines have changed (plus comments), for easier copy & paste:
graph G
{
splines = ortho;
rankdir = LR;
// node definitions
node [ shape="box" fixedsize = true width = 4 height = 1];
C
{ rank = same; B A }
{ rank = same; F D E }
node [ shape="point" width = 0 height = 0 ];
{ rank = same;
B_Inv_Parent_1
C_Inv_Even_Children_0
A_Inv_Parent_1 }
{ rank = same;
F_Inv_Parent_2
D_Inv_Parent_2
A_Inv_Even_Children_1
E_Inv_Parent_2 }
// edges
C -- C_Inv_Even_Children_0;
B_Inv_Parent_1 -- C_Inv_Even_Children_0 -- A_Inv_Parent_1;
// add extra weight to the continouous connection between four levels:
B_Inv_Parent_1 -- B -- F_Inv_Parent_2 -- F[ weight = 10 ];
// no weight here:
A_Inv_Parent_1 -- A -- A_Inv_Even_Children_1;
F_Inv_Parent_2 -- D_Inv_Parent_2[ style = invis ];
D_Inv_Parent_2 -- A_Inv_Even_Children_1 -- E_Inv_Parent_2;
// F_Inv_Parent_2 -- F; ### moved
D_Inv_Parent_2 -- D;
E_Inv_Parent_2 -- E;
}
Which gives you the disired straight line from B via F_Inv_Parent_2 to F which is actually the grandchild:
How does the following translates into hardware? If I have multiple same equation assigning it to a different register, how does it translate? Say I have
reg [31:0] A;
reg [31:0] B;
reg [31:0] C;
reg [31:0] D;
function [31:0] foo;
reg [31:0] x, y ,z;
// do something
endfunction
always#(posedge clk)
.
.
.
A <= (B <<< 50) + (C ^ D | A) + A;
B <= C + A + B;
C <= foo((B <<< 50) + (C ^ D | A) + A, C + A + B, C <<< 30)
.
.
.
Would I have two combination blocks (4 blocks total) of
(B <<< 50) + (C ^ D | A) + A
and
C + A + B
or would I only have one of each (2 blocks) wiring out the results into A, B, C, and foo? If the compiler makes two of those logic each, is there a way to ensure only one of each is made, and those two combinational logic wires to multiple registers?
As noted by #mcleod_ideafix, it will often depend on the compiler/synthesis tool. Some are better than others at seeing the repeated logic:
(B <<< 50) + (C ^ D | A) + A;
and
C + A + B;
What you should do is write your code to explicitly call these operations out as their own bus and then re-use that named bus inside the expressions. This will clearly show the synthesis tool that your non-blocking statements contain logic that already exists within the design. This will also make it easier to debug in simulation, since you can now easily drop temp1 and temp2 onto your waveform viewer. It is definitely longer, since it adds two lines of code. But it makes your code clearer, easier to understand, and it is more likely to provide the smaller area result that you want. Below is an example:
reg [31:0] A;
reg [31:0] B;
reg [31:0] C;
reg [31:0] D;
function [31:0] foo;
reg [31:0] x, y ,z;
// do something
endfunction
wire [31:0] temp1 = (B <<< 50) + (C ^ D | A) + A;
wire [31:0] temp2 = C + A + B;
always#(posedge clk)
.
.
.
A <= temp1;
B <= temp2;
C <= foo(temp1, temp2, C <<< 30)
.
.
.
Here's my verilog code about add and shift multiplying
when I compile and Initialze and adding the inputs and outputs to get waveforms and simulating them, I dont see any results, everything is z... what is the problem?
module multi(a, b, ans);
input [3:0] a;
input [3:0] b;
output reg [15:0] ans;
reg [15:0] aa;
reg [15:0] bb;
reg [15:0] tmp=0;
reg flag = 1'b1;
always #( a, b)
begin
aa = a;
bb = b;
while ( flag == 1'b1 )
begin
if( bb[0] == 1'b1 )
tmp = tmp + aa;
aa = aa << 1;
bb = bb >> 1;
if ( bb==0 )
flag = 1'b0;
end
ans = tmp;
end
endmodule
There are a number of things that look strange with this code.
First is that you have no clock input, but are attempting to do everything with combinatorial logic.
Second is that setting flag to 1 in the reg statement will mean that your module is only capable of doing a single multiplication. By the way, it is more normal (especially for ASIC design) to use a reset signal than use this initialisation in a reg line.
Third is that a 4 bit number times a 4 bit number will result in an 8bit answer, not 16bit.
In any case, unless you are working at very high speeds you should be able to perform a multiply in a single cycle.
Here are a couple of ways of writing this code more naturally:
Combinatorial Style
module multi(a, b, ans);
input [3:0] a;
input [3:0] b;
output reg [7:0] ans;
always #(*)
begin
ans = a * b;
end
endmodule
Clocked style
module multi(clk, a, b, ans);
input [3:0] a;
input [3:0] b;
output reg [7:0] ans;
always #(posedge clk)
begin
ans <= a * b;
end
endmodule
Your input is 4 bits wide and your assigning to a 16 bit variable, the top 12 bits are unassigned ie x.
input [3:0] a;
reg [15:0] aa;
//...
aa = a;
To assign all bits of aa try some thing like:
aa = {12'b0, a};
//{} is bit concatenation
Or to sign extend a to 16 bits, repeat the MSB 12 times using {width{value}} replication:
aa = {{12{a[3]}}, a};
I'm studying Verilog and here's my first ALU.
I can't understand why the output does not display in the tester block.
Sample outputs(scroll horizontally):
FAIL: a=00010010000101010011010100100100, b=11000000100010010101111010000001, op=101, z=zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz, expect=11010010100111010111111110100101
FAIL: a=10000100100001001101011000001001, b=10110001111100000101011001100011, op=101, z=zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz, expect=10110101111101001101011001101011
Why isn't z calculated?
ALU
module yAlu(z, ex, a, b, op);
input [31:0] a, b;
input [2:0] op;
output[31:0] z;
output ex;
wire [31:0] andRes, orRes, arithmRes, slt;
wire cout;
assign slt = 0; // not supported
assign ex = 0; // not supported
and myand[31:0] (andRes, a, b);
or myor[31:0](orRes, a, b);
//Instantiating yArith adder/subtractor from addSub.v
yArith addSub(arithmRes, cout, a, b, op[2]);
//Instantiating 4-to-1 32-bit multiplexor from 4to1Mux.v
yMux4to1 multiplexor(z, andRes, orRes, arithmRes, slt, op[1:0]);
endmodule
MULTIPLEXORS:
// 1-bit 2 to 1 selector
module yMux1(z, a, b, c);
output z;
input a, b, c;
wire notC, upper, lower;
not my_not(notC, c);
and upperAnd(upper, a, notC);
and lowerAnd(lower, c, b);
or my_or(z, upper, lower);
endmodule
//--------------------------------------------
// n-bit 2 to 1 selector
module yMux(z, a, b, c);
parameter SIZE = 2;
output [SIZE-1:0] z;
input [SIZE-1:0] a, b;
input c;
yMux1 mine[SIZE-1:0] (z, a, b, c);
endmodule
//--------------------------------------------
// n-bit 4-to-1 multiplexor
module yMux4to1(z, a0, a1, a2, a3, c);
parameter SIZE = 32;
output [SIZE-1:0] z;
input [SIZE-1:0] a0, a1, a2, a3;
input [1:0] c;
wire [SIZE-1:0] zLo, zHi;
yMux #(.SIZE(32)) lo(zLo, a0, a1, c[0]);
yMux #(.SIZE(32)) hi(zLo, a2, a3, c[0]);
yMux #(.SIZE(32)) final(zLo, zLo, zHi, c[1]);
// c in array is important (see LabL4.v page)
endmodule
//----------------------------------------------
ADDER/SUBTRACTOR BLOCK:
// A simple 1-bit full adder
module yAdder1(z, cout, a, b, cin);
output z, cout;
input a, b, cin;
xor left_xor(tmp, a, b);
xor right_xor(z, cin, tmp);
and left_and(outL, a, b);
and right_and(outR, tmp, cin);
or my_or(cout, outR, outL);
endmodule
//----------------------------------------------
// 32-bit adder with 1 bit carry
module yAdder(z, cout, a, b, cin);
output [31:0] z;
output cout;
input [31:0] a, b;
input cin;
wire [31:0] in, out;
yAdder1 adder[31:0](z, out, a, b, in);
assign in[0] = cin;
assign in[1] = out[0];
assign in[2] = out[1];
assign in[3] = out[2];
assign in[4] = out[3];
assign in[5] = out[4];
assign in[6] = out[5];
assign in[7] = out[6];
assign in[8] = out[7];
assign in[9] = out[8];
assign in[10] = out[9];
assign in[11] = out[10];
assign in[12] = out[11];
assign in[13] = out[12];
assign in[14] = out[13];
assign in[15] = out[14];
assign in[16] = out[15];
assign in[17] = out[16];
assign in[18] = out[17];
assign in[19] = out[18];
assign in[20] = out[19];
assign in[21] = out[20];
assign in[22] = out[21];
assign in[23] = out[22];
assign in[24] = out[23];
assign in[25] = out[24];
assign in[26] = out[25];
assign in[27] = out[26];
assign in[28] = out[27];
assign in[29] = out[28];
assign in[30] = out[29];
assign in[31] = out[30];
assign cout = out[31];
endmodule
//----------------------------------------------
// Arithmetic module. Adds if ctrl = 0, subtracts if ctrl = 1
module yArith(z, cout, a, b, ctrl);
output [31:0] z;
output cout;
input [31:0] a, b;
input ctrl;
wire [31:0] notB, tmp;
wire cin;
assign notB = ~b;
assign cin = ctrl;
yMux #(.SIZE(32)) mux(tmp, b, notB, ctrl);
yAdder adderSubtractor(z, cout, a, tmp, cin);
endmodule
//----------------------------------------------
TESTER:
module labL;
reg [31:0] a, b;
reg [31:0] expect;
reg [2:0] op;
wire ex;
wire[31:0] z;
reg ok, flag;
yAlu mine(z, ex, a, b, op);
initial
begin
repeat(10)
begin
a = $random;
b = $random;
op = 3'b101;
//flag = $value$plusargs("op=%d", op);
#10;
// ERROR CASE
if (op === 3'b011)
$display("Error!");
else if (op === 3'b111)
$display("Error!");
// ARITHM CASE
else if(op === 3'b010)
expect = a + b;
else if(op === 3'b110)
expect = a + ~b + 1;
// AND CASE
else if(op === 3'b000)
expect = a & b;
else if (op === 3'b100)
expect = a & b;
// OR CASE
else if (op === 3'b001)
expect = a | b;
else if (op === 3'b101)
expect = a | b;
// DONE WITH CASES;
#5;
if (expect === z)
$display("PASS: a=%b, b=%b, op=%b, z=%b", a, b, op, z, ex);
else
$display("FAIL: a=%b, b=%b, op=%b, z=%b, expect=%b", a, b, op, z, expect);
end
$finish;
end
endmodule
Your yMux4to1 does not drive the z output, so that's why you see 'zzz' as the output.
This means undriven/high-impedance.
You should be able to use a waveform viewer/simulator to trace your outputs (much better than using print statements).
You are getting a high-impedance signal out on Z. This means that your output Z is not driven. You should step through your design in simulation and put traces on your control signals and Z. Your IDE should support this. You most likely do not have the design wired up correctly so it's important to check your datapath and make sure all inputs/outputs are properly connected.