Generate XNF RAMS from synthesized memories.

This commit is contained in:
steve 1999-12-05 19:30:42 +00:00
parent 3e2bb85f58
commit 09de918198
5 changed files with 109 additions and 19 deletions

View File

@ -273,13 +273,6 @@ current state of support for Verilog.
- Min/Typ/Max expressions: Example: a = (1 : 6 : 14);
- Memories work, but only in procedural code.
reg [1:0] b [2:0], bar;
wire [1:0] foo;
always foo = b[i]; // sorry
always @(i) bar = b[i]; // OK
- `timescale directive
- force/release/assign/deassign procedural assignments not
@ -295,19 +288,14 @@ current state of support for Verilog.
- fork/join is not supported in vvm runtime
- Structural shift operators are in general not supported.
Procedural expressions are OK. Constant expressions are OK.
assign foo = a << b; // sorry
always @(a or b) foo = a << b; // OK
parameter foo = a << b; // OK
- Functions in structural contexts are not supported.
assign foo = user_function(a,b); // sorry
always @(a or b) foo = user_function(a,b); // OK
- multiplicative operators (*, /, %) are not supported.
- multiplicative operators (*, /, %) are not supported in
general. They do work if the compiler can evaluate them at compile
time.
assign foo = a * b; // sorry
always @(a or b) foo = a * b; // sorry

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: netlist.cc,v 1.98 1999/12/05 02:24:09 steve Exp $"
#ident "$Id: netlist.cc,v 1.99 1999/12/05 19:30:43 steve Exp $"
#endif
# include <cassert>
@ -1093,6 +1093,15 @@ const NetMemory* NetRamDq::mem() const
return mem_;
}
unsigned NetRamDq::count_partners() const
{
unsigned count = 0;
for (NetRamDq*cur = mem_->ram_list_ ; cur ; cur = cur->next_)
count += 1;
return count;
}
void NetRamDq::absorb_partners()
{
NetRamDq*cur, *tmp;
@ -2725,6 +2734,9 @@ NetNet* Design::find_signal(bool (*func)(const NetNet*))
/*
* $Log: netlist.cc,v $
* Revision 1.99 1999/12/05 19:30:43 steve
* Generate XNF RAMS from synthesized memories.
*
* Revision 1.98 1999/12/05 02:24:09 steve
* Synthesize LPM_RAM_DQ for writes into memories.
*

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: netlist.h,v 1.98 1999/12/05 02:24:09 steve Exp $"
#ident "$Id: netlist.h,v 1.99 1999/12/05 19:30:43 steve Exp $"
#endif
/*
@ -569,6 +569,10 @@ class NetRamDq : public NetNode {
// connections.
void absorb_partners();
// Use this method to count the partners (including myself)
// that are ports to the attached memory.
unsigned count_partners() const;
private:
NetMemory*mem_;
NetRamDq*next_;
@ -2062,6 +2066,9 @@ extern ostream& operator << (ostream&, NetNet::Type);
/*
* $Log: netlist.h,v $
* Revision 1.99 1999/12/05 19:30:43 steve
* Generate XNF RAMS from synthesized memories.
*
* Revision 1.98 1999/12/05 02:24:09 steve
* Synthesize LPM_RAM_DQ for writes into memories.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: t-xnf.cc,v 1.18 1999/11/19 03:02:25 steve Exp $"
#ident "$Id: t-xnf.cc,v 1.19 1999/12/05 19:30:43 steve Exp $"
#endif
/* XNF BACKEND
@ -77,11 +77,13 @@ class target_xnf : public target_t {
public:
void start_design(ostream&os, const Design*);
void end_design(ostream&os, const Design*);
void memory(ostream&os, const NetMemory*);
void signal(ostream&os, const NetNet*);
void lpm_add_sub(ostream&os, const NetAddSub*);
void lpm_ff(ostream&os, const NetFF*);
void lpm_mux(ostream&os, const NetMux*);
void lpm_ram_dq(ostream&os, const NetRamDq*);
void net_const(ostream&os, const NetConst*);
void logic(ostream&os, const NetLogic*);
@ -295,6 +297,14 @@ void scrape_pad_info(string str, char&dir, unsigned&num)
num = val;
}
/*
* Memories are handled by the lpm_ram_dq method, so there is nothing
* to do here.
*/
void target_xnf::memory(ostream&, const NetMemory*)
{
}
/*
* Look for signals that have attributes that are pertinent to XNF
* files. The most obvious are those that have the PAD attribute.
@ -545,6 +555,30 @@ void target_xnf::lpm_mux(ostream&os, const NetMux*net)
}
void target_xnf::lpm_ram_dq(ostream&os, const NetRamDq*ram)
{
assert(ram->count_partners() == 1);
const NetMemory*mem = ram->mem();
for (unsigned idx = 0 ; idx < ram->width() ; idx += 1) {
os << "SYM, " << mangle(ram->name())
<< "<" << idx << ">, RAMS" << endl;
draw_pin(os, "O", ram->pin_Q(idx));
draw_pin(os, "D", ram->pin_Data(idx));
draw_pin(os, "WE", ram->pin_WE());
draw_pin(os, "WCLK", ram->pin_InClock());
for (unsigned adr = 0 ; adr < ram->awidth() ; adr += 1) {
strstream tmp;
tmp << "A" << adr << ends;
draw_pin(os, tmp.str(), ram->pin_Address(adr));
}
os << "END" << endl;
}
}
void target_xnf::net_const(ostream&os, const NetConst*c)
{
verinum::V v=c->value();
@ -653,6 +687,9 @@ extern const struct target tgt_xnf = { "xnf", &target_xnf_obj };
/*
* $Log: t-xnf.cc,v $
* Revision 1.19 1999/12/05 19:30:43 steve
* Generate XNF RAMS from synthesized memories.
*
* Revision 1.18 1999/11/19 03:02:25 steve
* Detect flip-flops connected to opads and turn
* them into OUTFF devices. Inprove support for

48
xnf.txt
View File

@ -65,7 +65,50 @@ programmer really knows how the pins of the XNF device are to be
connected. It also bypasses the efforts of the compiler, so is not
checked for correctness.
XNF SPECIAL DEVICES
XNF STORAGE ELEMENTS
Storage elements in XNF include flip-flops, latches and CLB
rams. These devices are generated from the LPM equivilents that the
-Fsynth functor synthesizes from behavioral descriptions.
Flip-flops, or more specifically DFF devices, are generated to
implement behavioral code like this:
reg Q;
always @(posedge clk) Q = <expr>;
The edge can be positive or negative, and the expression can be any
synthesizeable expression. Furthermore, the register "Q" can have
width, which will cause the appropriate number of flip-flops to be
created. A clock enable expression can also be added like so:
reg Q;
always @(posedge clk) if (<ce>) Q = <expr>;
The <ce> expression can be any synthesizeable expression.
With or without the CE, the generated DFF devices are written into the
XNF output one bit at a time, with the clock input inverted if necessary.
Xilinx parts also support CLB circuitry as synchronous RAMS. These
devices are created from Verilog memories if the properties are
right. The behavioral description that the -Fsynth functor matches to
get a synchronous RAM looks very similar to that for a DFF:
memory [15:0] M;
always @(posedge clk) if (<we>) M[<addr>] = <expr>;
Note that in this case the l-value of the assignment is an addressed
memory. This statement models writes into the memory. Reads from the
device can be modeled with ordinary structural code, i.e.:
assign foo = M[<addr>];
For the memory to be synthesizeable in the XNF target, the address
lines for writes and reads must be connected. This corresponds to the
limitations of the real hardware.
OTHER XNF SPECIAL DEVICES
There are certain special devices in XNF that Verilog does not
naturally represent, although there are similar more generic Verilog
@ -176,6 +219,9 @@ IBUF, NOT gates cannot be absorbed as in the OPAD case.
$Log: xnf.txt,v $
Revision 1.10 1999/12/05 19:30:43 steve
Generate XNF RAMS from synthesized memories.
Revision 1.9 1999/11/18 03:52:20 steve
Turn NetTmp objects into normal local NetNet objects,
and add the nodangle functor to clean up the local