Not 100% sure what you mean by "dominating net types", but I think you can look back at previous postings of mine and it might be clear that you can work that out from the type conversions available. I.e. if you look at all the drivers of a "collapsed net" then (in general, inc. AMS) you do the resolution by working out what type/domain you can convert all drivers to losslessly and has a resolution function. The "dominant type" does not have to be explicity assigned to the net, so your "nettype" declarations as described below are redundant and error-prone.
The flavor of wreal driver (summing etc.) should be defined at the module level and not above, if you try to do it above then you run into the problem of what happens when you try to assert a different nettype at a higher level when the block gets re-included - it would just be a semantic mess (worse than defparam), and works against your desire to pre-compile modules.
Kev.
> 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
>
-- This message has been scanned for viruses and dangerous content by MailScanner, and is believed to be clean.Received on Sat Jan 29 00:24:45 2011
This archive was generated by hypermail 2.1.8 : Sat Jan 29 2011 - 00:24:46 PST