Sorry for the length of this. Needed a bunch of space to
give some semi-detailed examples...
On 1/28/2011 1:33 PM, Kevin Cameron wrote:
> Might I suggest that it would be a good exercise to determine how one
> would define the existing SV/Verilog type semantics as a user-defined
> type rather than he loosely defined built-in types? I.e. if you can
> express how the current stuff works (cleanly) in user-level terms it
> should be more obvious how to do the extensions.
This is a very good suggestion. Let me take a shot at describing what
can and can't be done given where I think there is alignment between
the vendors. Then I'll give an example of roughly what I am aiming for
with resolution function associations.
First, let me start by saying that we really can't mimic SV within any of
the current directions due to the rules regarding "dominating net types".
One way in which to view the dominating net types rules is that they
really don't define a dominating *type* (in the sense of the value
domains of the nets) but rather simply define an set of rules for
determining how to pick a resolution function when connecting nets
with different resolution rules. So, for example, an external "wand"
and internal "wire" picks the external resolution rule for the net
(causing the entire net to act as a "wand" net). In the case of a
supply0 and wand connection, you can view the selected resolution
function as just returning a "supply0" value.
Now I know that the above may not map to either implementations
nor everyone's view of how things work, but it is a useful description
for explaining what we aren't planning on doing.
A related problem in describing things is that SV has so deeply connected
the *value* domain with the resolution that there is no *type* that
defines a "wire value" (ie. admits ambiguous strengths) independently of
a "net type" that includes a resolution function. So I'm going to use
"wire_t" to denote such a value.
Given that, to have a "wand" net by itself is easy. Here is some syntax
that would likely be one approximation:
function wire_t wand_res(input wire_t v[]);
wire_t res = 'z;
foreach(v[i]) res &= v[i]; // assuming a ambiguous strength "&"
endfunction
nettype wire_t wand use wand_res;
Now it is reasonably easy to see that assignments by "wire_t" values
would be Ok. But what would the "dominating net rules" be? There
really couldn't be anything inferred. So either we'd have to extend the
language to allow for the description of how to select the "winning"
resolution function or we'd have to require that the "nettype" of any
connection would match (be the same type).
The latter is the direction in which all the discussion has gone. That
is really just a degenerate case of dominating net rules -- match
or error. As such, I am fine with that (for the conceivable future).
Now on to a description of what I'd like to be able to describe.
I'll give two examples -- one based on a description of a "wreal" like
type, and one based on a value pair with an encoding of what is
being driven.
In both, I am going to suggest some flexibility that I'd like to see
in terms of segregating the "value" from the resolution function.
Francoise has already given a brief description of the package based
approach that Cadence has been suggesting (where you recompile
all code using the type when changing the resolution).
Ex 1 -- wreal
package wreal_pkg;
// This defines an unresolved real valued nettype which is
// compatible with the Verilog-AMS approved standard
nettype real wreal;
function real sum_res(input real v[]); ... endfunction
function real min_res(input real v[]); ... endfunction
function real max_res(input real v[]); ... endfunction
endpackage
---------- separate IP library -----------
import wreal_pkg::*;
module some_ip1a(inout wreal w);
endmodule
module some_ip1b(inout wreal w);
endmodule
---------- separate IP library -----------
import wreal_pkg::*;
module some_ip2a(inout wreal w);
endmodule
module some_ip2b(inout wreal w);
endmodule
---------- separate IP library -----------
import wreal_pkg::*;
nettype wreal wreal_sum use sum_res;
module some_ip3a(inout wreal_sum w);
endmodule
module some_ip2b(inout wreal_sum w);
endmodule
------------------------------------------------
module top;
import wreal_pkg::*;
parameter CONFIG = 0;
wreal w1;
wreal w2;
some_ip1a ip1a(w1);
some_ip1b ip1b(w1);
some_ip2a ip2a(w2);
some_ip2b ip2b(w2);
if (CONFIG == 1) begin // generate if
nettype wreal use min_res; // use "min" for all
wreal nets
end
else if (CONFIG == 2) begin
nettype use min_res for top.w1; // use min for
topology w1
nettype use max_res for top.w1; // use max for
topology w2
end
else if (CONFIG == 3) begin
nettype use min_res for top.w1; // use min for w1
// w2 is unresolved (no multiple drivers)
end
end module
I've chosen in the above to use a generate -- you could obviously also just
have separate "top" modules and/or configs to control aspects of this.
The point here is that the IP blocks have a choice about how "tight" they
need to have their resolution function bound.
In ip1 & ip2, I used just "wreal" and let the TB define the resolution (by
configuration) either globally or per sub-design. In ip3, I have a
requirement
that any instantiation of the blocks would be required to use a wreal net
with the "sum" resolution function. So a TB using just "wreal" would be
fine (children define the resolution) or a TB using another wreal associated
with "sum" would also be fine.
One side note for the detailed readers -- if you used a "global" resolution
binding as in (CONFIG==1) that would imply a conflict with IP block 3.
I agree it would as I've described things; I'd be very open to having
some rules about what "overrules" what. I don't think it would need to
be terribly complex.
The key point is that there is local "tight" coupling of type and resolution
*when necessary* and more flexible determination when it isn't necessary.
Since all of the types still match, I see very little difficulty in
doing the
resolution function association in this "lazy" manner -- and I think this
approach "plays well" with the kinds of things that AMS does and will
be a good bridge to the ideas of generic interconnect description (which
decouples type and resolution function from the topology).
Ex 2 -- pair of reals and partial drives
I am running out of steam a bit here so I'm going to avoid anything with
implied analog meaning and just stick with a trivial basic idea. If someone
wants to take a shot at making this meaningful in analog, that might
be good...
package pair_package;
// am I driving only one of p1 or p2 or driving both
typedef enum { P1_DRIVE, P2_DRIVE, P12_DRIVE } DriveStyle;
typedef struct { real p1, p2; DriveStyle style; } pair_val;
nettype pair_val pair_net;
function pair_val sum_p1_only (input pair_val v[]);
pair_val res = '{ 0.0, 0.0, P1_DRIVE};
foreach (v[i]) begin
if (v[i].style != P1_DRIVE) begin
// handle error case
end
else begin
res.p1 += v[i].p1;
end
end
return res;
endfunction
function pair_val prefer_p1 (input pair_val v[]);
pair_val res = '{ 0.0, 0.0, P1_DRIVE};
foreach (v[i]) begin
if (v[i].style == P2_DRIVE) begin
res.p1 += v[i].p2;
end
else begin
res.p1 += v[i].p1;
end
end
return res;
endfunction
endpackage
import pair_package::*;
module top;
pair_net w1; // unresolved
pair_net w2;
nettype use sum_p1_only for w2;
nettype pair_val pair_p1 use prefer_p1;
pair_p1 w3;
assign w1 = pair_val'{1.0, 2.0, P12_DRIVE};
// error to have a second drive
// "p2" values are ignored in the resolution
// resulting value on w2 is '{2.5, 0.0, P1_DRIVE}
assign w2 = pair_val'{1.0, 2.0, P1_DRIVE};
assign w2 = pair_val'{1.5, 2.0, P1_DRIVE};
// resulting value on w2 is '{3.0, 0.0, P1_DRIVE}
assign w2 = pair_val'{1.0, 2.0, P1_DRIVE};
assign w2 = pair_val'{1.5, 2.0, P2_DRIVE};
endmodule
The above is very simplistic of course. But hopefully a bunch of the
core ideas are reasonable clear.
Gord
-- -------------------------------------------------------------------- Gordon Vreugdenhil 503-685-0808 Model Technology (Mentor Graphics) gordonv@model.com -- This message has been scanned for viruses and dangerous content by MailScanner, and is believed to be clean.Received on Fri Jan 28 21:39:01 2011
This archive was generated by hypermail 2.1.8 : Fri Jan 28 2011 - 21:39:03 PST