diff options
| author | jackbackrack | 2015-04-27 17:37:42 -0700 |
|---|---|---|
| committer | jackbackrack | 2015-04-27 17:37:42 -0700 |
| commit | 2a4f374b19e10a1571fbd2a23b30e92c9179defd (patch) | |
| tree | d106c4bd0204124cdf46479e8f6ebc1e37ede3d1 /src | |
| parent | cbc928e5e80898163871b8be1b34106e5275af58 (diff) | |
| parent | d6d630e6dbe3e5dd3c335cc8bd65a81d9dcb0f5f (diff) | |
merge
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib/stanza.zip | bin | 3758011 -> 3695332 bytes | |||
| -rw-r--r-- | src/main/stanza/firrtl-ir.stanza | 3 | ||||
| -rw-r--r-- | src/main/stanza/ir-parser.stanza | 504 | ||||
| -rw-r--r-- | src/main/stanza/ir-utils.stanza | 15 | ||||
| -rw-r--r-- | src/main/stanza/passes.stanza | 482 |
5 files changed, 543 insertions, 461 deletions
diff --git a/src/lib/stanza.zip b/src/lib/stanza.zip Binary files differindex fb9ac7d7..5fd5ff6d 100644 --- a/src/lib/stanza.zip +++ b/src/lib/stanza.zip diff --git a/src/main/stanza/firrtl-ir.stanza b/src/main/stanza/firrtl-ir.stanza index f14378cc..0e5400b2 100644 --- a/src/main/stanza/firrtl-ir.stanza +++ b/src/main/stanza/firrtl-ir.stanza @@ -192,6 +192,9 @@ public defstruct Conditionally <: Stmt : alt: Stmt public defstruct Begin <: Stmt : ;LOW body: List<Stmt> +public defstruct OnReset <: Stmt : ;LOW + loc: Expression + exp: Expression public defstruct Connect <: Stmt : ;LOW loc: Expression exp: Expression diff --git a/src/main/stanza/ir-parser.stanza b/src/main/stanza/ir-parser.stanza index 1772d773..6e6ba1a2 100644 --- a/src/main/stanza/ir-parser.stanza +++ b/src/main/stanza/ir-parser.stanza @@ -5,241 +5,321 @@ defpackage firrtl/parser : import stz/parser import stz/lexer -;======= Convenience Functions ==== -defn throw-error (x) : +;======= Convenience Functions ======== +defn first-info? (form) -> FileInfo|False : + match(form) : + (form:Token) : info(form) + (form:List) : search(first-info?, form) + (form) : false + +defn first-info (form:List) : + match(first-info?(form)) : + (i:FileInfo) : i + (f:False) : FileInfo() + +defn FPE (form, x) : throw $ new Exception : defmethod print (o:OutputStream, this) : - print(o, x) + print(o, "[~] FIRRTL Parsing Error: ~" << [first-info(form), x]) + +defn* apply-suffix-ops (x, fs:List) : + if empty?(fs) : x + else : apply-suffix-ops(head(fs)(x), tail(fs)) -defn ut (x) : - unwrap-token(x) +;======== Parser Utilities ============== +defn atom? (x) : unwrap-token(x) not-typeof List -;======== SYNTAX ======================= +defn primop (x:Symbol) : get?(OPERATORS, x, false) +val OPERATORS = HashTable<Symbol, PrimOp>(symbol-hash) +OPERATORS[`add] = ADD-OP +OPERATORS[`add-uu] = ADD-UU-OP +OPERATORS[`add-us] = ADD-US-OP +OPERATORS[`add-su] = ADD-SU-OP +OPERATORS[`add-ss] = ADD-SS-OP +OPERATORS[`sub] = SUB-OP +OPERATORS[`sub-uu] = SUB-UU-OP +OPERATORS[`sub-us] = SUB-US-OP +OPERATORS[`sub-su] = SUB-SU-OP +OPERATORS[`sub-ss] = SUB-SS-OP +OPERATORS[`mul] = MUL-OP +OPERATORS[`mul-uu] = MUL-UU-OP +OPERATORS[`mul-us] = MUL-US-OP +OPERATORS[`mul-su] = MUL-SU-OP +OPERATORS[`mul-ss] = MUL-SS-OP +OPERATORS[`div] = DIV-OP +OPERATORS[`div-uu] = DIV-UU-OP +OPERATORS[`div-us] = DIV-US-OP +OPERATORS[`div-su] = DIV-SU-OP +OPERATORS[`div-ss] = DIV-SS-OP +OPERATORS[`mod] = MOD-OP +OPERATORS[`mod-uu] = MOD-UU-OP +OPERATORS[`mod-us] = MOD-US-OP +OPERATORS[`mod-su] = MOD-SU-OP +OPERATORS[`mod-ss] = MOD-SS-OP +OPERATORS[`quo] = QUO-OP +OPERATORS[`quo-uu] = QUO-UU-OP +OPERATORS[`quo-us] = QUO-US-OP +OPERATORS[`quo-su] = QUO-SU-OP +OPERATORS[`quo-ss] = QUO-SS-OP +OPERATORS[`rem] = REM-OP +OPERATORS[`rem-uu] = REM-UU-OP +OPERATORS[`rem-us] = REM-US-OP +OPERATORS[`rem-su] = REM-SU-OP +OPERATORS[`rem-ss] = REM-SS-OP +OPERATORS[`add-wrap] = ADD-WRAP-OP +OPERATORS[`add-wrap-uu] = ADD-WRAP-UU-OP +OPERATORS[`add-wrap-us] = ADD-WRAP-US-OP +OPERATORS[`add-wrap-su] = ADD-WRAP-SU-OP +OPERATORS[`add-wrap-ss] = ADD-WRAP-SS-OP +OPERATORS[`sub-wrap] = SUB-WRAP-OP +OPERATORS[`sub-wrap-uu] = SUB-WRAP-UU-OP +OPERATORS[`sub-wrap-us] = SUB-WRAP-US-OP +OPERATORS[`sub-wrap-su] = SUB-WRAP-SU-OP +OPERATORS[`sub-wrap-ss] = SUB-WRAP-SS-OP +OPERATORS[`lt] = LESS-OP +OPERATORS[`lt-uu] = LESS-UU-OP +OPERATORS[`lt-us] = LESS-US-OP +OPERATORS[`lt-su] = LESS-SU-OP +OPERATORS[`lt-ss] = LESS-SS-OP +OPERATORS[`leq] = LESS-EQ-OP +OPERATORS[`leq-uu] = LESS-EQ-UU-OP +OPERATORS[`leq-us] = LESS-EQ-US-OP +OPERATORS[`leq-su] = LESS-EQ-SU-OP +OPERATORS[`leq-ss] = LESS-EQ-SS-OP +OPERATORS[`gt] = GREATER-OP +OPERATORS[`gt-uu] = GREATER-UU-OP +OPERATORS[`gt-us] = GREATER-US-OP +OPERATORS[`gt-su] = GREATER-SU-OP +OPERATORS[`gt-ss] = GREATER-SS-OP +OPERATORS[`geq] = GREATER-EQ-OP +OPERATORS[`geq-uu] = GREATER-EQ-UU-OP +OPERATORS[`geq-us] = GREATER-EQ-US-OP +OPERATORS[`geq-su] = GREATER-EQ-SU-OP +OPERATORS[`geq-ss] = GREATER-EQ-SS-OP +OPERATORS[`eq] = EQUAL-OP +OPERATORS[`eq-uu] = EQUAL-UU-OP +OPERATORS[`eq-ss] = EQUAL-SS-OP +OPERATORS[`neq] = NEQUAL-OP +OPERATORS[`neq-uu] = NEQUAL-UU-OP +OPERATORS[`neq-ss] = NEQUAL-SS-OP +OPERATORS[`mux] = MUX-OP +OPERATORS[`mux-uu] = MUX-UU-OP +OPERATORS[`mux-ss] = MUX-SS-OP +OPERATORS[`pad] = PAD-OP +OPERATORS[`pad-u] = PAD-U-OP +OPERATORS[`pad-s] = PAD-S-OP +OPERATORS[`neg] = NEG-OP +OPERATORS[`neg-u] = NEG-U-OP +OPERATORS[`neg-s] = NEG-S-OP +OPERATORS[`as-UInt] = AS-UINT-OP +OPERATORS[`as-UInt-u] = AS-UINT-U-OP +OPERATORS[`as-UInt-s] = AS-UINT-S-OP +OPERATORS[`as-SInt] = AS-SINT-OP +OPERATORS[`as-SInt-u] = AS-SINT-U-OP +OPERATORS[`as-SInt-s] = AS-SINT-S-OP +OPERATORS[`shl] = SHIFT-LEFT-OP +OPERATORS[`shl-u] = SHIFT-LEFT-U-OP +OPERATORS[`shl-s] = SHIFT-LEFT-S-OP +OPERATORS[`shr] = SHIFT-RIGHT-OP +OPERATORS[`shr-u] = SHIFT-RIGHT-U-OP +OPERATORS[`shr-s] = SHIFT-RIGHT-S-OP +OPERATORS[`convert] = CONVERT-OP +OPERATORS[`convert-u] = CONVERT-U-OP +OPERATORS[`convert-s] = CONVERT-S-OP +OPERATORS[`bit-and-reduce] = BIT-AND-REDUCE-OP +OPERATORS[`bit-or-reduce] = BIT-OR-REDUCE-OP +OPERATORS[`bit-xor-reduce] = BIT-XOR-REDUCE-OP +OPERATORS[`bit-not] = BIT-NOT-OP +OPERATORS[`bit-and] = BIT-AND-OP +OPERATORS[`bit-or] = BIT-OR-OP +OPERATORS[`bit-xor] = BIT-XOR-OP +OPERATORS[`cat] = CONCAT-OP +OPERATORS[`bit] = BIT-SELECT-OP +OPERATORS[`bits] = BITS-SELECT-OP + +;======== Parser Rules ================== defsyntax firrtl : + ;Useful Atoms + defrule atoms : + ;Unconditionally parse next form as identifier. + id = (?x) when atom?(x) : + match(unwrap-token(x)) : + (x:Symbol) : x + (x) : FPE(form, "Expected an identifier here. Got ~ instead." << [x]) + + ;Parses next form if integer literal + int = (?x) when unwrap-token(x) typeof Int : + unwrap-token(x) + + ;Parses next form if symbol + sym = (?x) when unwrap-token(x) typeof Symbol : + unwrap-token(x) + + ;Error Handling Productions defrule : - symbol = (?x) when ut(x) typeof Symbol : ut(x) - int = (?x) when ut(x) typeof Int : ut(x) - + ;Error if not an identifier + id! = (?x:#id) : x + id! != () : FPE(form, "Expected an identifier here.") + + ;Error if not a colon + :! = (:) : (`:) + :! != () : FPE(form, "Expected a colon here.") + + ;Error if not 'of' keyword + of! = (of) : `of + of! != () : FPE(form, "Expected the 'of' keyword here.") + + ;Error if not a = + =! = (=) : `= + =! != () : FPE(form, "Expected a '=' here.") + + ;Error if not a single integer + int$ = (?i:#int ?rest ...) when empty?(rest) : i + int$ != () : FPE(form, "Expected a single integer literal here.") + + ;Error if not a single width + width$ = (?w:#width ?rest ...) when empty?(rest) : w + width$ != () : FPE(form, "Expected a single width specifier here.") + + ;Error if not a type + type! = (?t:#type) : t + type! != () : FPE(form, "Expected a type here.") + + ;Error if not a vec type + vectype! = (?t:#type!) : + FPE(form, "Expected a vector type here.") when t not-typeof VectorType + t + + ;Error if not an expression + exp! = (?e:#exp) : e + exp! != () : FPE(form, "Expected an expression here.") + + ;Error if not a single expression + exp$ = (?e:#exp ?rest ...) when empty?(rest) : e + exp$ != () : FPE(form, "Expected a single expression here.") + + ;Error if not a stmt + stmt! = (?s:#stmt) : s + stmt! != () : FPE(form, "Expected a statement here.") + + ;Error if not a reference expression + ref! = (?e:#exp!) : + FPE(form, "Expected a reference expression here.") when e not-typeof Ref + e + + ;Main Circuit Production defrule circuit : - circuit = (circuit ?name:#symbol : (?modules:#module ... ?rest ...)) : + circuit = (circuit ?name:#id! #:! (?ms:#module ... ?rest ...)) : if not empty?(rest) : - throw-error("Expected module here: ~" << [rest]) - Circuit(modules, name) + FPE(rest, "Expected a module declaration here.") + Circuit(ms, name) + circuit != (circuit) : + FPE(form, "Invalid syntax for circuit definition.") + ;Main Module Production defrule module : - module = (module ?name:#symbol : (?ports:#port ... ?body:#comm ... ?rest ...)) : + module = (module ?name:#id! #:! (?ps:#port ... ?cs:#stmt ... ?rest ...)) : + if not empty?(rest) : + FPE(rest, "Expected a statement here.") + Module(name, ps, Begin(cs)) + module != (module) : + FPE(form, "Invalid syntax for module definition.") + + defrule port : + port = (input ?name:#id! #:! ?type:#type!) : Port(name, INPUT, type) + port = (output ?name:#id! #:! ?type:#type!) : Port(name, OUTPUT, type) + + ;Main Type Productions + defrule type : + inttype = (UInt<?w:#width$>) : UIntType(w) + inttype = (UInt) : UIntType(UnknownWidth()) + inttype = (SInt<?w:#width$>) : SIntType(w) + inttype = (SInt) : SIntType(UnknownWidth()) + + type = (?t:#typeterm ?ops:#typeop ...) : apply-suffix-ops(t, ops) + typeop = ((@get ?size:#int$)) : (fn (t) : VectorType(t, size)) + + typeterm = (?t:#inttype) : t + typeterm = ({?fs:#field ... ?rest ...}) : if not empty?(rest) : - throw-error("Expected command here: ~" << [rest]) - Module(name, ports, Begin(body)) + FPE(rest, "Expected a bundle field declaration here.") + BundleType(fs) defrule field : - field = (?name:#symbol : ?type:#type) : - Field(ut(name), DEFAULT, type) - field = (flip ?name:#symbol : ?type:#type) : - Field(ut(name), REVERSE, type) + field = (flip ?name:#id! #:! ?type:#type!) : Field(name, REVERSE, type) + field = (?name:#id #:! ?type:#type!) : Field(name, DEFAULT, type) - defrule port : - port = (input ?name:#symbol : ?type:#type) : - Port(ut(name), INPUT, type) - port = (output ?name:#symbol : ?type:#type) : - Port(ut(name), OUTPUT, type) + defrule width : + width = (?x:#int) : IntWidth(x) + width = (?) : UnknownWidth() - defrule type : - type = (?type:#type (@get ?size:#int)) : - VectorType(type, ut(size)) - type = (UInt (@do ?width:#int)) : - UIntType(IntWidth(ut(width))) - type = (UInt) : - UIntType(UnknownWidth()) - type = (SInt (@do ?width:#int)) : - SIntType(IntWidth(ut(width))) - type = (SInt) : - SIntType(UnknownWidth()) - type = ({?fields:#field ...}) : - BundleType(fields) - - defrule comm : - comm = (wire ?name:#symbol : ?type:#type) : - DefWire(ut(name), type) - comm = (reg ?name:#symbol : ?type:#type) : - DefRegister(ut(name), type) - comm = (mem ?name:#symbol : ?type:#type) : - DefMemory(ut(name), type) - comm = (inst ?name:#symbol of ?module:#exp) : - DefInstance(ut(name), module) - comm = (node ?name:#symbol = ?exp:#exp) : - DefNode(ut(name), exp) - comm = (accessor ?name:#symbol = ?source:#exp (@get ?index:#exp)) : - DefAccessor(ut(name), source, index) - comm = ((?body:#comm ...)) : - Begin(body) - comm = (?x:#exp := ?y:#exp) : - Connect(x, y) - comm = (?c:skip) : - EmptyStmt() - comm = (?c:#comm/when) : - c + ;Main Statement Productions + defrule statements : + stmt = (wire ?name:#id! #:! ?t:#type!) : DefWire(name, t) + stmt = (reg ?name:#id! #:! ?t:#type!) : DefRegister(name, t) + stmt = (mem ?name:#id! #:! ?t:#vectype!) : DefMemory(name, t) + stmt = (inst ?name:#id! #of! ?m:#ref!) : DefInstance(name, m) + stmt = (node ?name:#id! #=! ?e:#exp!) : DefNode(name, e) + stmt = (accessor ?name:#id! #=! ?s:#exp![?i:#exp$]) : DefAccessor(name, s, i) + stmt = (?s:#stmt/when) : s + + stmt = (?x:#exp := ?y:#exp!) : Connect(x, y) + stmt = (on-reset ?x:#exp := ?y:#exp!) : OnReset(x, y) + + stmt = ((?s:#stmt ?ss:#stmt ... ?rest ...)) : + if not empty?(rest) : + FPE(rest, "Expected a statement here.") + Begin(List(s, ss)) + stmt = (()) : + Begin(List()) - defrule comm/when : - comm/when = (when ?pred:#exp : ?conseq:#comm else : ?alt:#comm) : + defrule stmt/when : + stmt/when = (when ?pred:#exp! #:! ?conseq:#stmt! else ?alt:#stmt/when) : Conditionally(pred, conseq, alt) - comm/when = (when ?pred:#exp : ?conseq:#comm else ?alt:#comm/when) : + stmt/when = (when ?pred:#exp! #:! ?conseq:#stmt! else #:! ?alt:#stmt!) : Conditionally(pred, conseq, alt) - comm/when = (when ?pred:#exp : ?conseq:#comm) : + stmt/when = (when ?pred:#exp! #:! ?conseq:#stmt!) : Conditionally(pred, conseq, EmptyStmt()) + ;Main Expressions defrule exp : - exp = (?x:#exp . ?f:#int) : - Index(x, ut(f), UnknownType()) - exp = (?x:#exp . ?f:#symbol) : - Subfield(x, ut(f), UnknownType()) - exp = (?x:#exp-form) : - x - - val operators = HashTable<Symbol, PrimOp>(symbol-hash) - operators[`add] = ADD-OP - operators[`add-uu] = ADD-UU-OP - operators[`add-us] = ADD-US-OP - operators[`add-su] = ADD-SU-OP - operators[`add-ss] = ADD-SS-OP - operators[`sub] = SUB-OP - operators[`sub-uu] = SUB-UU-OP - operators[`sub-us] = SUB-US-OP - operators[`sub-su] = SUB-SU-OP - operators[`sub-ss] = SUB-SS-OP - operators[`mul] = MUL-OP - operators[`mul-uu] = MUL-UU-OP - operators[`mul-us] = MUL-US-OP - operators[`mul-su] = MUL-SU-OP - operators[`mul-ss] = MUL-SS-OP - operators[`div] = DIV-OP - operators[`div-uu] = DIV-UU-OP - operators[`div-us] = DIV-US-OP - operators[`div-su] = DIV-SU-OP - operators[`div-ss] = DIV-SS-OP - operators[`mod] = MOD-OP - operators[`mod-uu] = MOD-UU-OP - operators[`mod-us] = MOD-US-OP - operators[`mod-su] = MOD-SU-OP - operators[`mod-ss] = MOD-SS-OP - operators[`quo] = QUO-OP - operators[`quo-uu] = QUO-UU-OP - operators[`quo-us] = QUO-US-OP - operators[`quo-su] = QUO-SU-OP - operators[`quo-ss] = QUO-SS-OP - operators[`rem] = REM-OP - operators[`rem-uu] = REM-UU-OP - operators[`rem-us] = REM-US-OP - operators[`rem-su] = REM-SU-OP - operators[`rem-ss] = REM-SS-OP - operators[`add-wrap] = ADD-WRAP-OP - operators[`add-wrap-uu] = ADD-WRAP-UU-OP - operators[`add-wrap-us] = ADD-WRAP-US-OP - operators[`add-wrap-su] = ADD-WRAP-SU-OP - operators[`add-wrap-ss] = ADD-WRAP-SS-OP - operators[`sub-wrap] = SUB-WRAP-OP - operators[`sub-wrap-uu] = SUB-WRAP-UU-OP - operators[`sub-wrap-us] = SUB-WRAP-US-OP - operators[`sub-wrap-su] = SUB-WRAP-SU-OP - operators[`sub-wrap-ss] = SUB-WRAP-SS-OP - operators[`lt] = LESS-OP - operators[`lt-uu] = LESS-UU-OP - operators[`lt-us] = LESS-US-OP - operators[`lt-su] = LESS-SU-OP - operators[`lt-ss] = LESS-SS-OP - operators[`leq] = LESS-EQ-OP - operators[`leq-uu] = LESS-EQ-UU-OP - operators[`leq-us] = LESS-EQ-US-OP - operators[`leq-su] = LESS-EQ-SU-OP - operators[`leq-ss] = LESS-EQ-SS-OP - operators[`gt] = GREATER-OP - operators[`gt-uu] = GREATER-UU-OP - operators[`gt-us] = GREATER-US-OP - operators[`gt-su] = GREATER-SU-OP - operators[`gt-ss] = GREATER-SS-OP - operators[`geq] = GREATER-EQ-OP - operators[`geq-uu] = GREATER-EQ-UU-OP - operators[`geq-us] = GREATER-EQ-US-OP - operators[`geq-su] = GREATER-EQ-SU-OP - operators[`geq-ss] = GREATER-EQ-SS-OP - operators[`eq] = EQUAL-OP - operators[`eq-uu] = EQUAL-UU-OP - operators[`eq-ss] = EQUAL-SS-OP - operators[`neq] = NEQUAL-OP - operators[`neq-uu] = NEQUAL-UU-OP - operators[`neq-ss] = NEQUAL-SS-OP - operators[`mux] = MUX-OP - operators[`mux-uu] = MUX-UU-OP - operators[`mux-ss] = MUX-SS-OP - operators[`pad] = PAD-OP - operators[`pad-u] = PAD-U-OP - operators[`pad-s] = PAD-S-OP - operators[`as-UInt] = AS-UINT-OP - operators[`as-UInt-u] = AS-UINT-U-OP - operators[`as-UInt-s] = AS-UINT-S-OP - operators[`as-SInt] = AS-SINT-OP - operators[`as-SInt-u] = AS-SINT-U-OP - operators[`as-SInt-s] = AS-SINT-S-OP - operators[`shl] = SHIFT-LEFT-OP - operators[`shl-u] = SHIFT-LEFT-U-OP - operators[`shl-s] = SHIFT-LEFT-S-OP - operators[`shr] = SHIFT-RIGHT-OP - operators[`shr-u] = SHIFT-RIGHT-U-OP - operators[`shr-s] = SHIFT-RIGHT-S-OP - operators[`convert] = CONVERT-OP - operators[`convert-u] = CONVERT-U-OP - operators[`convert-s] = CONVERT-S-OP - operators[`neg] = NEG-OP - operators[`neg-u] = NEG-U-OP - operators[`neg-s] = NEG-S-OP - operators[`bit-not] = BIT-NOT-OP - operators[`bit-and] = BIT-AND-OP - operators[`bit-or] = BIT-OR-OP - operators[`bit-xor] = BIT-XOR-OP - operators[`cat] = CONCAT-OP - operators[`bit] = BIT-SELECT-OP - operators[`bits] = BITS-SELECT-OP - operators[`bit-and-reduce] = BIT-AND-REDUCE-OP - operators[`bit-or-reduce] = BIT-OR-REDUCE-OP - operators[`bit-xor-reduce] = BIT-XOR-REDUCE-OP + ;Suffix Operators + exp = (?x:#expterm ?ops:#expop ...) : apply-suffix-ops(x, ops) + expop = ((@get ?f:#int)) : (fn (x) : Index(x, f, UnknownType())) + expop = (. ?f:#id!) : (fn (x) : Subfield(x, f, UnknownType())) + + ;Prefix Operators + expterm = (?t:#inttype(?v:#int$)) : + match(t) : + (t:UIntType) : UIntValue(v, width(t)) + (t:SIntType) : SIntValue(v, width(t)) - defrule width : - width = (?) : - UnknownWidth() - width = (?width:#int) : - IntWidth(ut(width)) - - defrule exp-form : - exp-form = (UInt (@do ?value:#int ?width:#width)) : - UIntValue(ut(value), width) - exp-form = (UInt (@do ?value:#int)) : - UIntValue(ut(value), UnknownWidth()) - exp-form = (SInt (@do ?value:#int ?width:#width)) : - SIntValue(ut(value), width) - exp-form = (SInt (@do ?value:#int)) : - SIntValue(ut(value), UnknownWidth()) - exp-form = (WritePort (@do ?mem:#exp ?index:#exp ?enable:#exp)) : - WritePort(mem, index, UnknownType(), enable) - exp-form = (ReadPort (@do ?mem:#exp ?index:#exp ?enable:#exp)) : - ReadPort(mem, index, UnknownType(), enable) - exp-form = (Register (@do ?value:#exp ?enable:#exp)) : - Register(UnknownType(),value,enable) - exp-form = (Pad (@do ?value:#exp ?width:#width)) : - Pad(value,width,UnknownType()) - exp-form = (?op:#symbol (@do ?es:#exp ... ?ints:#int ...)) : - println("Op-symbol is:~" % [op]) - match(get?(operators, ut(op), false)) : - (op:PrimOp) : - ;println("Op is:~ ~ ~" % [op,op == ADD-OP, op == ADD-UU-OP]) - DoPrim(op, es, map(ut, ints), UnknownType()) - (f:False) : - throw-error $ string-join $ [ - "Invalid operator: " op] - exp-form = (?x:#symbol) : - Ref(ut(x), UnknownType()) + expterm = (WritePort(?m:#exp, ?i:#exp, ?e:#exp)) : WritePort(m, i, UnknownType(), e) + expterm != (WritePort) : FPE(form, "Invalid syntax for WritePort expression.") + + expterm = (ReadPort(?m:#exp, ?i:#exp, ?e:#exp)) : ReadPort(m, i, UnknownType(), e) + expterm != (ReadPort) : FPE(form, "Invalid syntax for ReadPort expression.") + + expterm = (Register(?v:#exp, ?e:#exp)) : Register(UnknownType(), v, e) + expterm != (Register) : FPE(form, "Invalid syntax for Register expression.") + + expterm = (Pad(?e:#exp, ?w:#width$)) : Pad(e,w,UnknownType()) + expterm != (Pad) : FPE(form, "Invalid syntax for Pad expression.") + + expterm = (?op:#sym(?es:#exp ... ?ints:#int ... ?rest ...)) : + if not empty?(rest) : + FPE(rest, "Illegal operands to primitive operator.") + match(primop(op)) : + (p:PrimOp) : DoPrim(p, es, ints, UnknownType()) + (p:False) : FPE(form, "Unrecognized primitive operator '~'." << [op]) + expterm = (?op:#sym) : + Ref(op, UnknownType()) public defn parse-firrtl (forms:List) : with-syntax(firrtl) : match-syntax(forms) : - (?c:#circuit) : - c + (?c:#circuit) : c + (_ ...) : FPE(form, "Invalid firrtl circuit.") + +public defn parse-firrtl-file (filename:String) : + parse-firrtl(lex-file(filename)) diff --git a/src/main/stanza/ir-utils.stanza b/src/main/stanza/ir-utils.stanza index 91e49123..1131c1b3 100644 --- a/src/main/stanza/ir-utils.stanza +++ b/src/main/stanza/ir-utils.stanza @@ -129,18 +129,18 @@ defmethod print (o:OutputStream, op:PrimOp) : BIT-AND-OP : "bit-and" BIT-OR-OP : "bit-or" BIT-XOR-OP : "bit-xor" - CONCAT-OP : "cat" - BIT-SELECT-OP : "bit" - BITS-SELECT-OP : "bits" BIT-AND-REDUCE-OP : "bit-and-reduce" BIT-OR-REDUCE-OP : "bit-or-reduce" BIT-XOR-REDUCE-OP : "bit-xor-reduce" + CONCAT-OP : "cat" + BIT-SELECT-OP : "bit" + BITS-SELECT-OP : "bits" defmethod print (o:OutputStream, e:Expression) : match(e) : (e:Ref) : print(o, name(e)) (e:Subfield) : print-all(o, [exp(e) "." name(e)]) - (e:Index) : print-all(o, [exp(e) "." value(e)]) + (e:Index) : print-all(o, [exp(e) "[" value(e) "]"]) (e:UIntValue) : print-all(o, ["UInt(" value(e) ")"]) (e:SIntValue) : print-all(o, ["SInt(" value(e) ")"]) (e:DoPrim) : @@ -179,6 +179,8 @@ defmethod print (o:OutputStream, c:Stmt) : do(print{o,_}, join(body(c), "\n")) (c:Connect) : print-all(o, [loc(c) " := " exp(c)]) + (c:OnReset) : + print-all(o, ["on-reset " loc(c) " := " exp(c)]) (c:EmptyStmt) : print(o, "skip") print-debug(o,c) @@ -190,11 +192,11 @@ defmethod print (o:OutputStream, t:Type) : (t:UIntType) : match(width(t)) : (w:UnknownWidth) : print-all(o, ["UInt"]) - (w) : print-all(o, ["UInt(" width(t) ")"]) + (w) : print-all(o, ["UInt<" width(t) ">"]) (t:SIntType) : match(width(t)) : (w:UnknownWidth) : print-all(o, ["SInt"]) - (w) : print-all(o, ["SInt(" width(t) ")"]) + (w) : print-all(o, ["SInt<" width(t) ">"]) (t:BundleType) : print(o, "{") print-all(o, join(fields(t), ", ")) @@ -258,6 +260,7 @@ defmethod map (f: Expression -> Expression, c:Stmt) -> Stmt : (c:DefInstance) : DefInstance(name(c), f(module(c))) (c:Conditionally) : Conditionally(f(pred(c)), conseq(c), alt(c)) (c:Connect) : Connect(f(loc(c)), f(exp(c))) + (c:OnReset) : OnReset(f(loc(c)),f(exp(c))) (c) : c public defmulti map<?T> (f: Stmt -> Stmt, c:?T&Stmt) -> T diff --git a/src/main/stanza/passes.stanza b/src/main/stanza/passes.stanza index 1267d5f3..1b76b949 100644 --- a/src/main/stanza/passes.stanza +++ b/src/main/stanza/passes.stanza @@ -40,12 +40,6 @@ defstruct WRef <: Expression : kind: Kind gender: Gender with: (as-method => true) -defstruct WRegInit <: Expression : - reg: Expression - name: Symbol - type: Type with: (as-method => true) - gender: Gender with: (as-method => true) - defstruct WSubfield <: Expression : exp: Expression name: Symbol @@ -123,7 +117,6 @@ defn times (f1:Flip,f2:Flip) -> Flip : REVERSE : swap(f1) defn to-field (p:Port) -> Field : - Field(name(p),REVERSE,type(p)) if direction(p) == OUTPUT : Field(name(p),REVERSE,type(p)) else if direction(p) == INPUT : Field(name(p),DEFAULT,type(p)) else : error("Shouldn't be here") @@ -182,7 +175,7 @@ defmethod print (o:OutputStream, k:Kind) : (k:WriteAccessorKind) : "wacc" defn hasGender (e:Expression|Stmt|Type|Port|Field) : - e typeof WRef|WSubfield|WIndex|WDefAccessor|WRegInit + e typeof WRef|WSubfield|WIndex|WDefAccessor defn hasWidth (e:Expression|Stmt|Type|Port|Field) : e typeof UIntType|SIntType|UIntValue|SIntValue|Pad @@ -190,7 +183,7 @@ defn hasWidth (e:Expression|Stmt|Type|Port|Field) : defn hasType (e:Expression|Stmt|Type|Port|Field) : e typeof Ref|Subfield|Index|DoPrim|WritePort|ReadPort|WRef|WSubfield |WIndex|DefWire|DefRegister|DefMemory|Register - |VectorType|Port|Field|WRegInit|Pad + |VectorType|Port|Field|Pad defn hasKind (e:Expression|Stmt|Type|Port|Field) : e typeof WRef @@ -219,16 +212,12 @@ defmethod print (o:OutputStream, e:WRef) : print(o,name(e)) print-debug(o,e as ?) -defmethod print (o:OutputStream, e:WRegInit) : - print-all(o,[name(e)]) - print-debug(o,e as ?) - defmethod print (o:OutputStream, e:WSubfield) : print-all(o,[exp(e) "." name(e)]) print-debug(o,e as ?) defmethod print (o:OutputStream, e:WIndex) : - print-all(o,[exp(e) "." value(e)]) + print-all(o,[exp(e) "[" value(e) "]"]) print-debug(o,e as ?) defmethod print (o:OutputStream, s:WDefAccessor) : @@ -243,8 +232,6 @@ defmethod print (o:OutputStream, c:ConnectFromIndexed) : print-all(o, [loc(c) " := " exps(c) "[" index(c) "]"]) print-debug(o,c as ?) -defmethod map (f: Expression -> Expression, e: WRegInit) : - WRegInit(f(reg(e)), name(e), type(e), gender(e)) defmethod map (f: Expression -> Expression, e: WSubfield) : WSubfield(f(exp(e)), name(e), type(e), gender(e)) defmethod map (f: Expression -> Expression, e: WIndex) : @@ -259,8 +246,6 @@ defmethod map (f: Expression -> Expression, c:ConnectFromIndexed) : defmethod map (f: Type -> Type, e: WRef) : WRef(name(e), f(type(e)), kind(e), gender(e)) -defmethod map (f: Type -> Type, e: WRegInit) : - WRegInit(reg(e), name(e), f(type(e)), gender(e)) defmethod map (f: Type -> Type, e: WSubfield) : WSubfield(exp(e), name(e), f(type(e)), gender(e)) defmethod map (f: Type -> Type, e: WIndex) : @@ -303,9 +288,7 @@ defn to-working-ir (c:Circuit) : defn to-exp (e:Expression) : match(map(to-exp,e)) : (e:Ref) : WRef(name(e), type(e), NodeKind(), UNKNOWN-GENDER) - (e:Subfield) : - if name(e) == `init : WRegInit(exp(e), to-symbol("~.init" % [name(exp(e) as WRef)]), type(e), UNKNOWN-GENDER) - else : WSubfield(exp(e), name(e), type(e), UNKNOWN-GENDER) + (e:Subfield) : WSubfield(exp(e), name(e), type(e), UNKNOWN-GENDER) (e:Index) : WIndex(exp(e), value(e), type(e), UNKNOWN-GENDER) (e) : e defn to-stmt (s:Stmt) : @@ -450,7 +433,6 @@ defn infer-exp-types (e:Expression, l:List<KeyValue<Symbol,Type>>) -> Expression match(r) : (e:WRef) : WRef(name(e), get-type(name(e),l),kind(e),gender(e)) (e:WSubfield) : WSubfield(exp(e),name(e), bundle-field-type(type(exp(e)),name(e)),gender(e)) - (e:WRegInit) : WRegInit(reg(e),name(e),get-type(name(reg(e) as WRef),l),gender(e)) (e:WIndex) : WIndex(exp(e),value(e), get-vector-subtype(type(exp(e))),gender(e)) (e:DoPrim) : lower-and-type-primop(e) ;DoPrim(op(e),args(e),consts(e),get-primop-rettype(e)) @@ -480,7 +462,7 @@ defn infer-types (s:Stmt, l:List<KeyValue<Symbol,Type>>) -> [Stmt List<KeyValue< val [s*,l*] = infer-types(conseq(s),l) val [s**,l**] = infer-types(alt(s),l) [Conditionally(pred(s),s*,s**),l] - (s:Connect|EmptyStmt) : [s,l] + (s:Connect|OnReset|EmptyStmt) : [s,l] defn infer-types (m:Module, l:List<KeyValue<Symbol,Type>>) -> Module : val ptypes = @@ -568,6 +550,8 @@ defn resolve-genders (c:Circuit) : WDefAccessor(name(s),source*,index*,gender*) (s:Connect) : Connect(resolve-expr(loc(s),FEMALE),resolve-expr(exp(s),MALE)) + (s:OnReset) : + OnReset(resolve-expr(loc(s),FEMALE),resolve-expr(exp(s),MALE)) (s:Conditionally) : val pred* = resolve-expr(pred(s),MALE) val conseq* = resolve-stmt(conseq(s)) @@ -582,11 +566,6 @@ defn resolve-genders (c:Circuit) : WRef{name(e),type(e),kind(e),_} $ if gender == BI-GENDER : desired else : gender - (e:WRegInit) : - val gender = get-gender(name(reg(e) as WRef),desired) - WRegInit{reg(e),name(e),type(e),_} $ - if gender == BI-GENDER : desired - else : gender (e:WSubfield) : val field-flip = bundle-field-flip(name(e),type(exp(e))) val exp* = resolve-expr(exp(e),field-flip * desired) @@ -705,7 +684,6 @@ defn lower (body:Stmt, table:HashTable<Symbol,List<KeyValue<Expression,Flip>>>) defn calc-gender (g:Gender, e:Expression) -> Gender : match(e) : (e:WRef) : gender(e) - (e:WRegInit) : gender(e) (e:WSubfield) : if is-instance(exp(e)) : gender(e) else : calc-gender(bundle-field-flip(name(e),type(exp(e))) * g,exp(e)) @@ -725,6 +703,16 @@ defn lower (body:Stmt, table:HashTable<Symbol,List<KeyValue<Expression,Flip>>>) DefWire(name(s),type(value(s))), Connect(WRef(name(s),type(value(s)),NodeKind(),FEMALE),value(s))) lower-stmt(s*) + (s:OnReset) : Begin{_} $ + for (l in expand-expr(loc(s)), r in expand-expr(exp(s))) map : + println-debug(s) + val lgender = calc-gender(FEMALE,loc(s)) * value(l) + val rgender = calc-gender(MALE,exp(s)) * value(r) + println-debug(loc(s)) + println-debug(exp(s)) + switch fn ([x,y]) : lgender == x and rgender == y : + [FEMALE,MALE] : OnReset(key(l),key(r)) + [MALE,FEMALE] : OnReset(key(r),key(l)) (s:Connect) : Begin{_} $ for (l in expand-expr(loc(s)), r in expand-expr(exp(s))) map : println-debug(s) @@ -779,7 +767,6 @@ defn lower (body:Stmt, table:HashTable<Symbol,List<KeyValue<Expression,Flip>>>) defn expand-expr (e:Expression) -> List<KeyValue<Expression,Flip>> : match(e) : (e:WRef) : table[name(e)] - (e:WRegInit) : table[name(e)] (e:WSubfield) : val exps = expand-expr(exp(e)) val begin = index-of-elem(type(exp(e)) as BundleType,name(e)) @@ -827,12 +814,7 @@ defn lower-module (m:Module,table:HashTable<Symbol,List<KeyValue<Expression,Flip (s:DefWire) : table[name(s)] = get-entries(name(s),type(s)) (s:DefRegister) : val regs = get-entries(name(s),type(s)) - val init-sym = symbol-join([name(s),`\|.init|]) - val init-regs = for r in regs map : - val [e f] = [key(r) value(r)] - WRegInit(e,symbol-join([name(e),`\|.init|]),type(e),gender(e)) => f table[name(s)] = regs - table[init-sym] = init-regs (s:DefInstance) : val r = WRef(name(s),type(module(s)),InstanceKind(),FEMALE) val ports = table[name(module(s) as WRef)] @@ -918,70 +900,70 @@ defn expand-connect-indexed (c: Circuit) -> Circuit : ; This ensures proper behavior if this pass is run multiple ; times. -defn initialize-registers (c:Circuit) : - defn to-wire-name (y:Symbol) : symbol-join([ y "$init"]) - defn add-when (s:Stmt,h:HashTable<Symbol,Type>) -> Stmt : - var inits = List<Stmt>() - for kv in h do : - val refreg = WRef(key(kv),value(kv),RegKind(),FEMALE) - val refwire = WRef(to-wire-name(key(kv)),value(kv),NodeKind(),MALE) - val connect = Connect(refreg,refwire) - inits = append(inits,list(connect)) - if empty?(inits) : s - else : - val pred = WRef(`reset, UIntType(IntWidth(1)), PortKind(), MALE) - val when-reset = Conditionally(pred,Begin(inits),Begin(List<Stmt>())) - Begin(list(s,when-reset)) - - defn rename (s:Stmt,h:HashTable<Symbol,True|False>) -> [Stmt HashTable<Symbol,Type>] : - val t = HashTable<Symbol,Type>(symbol-hash) - defn rename-expr (e:Expression) -> Expression : - match(map(rename-expr,e)) : - (e:WRegInit) : - val new-name = to-wire-name(name(reg(e) as WRef)) - WRef(new-name,type(reg(e)),RegKind(),gender(e)) - (e) : e - defn rename-stmt (s:Stmt) -> Stmt : - match(map(rename-stmt,s)) : - (s:DefRegister) : - if h[name(s)] : - t[name(s)] = type(s) - Begin(list(s,DefWire(to-wire-name(name(s)),type(s)))) - else : s - (s) : map(rename-expr,s) - [rename-stmt(s) t] - - defn init? (y:Symbol,s:Stmt) -> True|False : - var used? = false - defn has? (e:Expression) -> Expression : - match(map(has?,e)) : - (e:WRegInit) : - if name(reg(e) as WRef) == y : used? = true - (e) : map(has?,e) - e - map(has?,s) - used? - - defn using-init (s:Stmt,h:HashTable<Symbol,True|False>) -> Stmt : - match(s) : - (s:DefRegister) : h[name(s)] = false - (s) : - for x in h do : - h[key(x)] = value(x) or init?(key(x),s) - map(using-init{_,h},s) - - defn explicit-init-scope (s:Stmt) -> Stmt : - val h = HashTable<Symbol,True|False>(symbol-hash) - using-init(s,h) - ;println-debug(h) - val [s* t] = rename(s,h) - add-when(s*,t) - - Circuit(modules*, main(c)) where : - val modules* = - for m in modules(c) map : - Module(name(m), ports(m), body*) where : - val body* = explicit-init-scope(body(m)) +;defn initialize-registers (c:Circuit) : +; defn to-wire-name (y:Symbol) : symbol-join([ y "$init"]) +; defn add-when (s:Stmt,h:HashTable<Symbol,Type>) -> Stmt : +; var inits = List<Stmt>() +; for kv in h do : +; val refreg = WRef(key(kv),value(kv),RegKind(),FEMALE) +; val refwire = WRef(to-wire-name(key(kv)),value(kv),NodeKind(),MALE) +; val connect = Connect(refreg,refwire) +; inits = append(inits,list(connect)) +; if empty?(inits) : s +; else : +; val pred = WRef(`reset, UIntType(IntWidth(1)), PortKind(), MALE) +; val when-reset = Conditionally(pred,Begin(inits),Begin(List<Stmt>())) +; Begin(list(s,when-reset)) +; +; defn rename (s:Stmt,h:HashTable<Symbol,True|False>) -> [Stmt HashTable<Symbol,Type>] : +; val t = HashTable<Symbol,Type>(symbol-hash) +; defn rename-expr (e:Expression) -> Expression : +; match(map(rename-expr,e)) : +; (e:WRegInit) : +; val new-name = to-wire-name(name(reg(e) as WRef)) +; WRef(new-name,type(reg(e)),RegKind(),gender(e)) +; (e) : e +; defn rename-stmt (s:Stmt) -> Stmt : +; match(map(rename-stmt,s)) : +; (s:DefRegister) : +; if h[name(s)] : +; t[name(s)] = type(s) +; Begin(list(s,DefWire(to-wire-name(name(s)),type(s)))) +; else : s +; (s) : map(rename-expr,s) +; [rename-stmt(s) t] +; +; defn init? (y:Symbol,s:Stmt) -> True|False : +; var used? = false +; defn has? (e:Expression) -> Expression : +; match(map(has?,e)) : +; (e:WRegInit) : +; if name(reg(e) as WRef) == y : used? = true +; (e) : map(has?,e) +; e +; map(has?,s) +; used? +; +; defn using-init (s:Stmt,h:HashTable<Symbol,True|False>) -> Stmt : +; match(s) : +; (s:DefRegister) : h[name(s)] = false +; (s) : +; for x in h do : +; h[key(x)] = value(x) or init?(key(x),s) +; map(using-init{_,h},s) +; +; defn explicit-init-scope (s:Stmt) -> Stmt : +; val h = HashTable<Symbol,True|False>(symbol-hash) +; using-init(s,h) +; ;println-debug(h) +; val [s* t] = rename(s,h) +; add-when(s*,t) +; +; Circuit(modules*, main(c)) where : +; val modules* = +; for m in modules(c) map : +; Module(name(m), ports(m), body*) where : +; val body* = explicit-init-scope(body(m)) ;;================ EXPAND WHENS ============================= ; This pass does three things: remove last connect semantics, @@ -1018,7 +1000,6 @@ defmethod equal? (e1:Expression,e2:Expression) -> True|False : else : false (e1:WRef,e2:WRef) : name(e1) == name(e2) ;(e1:DoPrim,e2:DoPrim) : TODO - (e1:WRegInit,e2:WRegInit) : reg(e1) == reg(e2) and name(e1) == name(e2) (e1:WSubfield,e2:WSubfield) : name(e1) == name(e2) (e1:Pad,e2:Pad) : width(e1) == width(e2) and value(e1) == value(e2) (e1:DoPrim,e2:DoPrim) : @@ -1146,15 +1127,15 @@ defn remove-nul (sv:SymbolicValue) -> SymbolicValue : (c:SVNul,a) : a (c,a) : sv (sv) : sv -defn to-exp (sv:SymbolicValue) -> Expression : +defn to-exp (sv:SymbolicValue) -> Expression|False : match(remove-nul(sv)) : (sv:SVMux) : DoPrim(MUX-UU-OP, - list(pred(sv),to-exp(conseq(sv)),to-exp(alt(sv))), + list(pred(sv),to-exp(conseq(sv)) as Expression,to-exp(alt(sv)) as Expression), list(), UIntType(IntWidth(1))) (sv:SVExp) : exp(sv) - (sv) : error("Shouldn't be here") + (sv:SVNul) : false defn reduce-or (l:List<True|False>) -> True|False : if length(l) == 0 : false else : head(l) or reduce-or(tail(l)) @@ -1169,58 +1150,76 @@ defn reduce-or (l:List<Expression>) -> Expression : ; 1) Build Table, Build Declaration List -defn expand-whens (assign:HashTable<Symbol,SymbolicValue>, - kinds:HashTable<Symbol,Kind>, - stmts:HashTable<Symbol,Stmt>, - decs:Vector<Stmt>, - enables:HashTable<Symbol,SymbolicValue>) -> Stmt : - - for x in assign do : - val [n sv] = [key(x) value(x)] - match(kinds[n]) : - (k:WriteAccessorKind) : - ;First create WritePort and assign from accessor-turned-wire - val s = stmts[n] as WDefAccessor - val t = type(type(source(s)) as VectorType) - val ref = WRef(n,t,k,MALE) - val wp = WritePort(source(s),index(s),t,to-exp(enables[n])) - add(decs,Connect(wp,ref)) - ;If initialized, assign input to accessor-turned-wire - val sv = remove-nul(assign[n]) - if sv == SVNul : println("Uninitialized: ~" % [to-string(n)]) ;TODO actually collect error - else : add(decs,Connect(ref,to-exp(sv))) - (k:ReadAccessorKind) : - val s = stmts[n] as WDefAccessor - val t = type(type(source(s)) as VectorType) - val ref = WRef(n,t,k,FEMALE) - val rp = ReadPort(source(s),index(s),t,to-exp(enables[n])) - add(decs,Connect(ref,rp)) - (k:RegKind) : - val s = stmts[n] as DefRegister - val ref = WRef(n,type(s),k,FEMALE) - val sv = remove-nul(assign[n]) - val reg = - if sv typeof SVNul : Register(type(s),UIntValue(0,width(type(s) as ?)),zero) - else : Register(type(s),to-exp(sv),to-exp(enables[n])) - add(decs,Connect(ref,reg)) - (k:InstanceKind) : - val s = stmts[n] as DefInstance - val x = to-symbol(split(to-string(n),'.')[0]) - val f = to-symbol(split(to-string(n),'.')[1]) - val ref = WRef(x,type(module(s)),k,FEMALE) - val sref = WSubfield(ref,f,bundle-field-type(type(module(s)),f),FEMALE) - if has-nul?(assign[n]) : println("Uninitialized: ~" % [to-string(n)]);TODO actually collect error - else : add(decs,Connect(sref,to-exp(assign[n]))) - (k) : - val s = stmts[n] as DefWire - val ref = WRef(n,type(s),k,FEMALE) - if has-nul?(assign[n]) : println("Uninitialized: ~" % [to-string(n)]);TODO actually collect error - else : add(decs,Connect(ref,to-exp(assign[n]))) - Begin(to-list(decs)) - -defn get-enables (assign:HashTable<Symbol,SymbolicValue>, - kinds:HashTable<Symbol,Kind>) -> HashTable<Symbol,SymbolicValue> : - defn get-read-enable (sym:Symbol,sv:SymbolicValue) -> Expression : +; assign: holds the symbolic value of a wref. +; resets: holds the symbolic value of connections under reset +; stmts: Used to hold the orignal type, as well as the mem/index for Write/ReadPorts +; kinds: Used to know the kind of reference, so we know whether we should error if it isn't initialized. We also know how we should declare the refernce. +; enables:Calculated off of assigns. + +; I think I'm going to restructure this so that not all information is held in the tables, but instead, we walk the graph again, and do stuff on declarations, and delete other stuff +defn expand-whens (s:Stmt, table:HashTable<Symbol,SymbolicValue>,decs:Vector<Stmt>,cons:Vector<Stmt>) -> Stmt : + match(map(expand-whens{_,table,decs,cons},s)) : + (s:DefNode|DefMemory) : add(decs,s) + (s:DefWire) : + add(decs,s) + add{cons,_} $ { + val ref = WRef(name(s),type(s),NodeKind(),FEMALE) + if has-nul?(table[name(s)]) : + println("Uninitialized: ~" % [to-string(name(s))]);TODO actually collect error + EmptyStmt() + else : Connect(ref,to-exp(table[name(s)]) as Expression) + }() + (s:DefRegister) : + add(decs,DefWire(name(s),type(s))) + add{cons,_} $ { + val ref = WRef(name(s),type(s),RegKind(),FEMALE) + val e = to-exp(table[name(s)]) + match(e) : + (e:False) : EmptyStmt() + (e:Expression) : Connect(ref,Register(type(s),e, to-exp(optimize $ get-write-enable(table[name(s)])) as Expression)) + }() + (s:WDefAccessor) : + val t = type(type(source(s)) as VectorType) + val n = name(s) + add(decs,DefWire(n,t)) + add{cons,_} $ { + switch {_ == gender(s)} : + MALE : + val ref = WRef(n,t,ReadAccessorKind(),FEMALE) + Begin $ list $ Connect(ref,ReadPort(source(s),index(s),t,get-read-enable(n,table))) + FEMALE : + val ref = WRef(n,t,WriteAccessorKind(),FEMALE) + val e = to-exp(table[n]) + val s* = match(e) : + (e:False) : + println("Uninitialized: ~" % [to-string(n)]) ;TODO actually collect error + EmptyStmt() + (e:Expression) : + Connect(ref,e) + val enable = (to-exp $ optimize $ get-write-enable(table[n])) as Expression + val wp = WritePort(source(s),index(s),t,enable as Expression) + Begin $ list(Connect(wp,ref),s*) + }() + (s:DefInstance) : + add(decs,s) + add{cons,_} $ Begin $ + for f in fields(type(module(s)) as BundleType) map : + if flip(f) == DEFAULT : + val n = to-symbol("~.~" % [name(s),name(f)]) ; only on inputs + val x = to-symbol(split(to-string(n),'.')[0]) + val f = to-symbol(split(to-string(n),'.')[1]) + val ref = WRef(x,type(module(s)),InstanceKind(),FEMALE) + val sref = WSubfield(ref,f,bundle-field-type(type(module(s)),f),FEMALE) + if has-nul?(table[n]) : + println("Uninitialized: ~" % [to-string(n)]);TODO actually collect error + EmptyStmt() + else : Connect(sref,to-exp(table[n]) as Expression) + else : EmptyStmt() + (s:Connect|Conditionally|OnReset|Begin|EmptyStmt) : false + s + +defn get-read-enable (sym:Symbol,table:HashTable<Symbol,SymbolicValue>) -> Expression : + defn get-single-read-enable (sym:Symbol,sv:SymbolicValue) -> Expression : defn active (e:Expression) -> True|False : match(e) : (e:WRef) : name(e) == sym @@ -1232,124 +1231,123 @@ defn get-enables (assign:HashTable<Symbol,SymbolicValue>, if active(exp(sv)) : one else : zero (sv: SVMux) : - val e0 = get-read-enable(sym,SVExp(pred(sv))) - val e1 = get-read-enable(sym,conseq(sv)) - val e2 = get-read-enable(sym,alt(sv)) + val e0 = get-single-read-enable(sym,SVExp(pred(sv))) + val e1 = get-single-read-enable(sym,conseq(sv)) + val e2 = get-single-read-enable(sym,alt(sv)) if e1 == e2 : OR(e0,e1) else : OR(e0,OR(AND(pred(sv),e1),AND(NOT(pred(sv)),e2))) + DoPrim{BIT-OR-OP,_,list(),UIntType(IntWidth(1))} $ to-list $ + for y in table stream : get-single-read-enable(sym,value(y)) - defn get-write-enable (sv:SymbolicValue) -> SymbolicValue : - match(map(get-write-enable,sv)) : - (sv: SVExp) : SVExp(one) - (sv: SVNul) : SVExp(zero) - (sv) : sv - - val enables = HashTable<Symbol,SymbolicValue>(symbol-hash) - for x in assign do : - val sym = key(x) - match(kinds[sym]) : - (k:ReadAccessorKind) : - enables[sym] = SVExp{_} $ reduce-or{_} $ to-list{_} $ - for y in assign stream : - get-read-enable(sym,value(y)) - (k:WriteAccessorKind) : enables[sym] = get-write-enable(value(x)) - (k:RegKind) : enables[sym] = get-write-enable(value(x)) - (k) : k - enables +defn get-write-enable (sv:SymbolicValue) -> SymbolicValue : + match(map(get-write-enable,sv)) : + (sv: SVExp) : SVExp(one) + (sv: SVNul) : SVExp(zero) + (sv) : sv + +defn merge-resets (assign:HashTable<Symbol,SymbolicValue>, resets:HashTable<Symbol,SymbolicValue>) -> HashTable<Symbol,SymbolicValue> : + val table = HashTable<Symbol,SymbolicValue>(symbol-hash) + val reset = WRef(`reset, UnknownType(), PortKind(), MALE) + for i in get-unique-keys(list(assign,resets)) do : + table[i] = match(get?(assign,i,false),get?(resets,i,false)) : + (a:SymbolicValue,r:SymbolicValue) : SVMux(reset,r,a) + (a:SymbolicValue,r:False) : a + (a:False,r:SymbolicValue) : SVMux(reset,r,SVNul()) + (a:False,r:False) : error("Shouldn't be here") + table defn build-tables (s:Stmt, assign:HashTable<Symbol,SymbolicValue>, - kinds:HashTable<Symbol,Kind>, - decs:Vector<Stmt>, - stmts:HashTable<Symbol,Stmt>) -> False : + resets:HashTable<Symbol,SymbolicValue>, + flattn:HashTable<Symbol,True|False>, + ) -> False : match(s) : - (s:DefWire) : - add(decs,s) - kinds[name(s)] = WireKind() - assign[name(s)] = SVNul() - stmts[name(s)] = s - (s:DefNode) : add(decs,s) - (s:DefRegister) : - add(decs,DefWire(name(s),type(s))) - kinds[name(s)] = RegKind() + (s:DefWire) : assign[name(s)] = SVNul() - stmts[name(s)] = s - (s:WDefAccessor) : - add(decs,DefWire(name(s),type(type(source(s)) as VectorType))) + flattn[name(s)] = true + (s:DefRegister|WDefAccessor) : assign[name(s)] = SVNul() - kinds[name(s)] = switch {_ == gender(s)} : - MALE : ReadAccessorKind() - FEMALE : WriteAccessorKind() - stmts[name(s)] = s - (s:DefInstance) : - add(decs,s) + flattn[name(s)] = false + (s:DefInstance) : ;TODO only add instance input ports. This probably involves correcting instance genders for f in fields(type(module(s)) as BundleType) do : - val n = to-symbol("~.~" % [name(s),name(f)]) ; only on inputs - println-all-debug(["In DefInst adding: " n]) - kinds[n] = InstanceKind() - assign[n] = SVNul() - stmts[n] = s - (s:DefMemory) : add(decs,s) + if flip(f) == DEFAULT : + println-all-debug(["Instance: " s " has input " f]) + val n = to-symbol("~.~" % [name(s),name(f)]) ; only on inputs + assign[n] = SVNul() + flattn[n] = true (s:Conditionally) : - val assign-c = deepcopy(assign) - val assign-a = deepcopy(assign) - build-tables(conseq(s),assign-c,kinds,decs,stmts) - build-tables(alt(s),assign-a,kinds,decs,stmts) - for i in get-unique-keys(list(assign-c,assign-a)) do : - assign[i] = match(get?(assign-c,i,false),get?(assign-a,i,false)) : ;TODO add to syntax highlighting + defn combine (flattn:HashTable<Symbol,True|False>, + table-c:HashTable<Symbol,SymbolicValue>, + table-a:HashTable<Symbol,SymbolicValue>, + i:Symbol) -> SymbolicValue|False : + match(get?(table-c,i,false),get?(table-a,i,false)) : (c:SymbolicValue,a:SymbolicValue) : if c == a : c else : SVMux(pred(s),c,a) - (c:SymbolicValue,a:False) : - if kinds[i] typeof WireKind|InstanceKind|NodeKind : c + (c:SymbolicValue,a:False) : + if flattn[i] : c else : SVMux(pred(s),c,SVNul()) - (c:False,a:SymbolicValue) : - if kinds[i] typeof WireKind|InstanceKind|NodeKind : a + (c:False,a:SymbolicValue) : + if flattn[i] : a else : SVMux(pred(s),SVNul(),a) - (c:False,a:False) : error("Shouldn't be here") - println-debug("TABLE-C") - for x in assign-c do : println-debug(x) - println-debug("TABLE-A") - for x in assign-a do : println-debug(x) - println-debug("TABLE") - for x in assign do : println-debug(x) - (s:Connect) : + (c:False,a:False) : false + + val assign-c = deepcopy(assign) + val assign-a = deepcopy(assign) + val resets-c = deepcopy(resets) + val resets-a = deepcopy(resets) + build-tables(conseq(s),assign-c,resets-c,flattn) + build-tables(alt(s),assign-a,resets-a,flattn) + for i in get-unique-keys(list(assign-c,assign-a)) do : + assign[i] = combine(flattn,assign-c,assign-a,i) as SymbolicValue + val r = combine(flattn,resets-c,resets-a,i) + match(r) : + (r:SymbolicValue) : resets[i] = r + (r) : false + ;println-debug("TABLE-C") + ;for x in assign-c do : println-debug(x) + ;println-debug("TABLE-A") + ;for x in assign-a do : println-debug(x) + ;println-debug("TABLE") + ;for x in assign do : println-debug(x) + (s:Connect|OnReset) : val key* = match(loc(s)) : (e:WRef) : name(e) (e:WSubfield) : symbol-join([name(exp(e) as ?) `. name(e)]) (e) : error("Shouldn't be here with ~" % [e]) - assign[key*] = SVExp(exp(s)); TODO, need to check all references are declared before this point - (s:Begin) : for s* in body(s) do: build-tables(s*,assign,kinds,decs,stmts) - (s) : false + if s typeof Connect : assign[key*] = SVExp(exp(s)) + if s typeof OnReset : resets[key*] = SVExp(exp(s)) + (s:Begin) : for s* in body(s) do: build-tables(s*,assign,resets,flattn) + (s:DefMemory|DefNode|EmptyStmt) : false defn expand-whens (m:Module) -> Module : val assign = HashTable<Symbol,SymbolicValue>(symbol-hash) - val decs = Vector<Stmt>() - val kinds = HashTable<Symbol,Kind>(symbol-hash) - val stmts = HashTable<Symbol,Stmt>(symbol-hash) + val resets = HashTable<Symbol,SymbolicValue>(symbol-hash) + val flattn = HashTable<Symbol,True|False>(symbol-hash) for p in ports(m) do : if direction(p) == OUTPUT : assign[name(p)] = SVNul() - kinds[name(p)] = PortKind() - stmts[name(p)] = DefWire(name(p),type(p)) + flattn[name(p)] = false - build-tables(body(m),assign,kinds,decs,stmts) - + build-tables(body(m),assign,resets,flattn) for x in assign do : assign[key(x)] = optimize(value(x)) - val enables = get-enables(assign,kinds) - for x in enables do : enables[key(x)] = optimize(value(x)) + for x in resets do : resets[key(x)] = optimize(value(x)) + ;val enables = get-enables(assign,kinds) + ;for x in enables do : enables[key(x)] = optimize(value(x)) - println-debug("Assigns") + println-debug("====== Assigns ======") for x in assign do : println-debug(x) - println-debug("Kinds") - for x in kinds do : println-debug(x) - println-debug("Decs") - for x in decs do : println-debug(x) - println-debug("Enables") - for x in enables do : println-debug(x) + println-debug("====== Resets ======") + for x in resets do : println-debug(x) - Module(name(m),ports(m),expand-whens(assign,kinds,stmts,decs,enables)) + val table = merge-resets(assign,resets) + println-debug("====== Table ======") + for x in table do : println-debug(x) + val decs = Vector<Stmt>() + val cons = Vector<Stmt>() + expand-whens(body(m),table,decs,cons) + Module(name(m),ports(m),Begin(append(to-list(decs),to-list(cons)))) defn expand-whens (c:Circuit) -> Circuit : Circuit(modules*, main(c)) where : @@ -1793,7 +1791,6 @@ defn to-real-ir (c:Circuit) : match(map(to-exp,e)) : (e:WRef) : Ref(name(e), type(e)) (e:WSubfield) : Subfield(exp(e),name(e),type(e)) - (e:WRegInit) : error("Shouldn't be here") (e:WIndex) : error("Shouldn't be here") (e) : e defn to-stmt (s:Stmt) : @@ -2039,7 +2036,6 @@ public defn run-passes (c: Circuit, p: List<Char>,file:String) : if contains(p,'X') or contains(p,'g') : do-stage("Expand Accessors", expand-accessors) if contains(p,'X') or contains(p,'h') : do-stage("Lower To Ground", lower-to-ground) if contains(p,'X') or contains(p,'i') : do-stage("Expand Indexed Connects", expand-connect-indexed) - if contains(p,'X') or contains(p,'j') : do-stage("Initialize Registers", initialize-registers) if contains(p,'X') or contains(p,'k') : do-stage("Expand Whens", expand-whens) if contains(p,'X') or contains(p,'l') : do-stage("Infer Widths", infer-widths) if contains(p,'X') or contains(p,'m') : do-stage("Inline Instances", inline-instances) |
