unknown_ifb Imported from Blogger
Getting these to work sometimes feels like an exercise in self-torture. The most elegant constraints are rarely supported by either LRM or the tools. Even so, every time you do one of these, I always try to come up with my own solution.
I rarely (never? ) come up with something better, but I think this time I got an elegant one…
-
We can represent required edges in a matrix m_edges[v1][v2], where m_edges[v1][v2] == 1 if there’s an edge between v1 and v2.
-
We can represent the drawing path using r_vertex[EDGES] array, where pencil starts on r_vertex[0], moves to r_vertex[1], etc.
-
Then, the constraint is to say that for each r_vertex[i], r_vertex[i-1] pair, we must have m_edges[r_vertex[i]][r_vertex[i-1]]==1.
-
The only thing missing now is the uniqueness. This is where I use a 3-D matrix r_edges[v1][v2][i] to represent whether step ‘i’ has drawn edge v1-v2 or not. With that available, we can then say that for each m_edges[v1][v2] == 1, we must have a one-hot {r_edges[v1][v2], r_edges[v2][v1]} (accounting for either direction).
Code: (it’s hard to read, blogger doesn’t allow code or pre tags in comments)
class drawer#(VERTICES=5,EDGES=8);
bit[VERTICES-1:0][VERTICES-1:0] m_edges;
rand byte unsigned r_vertex[EDGES:0];
rand bit[VERTICES-1:0][VERTICES-1:0][EDGES:0] r_edges;
constraint c_edges {
foreach(r_edges[v1, v2, i]) {
r_vertex[i] < VERTICES;
(i > 0) && (r_vertex[i] == v2) && (r_vertex[i-1] == v1) →
r_edges[v1][v2][i-1] == 1 &&
m_edges[v1][v2] | m_edges[v2][v1] == 1;
m_edges[v1][v2] → $onehot({r_edges[v1][v2], r_edges[v2][v1]});
}
}
endclass
This works with VCS and Questa. VCS is a bit slow at it… It speeds up quite a bit if we explicitly set r_edges to 0 when they are not drawn on, but I was going for the least amount of constraint code :).
I think Incisive still doesn't support $onehot in a constraint, but one could write a function to replace it.