diff --git a/vvp/compile.h b/vvp/compile.h index 44f1a1c6b..5745a7b25 100644 --- a/vvp/compile.h +++ b/vvp/compile.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: compile.h,v 1.56.2.2 2006/03/12 07:34:21 steve Exp $" +#ident "$Id: compile.h,v 1.56.2.3 2006/03/26 23:09:00 steve Exp $" #endif # include @@ -120,6 +120,9 @@ extern void compile_decode_adr(char*label, extern void compile_decode_en(char*label, char*decoder, int slice, struct symb_s enable, struct symb_s mass_enable); +extern void compile_demux(char*label, char*decoder, int slice, + struct symb_s not_selected, + struct symb_s selected); extern void compile_shiftl(char*label, long width, unsigned argc, struct symb_s*argv); extern void compile_shiftr(char*label, long width, @@ -273,6 +276,9 @@ extern void compile_net(char*label, char*name, /* * $Log: compile.h,v $ + * Revision 1.56.2.3 2006/03/26 23:09:00 steve + * Add the .demux device. + * * Revision 1.56.2.2 2006/03/12 07:34:21 steve * Fix the memsynth1 case. * diff --git a/vvp/decoder.cc b/vvp/decoder.cc index 5e031fe0c..12938de6b 100644 --- a/vvp/decoder.cc +++ b/vvp/decoder.cc @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ -#ident "$Id: decoder.cc,v 1.1.2.2 2006/03/12 07:34:21 steve Exp $" +#ident "$Id: decoder.cc,v 1.1.2.3 2006/03/26 23:09:00 steve Exp $" # include "compile.h" # include "functor.h" @@ -67,10 +67,33 @@ struct vvp_decode_adr_s : public functor_s { vvp_ipoint_t ix; const unsigned width; // Keep a list of decode_en objects that reference me. - struct vvp_decode_en_s* enable_list; + struct vvp_decodable_s* enable_list; }; -struct vvp_decode_en_s : public functor_s { +/* + * A vvp_decodeable_s object may receive results from an address + * decoder. The propagate_decoder_address virtual method is called by + * the address decoder for all the associated decodable objects. + */ +struct vvp_decodable_s { + vvp_decodable_s(vvp_decode_adr_s*dec, unsigned s) + : decoder(dec), self(s) + { + enable_next = decoder->enable_list; + decoder->enable_list = this; + } + + virtual void propagate_decoder_address(unsigned adr) =0; + + struct vvp_decode_adr_s*decoder; + const unsigned self; + + struct vvp_decodable_s* enable_next; +}; + +/* + */ +struct vvp_decode_en_s : public functor_s, public vvp_decodable_s { vvp_decode_en_s(vvp_decode_adr_s*dec, unsigned s); @@ -78,10 +101,6 @@ struct vvp_decode_en_s : public functor_s { void propagate_decoder_address(unsigned adr); - struct vvp_decode_adr_s*decoder; - struct vvp_decode_en_s* enable_next; - - const unsigned self; // This is the enable calculated from the decoder bool decode_en; // This is the enable that arrives from the extra input. @@ -90,6 +109,19 @@ struct vvp_decode_en_s : public functor_s { bool mass_en; }; +struct vvp_demux_s : public functor_s, public vvp_decodable_s { + + vvp_demux_s(vvp_decode_adr_s*dec, unsigned s); + + void set(vvp_ipoint_t i, bool push, unsigned val, unsigned str); + + void propagate_decoder_address(unsigned adr); + + unsigned char sel_val; + unsigned char not_val; + bool decode_en; +}; + vvp_decode_adr_s::vvp_decode_adr_s(vvp_ipoint_t me, unsigned w) : ix(me), width(w), enable_list(0) { @@ -111,21 +143,17 @@ void vvp_decode_adr_s::set(vvp_ipoint_t i, bool push, } - for (vvp_decode_en_s*cur = enable_list ; cur ; cur = cur->enable_next) + for (vvp_decodable_s*cur = enable_list ; cur ; cur = cur->enable_next) cur->propagate_decoder_address(cur_adr); } vvp_decode_en_s::vvp_decode_en_s(vvp_decode_adr_s*dec, unsigned s) -: self(s) +: vvp_decodable_s(dec, s) { - enable_next = 0; decode_en = false; extra_en = true; mass_en = false; - decoder = dec; - enable_next = decoder->enable_list; - decoder->enable_list = this; } void vvp_decode_en_s::set(vvp_ipoint_t i, bool push, @@ -173,6 +201,50 @@ void vvp_decode_en_s::propagate_decoder_address(unsigned adr) put_oval(0, true); } +vvp_demux_s::vvp_demux_s(vvp_decode_adr_s*dec, unsigned s) +: vvp_decodable_s(dec, s) +{ + decode_en = false; + sel_val = StX; + not_val = StX; +} + +void vvp_demux_s::set(vvp_ipoint_t i, bool push, + unsigned val, unsigned str) +{ + functor_t ifu = functor_index(i); + ifu->put(i, val); + + unsigned port = ipoint_port(i); + switch (port) { + case 0: // not-selected input + not_val = val; + break; + case 1: // is-selected input + sel_val = val; + break; + } + + if (decode_en) + put_oval(sel_val, true); + else + put_oval(not_val, true); +} + +void vvp_demux_s::propagate_decoder_address(unsigned adr) +{ + if (adr == self) { + decode_en = true; + } else { + decode_en = false; + } + + if (decode_en) + put_oval(sel_val, true); + else + put_oval(not_val, true); +} + void compile_decode_adr(char*label, unsigned argc, struct symb_s*argv) { unsigned nfun = (argc + 3)/4; @@ -216,8 +288,30 @@ void compile_decode_en(char*label, char*decoder, int slice, free(label); } +void compile_demux(char*label, char*decoder, int slice, + struct symb_s not_selected, + struct symb_s selected) +{ + vvp_decode_adr_s*adr = decoder_find(decoder); + vvp_demux_s*a = new struct vvp_demux_s(adr, slice); + + vvp_ipoint_t ix = functor_allocate(1); + functor_define(ix, a); + + symb_s argv[2]; + argv[0] = not_selected; + argv[1] = selected; + inputs_connect(ix, 2, argv); + + define_functor_symbol(label, ix); + free(label); +} + /* * $Log: decoder.cc,v $ + * Revision 1.1.2.3 2006/03/26 23:09:00 steve + * Add the .demux device. + * * Revision 1.1.2.2 2006/03/12 07:34:21 steve * Fix the memsynth1 case. * diff --git a/vvp/lexor.lex b/vvp/lexor.lex index 41854b889..56af55ade 100644 --- a/vvp/lexor.lex +++ b/vvp/lexor.lex @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: lexor.lex,v 1.43.2.1 2006/02/19 00:11:36 steve Exp $" +#ident "$Id: lexor.lex,v 1.43.2.2 2006/03/26 23:09:00 steve Exp $" #endif # include "parse_misc.h" @@ -97,6 +97,7 @@ ".cmp/gt.s" { return K_CMP_GT_S; } ".decode/adr" { return K_DECODE_ADR; } ".decode/en" { return K_DECODE_EN; } +".demux" { return K_DEMUX; } ".event" { return K_EVENT; } ".event/or" { return K_EVENT_OR; } ".functor" { return K_FUNCTOR; } @@ -184,6 +185,9 @@ int yywrap() /* * $Log: lexor.lex,v $ + * Revision 1.43.2.2 2006/03/26 23:09:00 steve + * Add the .demux device. + * * Revision 1.43.2.1 2006/02/19 00:11:36 steve * Handle synthesis of FF vectors with l-value decoder. * diff --git a/vvp/parse.y b/vvp/parse.y index 1b7563e07..a819cda09 100644 --- a/vvp/parse.y +++ b/vvp/parse.y @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: parse.y,v 1.60.2.2 2006/03/12 07:34:21 steve Exp $" +#ident "$Id: parse.y,v 1.60.2.3 2006/03/26 23:09:01 steve Exp $" #endif # include "parse_misc.h" @@ -60,7 +60,7 @@ extern FILE*yyin; %token K_ARITH_DIV K_ARITH_DIV_S K_ARITH_MOD K_ARITH_MULT %token K_ARITH_SUB K_ARITH_SUM %token K_CMP_EQ K_CMP_NE K_CMP_GE K_CMP_GE_S K_CMP_GT K_CMP_GT_S -%token K_DECODE_ADR K_DECODE_EN +%token K_DECODE_ADR K_DECODE_EN K_DEMUX %token K_EVENT K_EVENT_OR K_FUNCTOR K_NET K_NET_S K_PARAM %token K_RESOLV K_SCOPE K_SHIFTL K_SHIFTR K_THREAD K_TIMESCALE K_UFUNC %token K_UDP K_UDP_C K_UDP_S @@ -274,6 +274,10 @@ statement { compile_decode_en($1, $3, $5, $7, $9); } + | T_LABEL K_DEMUX T_SYMBOL ',' T_NUMBER ',' symbol ',' symbol ';' + { compile_demux($1, $3, $5, $7, $9); + } + /* Event statements take a label, a type (the first T_SYMBOL) and a list of inputs. If the type is instead a string, then we have a named event instead. */ @@ -646,6 +650,9 @@ int compile_design(const char*path) /* * $Log: parse.y,v $ + * Revision 1.60.2.3 2006/03/26 23:09:01 steve + * Add the .demux device. + * * Revision 1.60.2.2 2006/03/12 07:34:21 steve * Fix the memsynth1 case. *