aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/lib/stanza.zipbin3758011 -> 3695332 bytes
-rw-r--r--src/main/stanza/firrtl-ir.stanza3
-rw-r--r--src/main/stanza/ir-parser.stanza504
-rw-r--r--src/main/stanza/ir-utils.stanza15
-rw-r--r--src/main/stanza/passes.stanza482
5 files changed, 543 insertions, 461 deletions
diff --git a/src/lib/stanza.zip b/src/lib/stanza.zip
index fb9ac7d7..5fd5ff6d 100644
--- a/src/lib/stanza.zip
+++ b/src/lib/stanza.zip
Binary files differ
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)