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