fd4f52a1f8b3324ac77cbd0e5e799aeb78c848c5
[fleet.git] / src / edu / berkeley / fleet / fpga / verilog / Verilog.java
1 package edu.berkeley.fleet.fpga.verilog;
2 import edu.berkeley.fleet.api.*;
3 import edu.berkeley.fleet.two.*;
4 import edu.berkeley.fleet.*;
5 import java.lang.reflect.*;
6 import edu.berkeley.sbp.chr.*;
7 import edu.berkeley.sbp.misc.*;
8 import edu.berkeley.sbp.meta.*;
9 import edu.berkeley.sbp.util.*;
10 import java.util.*;
11 import java.io.*;
12 import static edu.berkeley.fleet.two.FleetTwoFleet.*;
13
14 public class Verilog {
15
16     public static class SimpleValue implements Value {
17         public final String s;
18         public SimpleValue(String s) { this.s = s; }
19         public SimpleValue(String s, int high, int low) { this.s = s+"["+high+":"+low+"]"; }
20         public Value getBits(int high, int low) { return new SimpleValue(s, high, low); }
21         public Assignable getAssignableBits(int high, int low) { return new SimpleValue(s, high, low); }
22         public String getVerilogName() { return s; }
23         public String toString() { return s; }
24     }
25
26     public static class CatValue implements Value {
27         private final Value[] values;
28         public CatValue(Value[] values) { this.values = values; }
29         public Value getBits(int high, int low) {
30             throw new RuntimeException();
31         }
32         public Assignable getAssignableBits(int high, int low) {
33             throw new RuntimeException();
34         }
35         public String toString() { return getVerilogName(); }
36         public String getVerilogName() {
37             StringBuffer sb = new StringBuffer();
38             sb.append("{ ");
39             boolean first = true;
40             for(int i=0; i<values.length; i++) {
41                 if (values[i]==null) continue;
42                 if (!first) sb.append(", ");
43                 sb.append(values[i].getVerilogName());
44                 first = false;
45             }
46             sb.append(" }");
47             return sb.toString();
48         }
49     }
50
51     public static interface Action {
52         public String getVerilogAction();
53     }
54
55     public static interface Trigger {
56         public String getVerilogTrigger();
57     }
58
59     public static interface Assignable {
60         public String getVerilogName();
61         public Assignable getAssignableBits(int high, int low);
62     }
63
64     public static interface Value extends Assignable {
65         public String getVerilogName();
66         public Value getBits(int high, int low);
67     }
68
69     public static class ConditionalAction implements Action {
70         public String condition;
71         public Action action;
72         public ConditionalAction(String condition, Action action) {
73             this.condition = condition;
74             this.action = action;
75         }
76         public String toString() { return getVerilogAction(); }
77         public String getVerilogAction() { return "if ("+condition+") begin "+action.getVerilogAction()+" end"; }
78     }
79
80     public static class ConditionalTrigger implements Trigger {
81         public String condition;
82         public Trigger trigger;
83         public ConditionalTrigger(String condition, Trigger trigger) {
84             this.condition = condition;
85             this.trigger = trigger;
86             if (trigger instanceof Module.Port)
87                 ((Module.Port)trigger).hasLatch = true;
88         }
89         public String getVerilogTrigger() {
90             return "&& (("+condition+") ? (1 " + trigger.getVerilogTrigger() + ") : 1)";
91         }
92     }
93
94     public static class SimpleAssignable implements Assignable {
95         public final String s;
96         public SimpleAssignable(String s) { this.s = s; }
97         public String getVerilogName() { return s; }
98         public Assignable getAssignableBits(int high, int low) { return new SimpleValue(s, high, low); }
99     }
100
101     public static class AssignAction implements Action {
102         public String left;
103         public String right;
104         public AssignAction(Assignable left, Value right) {
105             this.left = left.getVerilogName();
106             this.right = right.getVerilogName().toString();
107         }
108         public AssignAction(Assignable left, String right) {
109             this.left = left.getVerilogName();
110             this.right = right;
111         }
112         public String getVerilogAction() { return left + "<=" + right + ";"; }
113         public String toString() { return getVerilogAction(); }
114     }
115     
116     public static class SimpleAction implements Action {
117         public final String verilog;
118         public SimpleAction(String verilog) { this.verilog = verilog; }
119         public String getVerilogAction() { return verilog; }
120         public String toString() { return verilog; }
121     }
122
123     public static class Module {
124         public void dump(String prefix) throws IOException {
125             PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/bitfields.v")));
126             pw.println("`define DATAWIDTH                "+WIDTH_WORD);
127             pw.println("`define CODEBAG_SIZE_BITS        "+CBD_SIZE.valmaskwidth);
128             pw.println("`define INSTRUCTION_WIDTH        "+WIDTH_WORD);
129             pw.println("`define packet_token(p)          "+PACKET_TOKEN.verilogVal("p"));
130             pw.println("`define packet_data(p)           "+PACKET_DATA.verilogVal("p"));
131             pw.println("`define packet_dest(p)           "+PACKET_DEST.verilogVal("p"));
132             pw.println("`define instruction_dest(p)      "+DISPATCH_PATH.verilogVal("p"));
133             pw.flush();
134             pw.close();
135             pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/"+name+".v")));
136             dump(pw, true);
137             pw.flush();
138             for(InstantiatedModule m : instantiatedModules)
139                 m.module.dump(prefix);
140         }
141         public int id = 0;
142         public final String name;
143         public String getName() { return name; }
144         public Port getPort(String name) { return ports.get(name); }
145
146         public HashSet<InstantiatedModule> instantiatedModules = new HashSet<InstantiatedModule>();
147         public final ArrayList<Event> events = new ArrayList<Event>();
148
149         // FIXME: always-alphabetical convention?
150         public final HashMap<String,Port> ports = new HashMap<String,Port>();
151         public final ArrayList<String> portorder = new ArrayList<String>();
152         public final HashMap<String,StateWire> statewires = new HashMap<String,StateWire>();
153         public final HashMap<String,Latch> latches = new HashMap<String,Latch>();
154         
155         public StringBuffer crap = new StringBuffer();
156         public StringBuffer precrap = new StringBuffer();
157         //public void addCrap(String s) { crap.append(s); crap.append('\n'); }
158         public void addPreCrap(String s) { precrap.append(s); precrap.append('\n'); }
159         public void addPreCrap0(String s) { precrap.append(s); }
160
161         public Module(String name) {
162             this.name = name;
163         }
164
165         public SourcePort createInputPort(String name, int width) {
166             if (ports.get(name)!=null) throw new RuntimeException();
167             return new SourcePort(name, width, true);
168         }
169         public SourcePort getInputPort(String name) {
170             SourcePort ret = (SourcePort)ports.get(name);
171             if (ret==null) throw new RuntimeException();
172             return ret;
173         }
174         public SinkPort createOutputPort(String name, int width, String resetBehavior) {
175             if (ports.get(name)!=null) throw new RuntimeException();
176             return new SinkPort(name, width, true, resetBehavior);
177         }
178         public SinkPort createWirePort(String name, int width) {
179             if (ports.get(name)!=null) throw new RuntimeException();
180             return new SinkPort(name, width, false, "");
181         }
182         public SourcePort createWireSourcePort(String name, int width) {
183             if (ports.get(name)!=null) throw new RuntimeException();
184             return new SourcePort(name, width, false);
185         }
186         public SinkPort getOutputPort(String name) {
187             SinkPort ret = (SinkPort)ports.get(name);
188             if (ret==null) throw new RuntimeException();
189             return ret;
190         }
191
192         public class StateWire {
193             public final String name;
194             public final boolean initiallyFull;
195             public String getName() { return name; }
196             public Action isFull()  { return new SimpleAction(name+"==1"); }
197             public Action isEmpty() { return new SimpleAction(name+"==0"); }
198             public Action doFill()  { return new SimpleAction(name+"<=1;"); }
199             public Action doDrain() { return new SimpleAction(name+"<=0;"); }
200             public String doReset() { return name+"<="+(initiallyFull?"1":"0")+";"; }
201             public StateWire(String name) { this(name, false); }
202             public StateWire(String name, boolean initiallyFull) {
203                 this.name = name;
204                 this.initiallyFull = initiallyFull;
205                 statewires.put(name, this);
206             }
207             public void dump(PrintWriter pw) {
208                 pw.println("  reg "+name+";");
209                 pw.println("  initial "+name+"="+(initiallyFull?"1":"0")+";");
210             }
211         }
212
213         public class Latch implements Assignable, Value {
214             public final String name;
215             public final int width;
216             public final long initial;
217             public Latch(String name, int width) { this(name, width, 0); }
218             public Latch(String name, int width, long initial) {
219                 this.width = width;
220                 this.name = name;
221                 this.initial = initial;
222                 latches.put(name, this);
223             }
224             public String getVerilogName() { return name; }
225             public Value getBits(int high, int low) { return new SimpleValue(getVerilogName(), high, low); }
226             public Assignable getAssignableBits(int high, int low) { return new SimpleValue(getVerilogName(), high, low); }
227             public String doReset() { return name+"<="+initial+";"; }
228             public void dump(PrintWriter pw) {
229                 pw.println("  reg ["+(width-1)+":0] "+name+";");
230                 pw.println("  initial "+name+"="+initial+";");
231             }
232             public void connect(SinkPort driven) {
233                 driven.latchDriver = this;
234             }
235         }
236
237         public abstract class Port implements Action, Assignable, Trigger {
238             public abstract String doReset();
239             public final String name;
240             public String getName() { return name; }
241             public final int width;
242             public int getWidth() { return width; }
243             public boolean hasLatch = false;
244             public boolean external;
245             public Port(String name, int width, boolean external) {
246                 this.width = width;
247                 this.name = name;
248                 this.external = external;
249                 ports.put(name, this);
250                 if (external)
251                     portorder.add(name);
252             }
253             public String getVerilogName() { return name; }
254             public String getAck() { return name+"_a"; }
255             public String getReq() { return name+"_r"; }
256             public abstract String getInterface();
257             public abstract String getSimpleInterface();
258             public abstract String getDeclaration();
259             public abstract String getAssignments();
260             public abstract void   connect(SinkPort driven);
261         }
262
263         public static class InstantiatedModule {
264             public final Module module;
265             public final Module thisModule;
266             public final int id;
267             public final HashMap<String,Port> ports = new HashMap<String,Port>();
268             public String getName() { return module.getName()+"_"+id; }
269             public InstantiatedModule(Module thisModule, Module module) {
270                 this.thisModule = thisModule;
271                 this.module = module;
272                 this.id = thisModule.id++;
273                 thisModule.instantiatedModules.add(this);
274             }
275             public void dump(PrintWriter pw) {
276                 pw.println("  " + module.getName() + " " + getName() + "(clk, rst ");
277                 for(String s : module.portorder)
278                     pw.println(", " + getPort(s).getSimpleInterface());
279                 if (module.name.equals("dram")) {
280                     pw.println("    , dram_addr");
281                     pw.println("    , dram_addr_r");
282                     pw.println("    , dram_addr_a");
283                     pw.println("    , dram_isread");
284                     pw.println("    , dram_write_data");
285                     pw.println("    , dram_write_data_push");
286                     pw.println("    , dram_write_data_full");
287                     pw.println("    , dram_read_data");
288                     pw.println("    , dram_read_data_pop");
289                     pw.println("    , dram_read_data_empty");
290                     pw.println("    , dram_read_data_latency");
291                 }
292                 if (module.name.equals("ddr2")) {
293                     pw.println("    , ddr2_addr");
294                     pw.println("    , ddr2_addr_r");
295                     pw.println("    , ddr2_addr_a");
296                     pw.println("    , ddr2_isread");
297                     pw.println("    , ddr2_write_data");
298                     pw.println("    , ddr2_write_data_push");
299                     pw.println("    , ddr2_write_data_full");
300                     pw.println("    , ddr2_read_data");
301                     pw.println("    , ddr2_read_data_pop");
302                     pw.println("    , ddr2_read_data_empty");
303                     pw.println("    , ddr2_read_data_latency");
304                 }
305                 if (module.name.equals("video")) {
306                     pw.println("    , vga_clk");
307                     pw.println("    , vga_psave");
308                     pw.println("    , vga_hsync");
309                     pw.println("    , vga_vsync");
310                     pw.println("    , vga_sync");
311                     pw.println("    , vga_blank");
312                     pw.println("    , vga_r");
313                     pw.println("    , vga_g");
314                     pw.println("    , vga_b");
315                     pw.println("    , vga_clkout");
316                 }
317                 pw.println("   );");
318             }
319             public Port getPort(String name) {
320                 return (module.ports.get(name) instanceof SinkPort) ? getOutputPort(name) : getInputPort(name);
321             }
322             public SinkPort getInputPort(String name) {
323                 int width = module.getPort(name).getWidth();
324                 SinkPort port = (SinkPort)ports.get(name);
325                 if (port == null) {
326                     port = thisModule.new SinkPort(getName()+"_"+name, width, false, "");
327                     ports.put(name, port);
328                 }
329                 return port;
330             }
331             public SourcePort getOutputPort(String name) {
332                 int width = module.getPort(name).getWidth();
333                 SourcePort port = (SourcePort)ports.get(name);
334                 if (port == null) {
335                     port = thisModule.new SourcePort(getName()+"_"+name, width, false);
336                     ports.put(name, port);
337                 }
338                 return port;
339             }
340         }
341
342         public class SourcePort extends Port implements Value {
343             public SourcePort(String name, int width, boolean external) { 
344                 super(name, width, external); }
345             public Value getBits(int high, int low) { return new SimpleValue(getVerilogName(), high, low); }
346             public Assignable getAssignableBits(int high, int low) { return new SimpleValue(getVerilogName(), high, low); }
347             public String getVerilogTrigger() { return " && " + getReq() + " && !"+getAck(); }
348             public String getVerilogAction() { return getAck() + " <= 1;"; }
349             public String getInterface() { return getReq()+", "+getAck()+"_, "+name+""; }
350             public String getSimpleInterface() { return getReq()+", "+getAck()+", "+name+""; }
351             public String testBit(int index, boolean value) {
352                 return "("+name+"["+index+"]=="+(value?1:0)+")";
353             }
354             public String getDeclaration() {
355                 StringBuffer sb = new StringBuffer();
356                 if (external) {
357                     sb.append("input "  +                 name +"_r;\n");
358                     sb.append("output " +                 name +"_a_;\n");
359                     if (width>0)
360                         sb.append("input ["+(width-1)+":0]" + name +";\n");
361                     else
362                         sb.append("input [0:0]" + name +";\n"); // waste a bit, I guess
363                 } else {
364                     sb.append("wire "  +                 name +"_r;\n");
365                     if (width>0)
366                         sb.append("wire ["+(width-1)+":0]" + name +";\n");
367                 }
368                 if (!hasLatch) {
369                     sb.append("wire "    +                 name +"_a;\n");
370                 } else {
371                     sb.append("reg "    +                 name +"_a;\n");
372                     sb.append("initial " +                name +"_a = 0;\n");
373                 }
374                 return sb.toString();
375             }
376             public String doReset() { return hasLatch ? name+"_a<=1;" : ""; }
377             public String getAssignments() {
378                 StringBuffer sb = new StringBuffer();
379                 if (external)
380                     sb.append("assign " +                 name +"_a_ = " + name + "_a;\n");
381                 return sb.toString();
382             }
383             public void connect(SinkPort driven) {
384                 driven.driver = this;
385             }
386         }
387         public class SinkPort extends Port {
388             public SourcePort driver = null;
389             public boolean forceNoLatch = false;
390             public SinkPort driven = null;
391             public Latch latchDriver = null;
392             public final String resetBehavior;
393             public Assignable getAssignableBits(int high, int low) { return new SimpleValue(getVerilogName(), high, low); }
394             public String getVerilogAction() { return getReq() + " <= 1;"; }
395             public String getVerilogTrigger() { return " && !" + getReq() + " && !"+getAck(); }
396             public SinkPort(String name, int width, boolean external, String resetBehavior) {
397                 super(name, width, external); this.resetBehavior=resetBehavior; }
398             public String getResetBehavior() { return resetBehavior; }
399             public String getInterface() { return name+"_r_, "+name+"_a, "+name+"_"; }
400             public String getSimpleInterface() { return name+"_r, "+name+"_a, "+name; }
401             public String getDeclaration() {
402                 StringBuffer sb = new StringBuffer();
403                 if (external) {
404                     sb.append("output "  +                 name +"_r_;\n");
405                     sb.append("input "   +                 name +"_a;\n");
406                     if (width>0)
407                         sb.append("output ["+(width-1)+":0]" + name +"_;\n");
408                     else
409                         sb.append("output [0:0]" + name +"_;\n"); // waste a bit, I guess
410                 } else {
411                     sb.append("wire "   +                 name +"_a;\n");
412                 }
413
414                 if (forceNoLatch ||  latchDriver!=null) {
415                     sb.append("reg "    +                  name +"_r;\n");
416                     sb.append("initial " +                 name +"_r = 0;\n");
417                     if (width>0)
418                         sb.append("wire   ["+(width-1)+":0]" + name +";\n");
419                 } else if (!hasLatch) {
420                     sb.append("wire "    +                 name +"_r;\n");
421                     if (width>0)
422                         sb.append("wire   ["+(width-1)+":0]" + name +";\n");
423                 } else {
424                     sb.append("reg "    +                  name +"_r;\n");
425                     sb.append("initial " +                 name +"_r = 0;\n");
426                     if (width>0) {
427                         sb.append("reg    ["+(width-1)+":0]" + name +";\n");
428                         if (!"/*NORESET*/".equals(resetBehavior))
429                             sb.append("initial " +                 name +" = 0;\n");
430                     }
431                 }
432                 return sb.toString();
433             }
434             public String doReset() {
435                 return (forceNoLatch||latchDriver!=null)
436                     ? name+"_r<=0;"
437                     : hasLatch
438                     ? (name+"_r<=0; "+("/*NORESET*/".equals(resetBehavior) ? "" : (name+"<=0;")))
439                     : "";
440             }
441             public String getAssignments() {
442                 StringBuffer sb = new StringBuffer();
443                 if (external) {
444                     sb.append("assign " +                  name +"_r_ = " + name + "_r;\n");
445                     if (width>0)
446                         sb.append("assign " +                  name +"_ = " + name + ";\n");
447                 }
448                 if (driven != null) {
449                     sb.append("assign " + driven.name +"_r = " + name + "_r;\n");
450                     sb.append("assign " + name +"_a = " + driven.name + "_a;\n");
451                     if (width>0)
452                         sb.append("assign " + driven.name +"   = " + name + ";\n");
453                 }
454                 if (driver != null) {
455                     sb.append("assign " + name +"_r = " + driver.name + "_r;\n");
456                     sb.append("assign " + driver.name +"_a = " + name + "_a;\n");
457                     if (width>0)
458                         sb.append("assign " + name +"   = " + driver.name + ";\n");
459                 }
460                 if (latchDriver != null) {
461                     if (width>0)
462                         sb.append("assign " + name +"   = " + latchDriver.name + ";\n");
463                 }
464                 return sb.toString();
465             }
466             public void connect(SinkPort driven) {
467                 this.driven = driven;
468                 throw new RuntimeException();
469             }
470         }
471
472         public void dump(PrintWriter pw, boolean fix) {
473             pw.println("`include \"bitfields.v\"");
474             pw.println("module "+name+"(clk, rst ");
475             for(String name : portorder) {
476                 Port p = ports.get(name);
477                 pw.println("    , " + p.getInterface());
478             }
479             if (this.name.equals("root")) {
480                 pw.println("    , dram_addr");
481                 pw.println("    , dram_addr_r");
482                 pw.println("    , dram_addr_a");
483                 pw.println("    , dram_isread");
484                 pw.println("    , dram_write_data");
485                 pw.println("    , dram_write_data_push");
486                 pw.println("    , dram_write_data_full");
487                 pw.println("    , dram_read_data");
488                 pw.println("    , dram_read_data_pop");
489                 pw.println("    , dram_read_data_empty");
490                 pw.println("    , dram_read_data_latency");
491                 pw.println("    , vga_clk");
492                 pw.println("    , vga_psave");
493                 pw.println("    , vga_hsync");
494                 pw.println("    , vga_vsync");
495                 pw.println("    , vga_sync");
496                 pw.println("    , vga_blank");
497                 pw.println("    , vga_r");
498                 pw.println("    , vga_g");
499                 pw.println("    , vga_b");
500                 pw.println("    , vga_clkout");
501                 pw.println("    , ddr2_addr");
502                 pw.println("    , ddr2_addr_r");
503                 pw.println("    , ddr2_addr_a");
504                 pw.println("    , ddr2_isread");
505                 pw.println("    , ddr2_write_data");
506                 pw.println("    , ddr2_write_data_push");
507                 pw.println("    , ddr2_write_data_full");
508                 pw.println("    , ddr2_read_data");
509                 pw.println("    , ddr2_read_data_pop");
510                 pw.println("    , ddr2_read_data_empty");
511                 pw.println("    , ddr2_read_data_latency");
512             }
513             pw.println("   );");
514             pw.println();
515             pw.println("    input clk;");
516             pw.println("    input rst;");
517             if (this.name.equals("root")) {
518                 pw.println("output  [31:0] dram_addr;");
519                 pw.println("output         dram_addr_r;");
520                 pw.println("input          dram_addr_a;");
521                 pw.println("output         dram_isread;");
522                 pw.println("output  [63:0] dram_write_data;");
523                 pw.println("output         dram_write_data_push;");
524                 pw.println("input          dram_write_data_full;");
525                 pw.println("input   [63:0] dram_read_data;");
526                 pw.println("output         dram_read_data_pop;");
527                 pw.println("input          dram_read_data_empty;");
528                 pw.println("input   [1:0]  dram_read_data_latency;");
529                 pw.println("output  [31:0] ddr2_addr;");
530                 pw.println("output         ddr2_addr_r;");
531                 pw.println("input          ddr2_addr_a;");
532                 pw.println("output         ddr2_isread;");
533                 pw.println("output  [63:0] ddr2_write_data;");
534                 pw.println("output         ddr2_write_data_push;");
535                 pw.println("input          ddr2_write_data_full;");
536                 pw.println("input   [63:0] ddr2_read_data;");
537                 pw.println("output         ddr2_read_data_pop;");
538                 pw.println("input          ddr2_read_data_empty;");
539                 pw.println("input   [1:0]  ddr2_read_data_latency;");
540                 pw.println("input          vga_clk;");
541                 pw.println("output         vga_psave;");
542                 pw.println("output         vga_hsync;");
543                 pw.println("output         vga_vsync;");
544                 pw.println("output         vga_sync;");
545                 pw.println("output         vga_blank;");
546                 pw.println("output   [7:0] vga_r;");
547                 pw.println("output   [7:0] vga_g;");
548                 pw.println("output   [7:0] vga_b;");
549                 pw.println("output         vga_clkout;");
550             }
551             for(String name : ports.keySet()) {
552                 Port p = ports.get(name);
553                 pw.println("    " + p.getDeclaration());
554             }
555             for(StateWire sw : statewires.values())
556                 sw.dump(pw);
557             for(Latch l : latches.values())
558                 l.dump(pw);
559             for(String name : ports.keySet()) {
560                 Port p = ports.get(name);
561                 pw.println("    " + p.getAssignments());
562             }
563             for(InstantiatedModule m : instantiatedModules) {
564                 m.dump(pw);
565             }
566             pw.println(precrap);
567             pw.println("always @(posedge clk) begin");
568             pw.println("  if (!rst) begin");
569             for(Latch l : latches.values())
570                 pw.println(l.doReset());
571             for(StateWire sw : statewires.values())
572                 pw.println(sw.doReset());
573             for(Port p : ports.values())
574                 pw.println(p.doReset());
575             pw.println("  end else begin");
576             for(Port p : ports.values()) {
577                 if (p instanceof SourcePort) {
578                     SourcePort ip = (SourcePort)p;
579                     if (ip.hasLatch)
580                         pw.println("if (!"+ip.getReq()+" && "+ip.getAck()+") "+ip.getAck()+"<=0;");
581                 } else {
582                     SinkPort op = (SinkPort)p;
583                     if (op.hasLatch)
584                         pw.println("if ("+op.getReq()+" && "+op.getAck()+") begin "+
585                                    op.getReq()+"<=0; "+
586                                    op.getResetBehavior()+" end");
587                 }
588             }
589             for(Event a : events) a.dump(pw, fix);
590             pw.println("    begin end");
591             pw.println("    end");
592             pw.println("  end");
593
594             pw.println(crap);
595             pw.println("endmodule");
596         }
597
598         public class Event {
599             public Object[]  triggers;
600             public Object[]  actions;
601             public Event(Object[] triggers, Object action) { this(triggers, new Object[] { action }); }
602             public Event(Object[] triggers, Object[] actions) {
603                 Module.this.events.add(this);
604                 this.triggers = triggers;
605                 this.actions = actions;
606                 for(int i=0; i<triggers.length; i++)
607                     if (triggers[i] instanceof Port)
608                         ((Port)triggers[i]).hasLatch = true;
609             }
610             public void dump(PrintWriter pw, boolean fix) {
611                 pw.print("if (1");
612                 for(Object o : triggers) {
613                     if (o instanceof Trigger) pw.print(((Trigger)o).getVerilogTrigger());
614                     else                      pw.print(" && " + o);
615                 }
616                 pw.println(") begin ");
617                 for(Object a : actions) if (a!=null) pw.println(((Action)a).getVerilogAction());
618                 if (fix) pw.println("end /*else*/ ");
619                 else     pw.println("end else ");
620             }
621         }
622     }
623 }