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