defpackage firrtl/chirrtl : import core import verse import firrtl/ir2 import firrtl/ir-utils public defstruct ToIR <: Pass public defmethod pass (b:ToIR) -> (Circuit -> Circuit) : to-ir public defmethod name (b:ToIR) -> String : "To FIRRTL" public defmethod short-name (b:ToIR) -> String : "to-firrtl" defstruct MPort : name : Symbol clk : Expression defstruct MPorts : readers : Vector writers : Vector readwriters : Vector defstruct DataRef : exp : Expression male : Symbol female : Symbol public definterface Gender public val MALE = new Gender public val FEMALE = new Gender defn create-exps (e:Expression) -> List : match(type(e)) : (t:UIntType|SIntType|ClockType) : list(e) (t:BundleType) : for f in fields(t) map-append : create-exps(SubField(e,name(f),type(f))) (t:VectorType) : for i in 0 to size(t) map-append : create-exps(SubIndex(e,i,type(t))) defn to-ir (c:Circuit) : defn to-ir-m (m:InModule) -> InModule : val hash = HashTable(symbol-hash) val sh = get-sym-hash(m,keys(v-keywords)) val repl = HashTable(symbol-hash) val ut = UnknownType() defn EMPs () -> MPorts : MPorts(Vector(),Vector(),Vector()) defn collect-mports (s:Stmt) -> Stmt : match(s) : (s:CDefMPort) : val mports = get?(hash,mem(s),EMPs()) switch { _ == direction(s) } : MRead : add(readers(mports),MPort(name(s),exps(s)[1])) MWrite : add(writers(mports),MPort(name(s),exps(s)[1])) MReadWrite : add(readwriters(mports),MPort(name(s),exps(s)[1])) hash[mem(s)] = mports s (s) : map(collect-mports,s) defn collect-refs (s:Stmt) -> Stmt : match(s) : (s:CDefMemory) : val stmts = Vector() val naddr = firrtl-gensym(`GEN,sh) val taddr = UIntType(IntWidth(ceil-log2(size(s)))) add(stmts,DefPoison(info(s),naddr,taddr)) val ndata = firrtl-gensym(`GEN,sh) val tdata = type(s) add(stmts,DefPoison(info(s),ndata,tdata)) defn set-poison (vec:List,addr:Symbol) -> False : for r in vec do : add(stmts,Connect(info(s),SubField(SubField(Ref(name(s),ut),name(r),ut),addr,taddr),Ref(naddr,taddr))) add(stmts,Connect(info(s),SubField(SubField(Ref(name(s),ut),name(r),ut),`clk,taddr),clk(r))) defn set-enable (vec:List,en:Symbol) -> False: for r in vec do : add(stmts,Connect(info(s),SubField(SubField(Ref(name(s),ut),name(r),ut),en,taddr),zero)) defn set-write (vec:List,data:Symbol,mask:Symbol) -> False : val tmask = type(create-mask(`blah,type(s))) for r in vec do : add(stmts,Connect(info(s),SubField(SubField(Ref(name(s),ut),name(r),ut),data,tdata),Ref(ndata,tdata))) for x in create-exps(SubField(SubField(Ref(name(s),ut),name(r),ut),mask,tmask)) do : add(stmts,Connect(info(s),x,zero)) val rds = to-list $ readers $ get?(hash,name(s),EMPs()) set-poison(rds,`addr) set-enable(rds,`en) val wrs = to-list $ writers $ get?(hash,name(s),EMPs()) set-poison(wrs,`addr) set-enable(wrs,`en) set-write(wrs,`data,`mask) val rws = to-list $ readwriters $ get?(hash,name(s),EMPs()) set-poison(rws,`waddr) set-poison(rws,`raddr) set-enable(rws,`wen) set-enable(rws,`ren) set-write(rws,`wdata,`wmask) val read-l = if seq?(s) : 1 else : 0 val mem = DefMemory(info(s),name(s),type(s),size(s),1,read-l,map(name,rds),map(name,wrs),map(name,rws)) Begin $ List(mem,to-list(stmts)) (s:CDefMPort) : val addrs = Vector() val ens = Vector() val masks = Vector() switch { _ == direction(s) } : MReadWrite : repl[name(s)] = DataRef(SubField(Ref(mem(s),ut),name(s),ut),`wdata,`rdata) add(addrs,`addr) add(ens,`wen) add(ens,`ren) add(masks,`wmask) MWrite : repl[name(s)] = DataRef(SubField(Ref(mem(s),ut),name(s),ut),`data,`data) add(addrs,`addr) add(ens,`en) add(masks,`mask) else : ; TODO add MWrite for mask repl[name(s)] = DataRef(SubField(Ref(mem(s),ut),name(s),ut),`data,`data) add(addrs,`addr) add(ens,`en) val stmts = Vector() for x in addrs do : add(stmts,Connect(info(s),SubField(SubField(Ref(mem(s),ut),name(s),ut),x,ut),exps(s)[0])) for x in ens do : add(stmts,Connect(info(s),SubField(SubField(Ref(mem(s),ut),name(s),ut),x,ut),one)) for x in masks do : add(stmts,Connect(info(s),SubField(SubField(Ref(mem(s),ut),name(s),ut),x,ut),exps(s)[2])) Begin $ to-list $ stmts (s) : map(collect-refs,s) defn to-ir-e (e:Expression,g:Gender) -> Expression : match(map(to-ir-e{_,g},e)) : (e:Ref) : if key?(repl,name(e)) : val vt = repl[name(e)] switch {g == _ }: MALE : SubField(exp(vt),male(vt),ut) FEMALE : SubField(exp(vt),female(vt),ut) else : e (e) : e defn to-ir-s (s:Stmt) -> Stmt : match(s) : (s:Connect) : val loc* = to-ir-e(loc(s),FEMALE) val roc* = to-ir-e(exp(s),MALE) Connect(info(s),loc*,roc*) (s:BulkConnect) : val loc* = to-ir-e(loc(s),FEMALE) val roc* = to-ir-e(exp(s),MALE) BulkConnect(info(s),loc*,roc*) (s) : map(to-ir-e{_,MALE}, map(to-ir-s,s)) collect-mports(body(m)) val s* = collect-refs(body(m)) InModule(info(m),name(m), ports(m), to-ir-s(s*)) Circuit(info(c),modules*, main(c)) where : val modules* = for m in modules(c) map : match(m) : (m:InModule) : to-ir-m(m) (m:ExModule) : m