/* * Copyright (c) 1999 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU * General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) #ident "$Id: xnfsyn.cc,v 1.1 1999/07/18 05:52:47 steve Exp $" #endif /* * The xnfsyn function searches the behavioral description for * patterns that are known to represent XNF library components. This * is especially interesting for the sequential components such as * flip flops and latches. As threads are transformed into components, * the design is rewritten. * * Currently, this transform recognizes the following patterns: * * always @(posedge CLK) Q = D // DFF */ # include "functor.h" # include "netlist.h" class xnfsyn_f : public functor_t { public: void process(class Design*, class NetProcTop*); private: void proc_always(class Design*, class NetProcTop*); }; /* * Look at a process, and divide the problem into always and initial * threads. */ void xnfsyn_f::process(class Design*des, class NetProcTop*top) { switch (top->type()) { case NetProcTop::KALWAYS: proc_always(des, top); break; } } /* * Look for DFF devices. The pattern I'm looking for is: * * always @(posedge CLK) Q = D; * * This creates a DFF with the CLK, D and Q hooked up the obvious * way. CE and PRE/CLR are left unconnected. */ void xnfsyn_f::proc_always(class Design*des, class NetProcTop*top) { // The statement must be a NetPEvent, ... const NetProc*st = top->statement(); const NetPEvent*ev = dynamic_cast(st); if (ev == 0) return; // ... there must be a single event source, ... svector*neb = ev->back_list(); if (neb == 0) return; if (neb->count() != 1) { delete neb; return; } const NetNEvent*nev = (*neb)[0]; delete neb; // ... the event must be POSEDGE, ... if (nev->type() != NetNEvent::POSEDGE) return; // the NetPEvent must guard an assignment, ... const NetAssign*asn = dynamic_cast(ev->statement()); if (asn == 0) return; // ... and the rval must be a simple signal. const NetESignal*sig = dynamic_cast(asn->rval()); if (sig == 0) return ; // XXXX For now, only handle single bit. assert(asn->pin_count() == 1); assert(sig->pin_count() == 1); NetUDP*dff = new NetUDP(asn->name(), 3, true); connect(dff->pin(0), asn->pin(0)); connect(dff->pin(1), sig->pin(0)); connect(dff->pin(2), nev->pin(0)); dff->attribute("XNF-LCA", "DFF:Q,D,CLK"); des->add_node(dff); // This process is matched and replaced with a DFF. Get // rid of the now useless NetProcTop. des->delete_process(top); } void xnfsyn(Design*des) { xnfsyn_f xnfsyn_obj; des->functor(&xnfsyn_obj); } /* * $Log: xnfsyn.cc,v $ * Revision 1.1 1999/07/18 05:52:47 steve * xnfsyn generates DFF objects for XNF output, and * properly rewrites the Design netlist in the process. * */