Closed colinschmidt closed 8 years ago
The problem is at line 180755 of hwacha.fir, we have the following chirrtl:
module Queue_824 :
...
T_6898.lane is invalid
T_6898.lane[0] <- T_7635
infer mport T_6898 = ram[T_6884], clk
T_6898 <- io.enq.bits
T_6898 is being used before it is declared. Also, the ram being referred to is the following (if that's helpful):
cmem ram : {fn : {union : UInt<10>}, sreg : {ss1 : UInt<64>, ss2 : UInt<64>, ss3 : UInt<64>},
base : {vp : {id : UInt<4>, valid : UInt<1>, scalar : UInt<1>, pred : UInt<1>}, vs1 : {id : UInt<8>,
valid : UInt<1>, scalar : UInt<1>, pred : UInt<1>, prec : UInt<2>}, vs2 : {id : UInt<8>, valid : UInt<1>,
scalar : UInt<1>, pred : UInt<1>, prec : UInt<2>}, vs3 : {id : UInt<8>, valid : UInt<1>, scalar : UInt<1>,
pred : UInt<1>, prec : UInt<2>}, vd : {id : UInt<8>, valid : UInt<1>, scalar : UInt<1>, pred : UInt<1>,
prec : UInt<2>}}, reg : {vp : {id : UInt<8>}, vs1 : {id : UInt<8>}, vs2 : {id : UInt<8>}, vs3 : {id : UInt<8>},
vd : {id : UInt<8>}}, active : {vint : UInt<1>, vipred : UInt<1>, vimul : UInt<1>, vidiv : UInt<1>,
vfma : UInt<1>, vfdiv : UInt<1>, vfcmp : UInt<1>, vfconv : UInt<1>, vrpred : UInt<1>, vrfirst : UInt<1>,
vamo : UInt<1>, vldx : UInt<1>, vstx : UInt<1>, vld : UInt<1>, vst : UInt<1>}, lane : {active : UInt<1>,
vlen : UInt<12>}[1]}[2]
It seems to me that in order to catch this, we need some CheckCHIRRTL pass that is analogous to the current CheckHighForm which would've caught this with a more elegant error had it been FIRRTL code
Queue_824
is instantiated in module RPredMaster :
with the name inst opq of Queue_824
The queue instantiation looks normal
val opq = Module(new Queue(new IssueOpML, 2))
Ideally, Chisel should never allow a user to generate code that declares something before it is used - that was the assumption used by the CHIRRTL passes. Chisel can't do a good job of this, though, then we should certainly write the CheckHighForm pass on CHIRRTL.
Yeah fair point, I guess we'll see how exactly this is happening. Kind of weird though, it appears to be coming from the implementation of Queue
Just looking at the generated FIRRTL, there's a bunch of weird stuff going on:
module Queue_824 :
input clk : Clock
input reset : UInt<1>
output io : {flip enq : {flip ready : UInt<1>, valid : UInt<1>, bits : {fn : {union : UInt<10>}, sreg : {ss1 : UInt<64>, ss2 : UInt<64>, ss3 : UInt<64>}, base : {vp : {id : UInt<4>, valid : UInt<1>, scalar : UInt<1>, pred : UInt<1>}, vs1 : {id : UInt<8>, valid : UInt<1>, scalar : UInt<1>, pred : UInt<1>, prec : UInt<2>}, vs2 : {id : UInt<8>, valid : UInt<1>, scalar : UInt<1>, pred : UInt<1>, prec : UInt<2>}, vs3 : {id : UInt<8>, valid : UInt<1>, scalar : UInt<1>, pred : UInt<1>, prec : UInt<2>}, vd : {id : UInt<8>, valid : UInt<1>, scalar : UInt<1>, pred : UInt<1>, prec : UInt<2>}}, reg : {vp : {id : UInt<8>}, vs1 : {id : UInt<8>}, vs2 : {id : UInt<8>}, vs3 : {id : UInt<8>}, vd : {id : UInt<8>}}, active : {vint : UInt<1>, vipred : UInt<1>, vimul : UInt<1>, vidiv : UInt<1>, vfma : UInt<1>, vfdiv : UInt<1>, vfcmp : UInt<1>, vfconv : UInt<1>, vrpred : UInt<1>, vrfirst : UInt<1>, vamo : UInt<1>, vldx : UInt<1>, vstx : UInt<1>, vld : UInt<1>, vst : UInt<1>}, lane : {active : UInt<1>, vlen : UInt<12>}[1]}}, deq : {flip ready : UInt<1>, valid : UInt<1>, bits : {fn : {union : UInt<10>}, sreg : {ss1 : UInt<64>, ss2 : UInt<64>, ss3 : UInt<64>}, base : {vp : {id : UInt<4>, valid : UInt<1>, scalar : UInt<1>, pred : UInt<1>}, vs1 : {id : UInt<8>, valid : UInt<1>, scalar : UInt<1>, pred : UInt<1>, prec : UInt<2>}, vs2 : {id : UInt<8>, valid : UInt<1>, scalar : UInt<1>, pred : UInt<1>, prec : UInt<2>}, vs3 : {id : UInt<8>, valid : UInt<1>, scalar : UInt<1>, pred : UInt<1>, prec : UInt<2>}, vd : {id : UInt<8>, valid : UInt<1>, scalar : UInt<1>, pred : UInt<1>, prec : UInt<2>}}, reg : {vp : {id : UInt<8>}, vs1 : {id : UInt<8>}, vs2 : {id : UInt<8>}, vs3 : {id : UInt<8>}, vd : {id : UInt<8>}}, active : {vint : UInt<1>, vipred : UInt<1>, vimul : UInt<1>, vidiv : UInt<1>, vfma : UInt<1>, vfdiv : UInt<1>, vfcmp : UInt<1>, vfconv : UInt<1>, vrpred : UInt<1>, vrfirst : UInt<1>, vamo : UInt<1>, vldx : UInt<1>, vstx : UInt<1>, vld : UInt<1>, vst : UInt<1>}, lane : {active : UInt<1>, vlen : UInt<12>}[1]}}, count : UInt<2>}
io is invalid
node T_80 = cat(T_53.fp, T_53.op)
node T_81 = cat(T_53.dw, T_80)
node T_133 = cat(T_107.dw, T_107.op)
node T_160 = cat(T_134.dw, T_134.op)
node T_188 = cat(T_161.rm, T_161.op)
node T_189 = cat(T_161.fp, T_188)
node T_217 = cat(T_190.rm, T_190.op)
node T_218 = cat(T_190.fp, T_217)
node T_246 = cat(T_219.rm, T_219.op)
node T_247 = cat(T_219.fp, T_246)
node T_275 = cat(T_248.rm, T_248.op)
node T_276 = cat(T_248.fp, T_275)
node T_281 = cat(T_277.cmd, T_277.mt)
node T_282 = cat(T_277.mode, T_281)
wire lane : {active : UInt<1>, vlen : UInt<12>}[1]
T_5.lane is invalid
T_5.lane[0] <- T_742
node T_846 = cat(T_819.fp, T_819.op)
node T_847 = cat(T_819.dw, T_846)
node T_899 = cat(T_873.dw, T_873.op)
node T_926 = cat(T_900.dw, T_900.op)
node T_954 = cat(T_927.rm, T_927.op)
node T_955 = cat(T_927.fp, T_954)
node T_983 = cat(T_956.rm, T_956.op)
node T_984 = cat(T_956.fp, T_983)
node T_1012 = cat(T_985.rm, T_985.op)
node T_1013 = cat(T_985.fp, T_1012)
node T_1041 = cat(T_1014.rm, T_1014.op)
node T_1042 = cat(T_1014.fp, T_1041)
node T_1047 = cat(T_1043.cmd, T_1043.mt)
node T_1048 = cat(T_1043.mode, T_1047)
wire lane : {active : UInt<1>, vlen : UInt<12>}[1]
T_771.lane is invalid
...
wire lane
is declared multiple times, it's always followed with some T_#.lane is invalid
as if its a mem or an instance rather than a wire. What's going on inside of this type?
That bundle has a Vec.fill(n){new InnerBundle} that when corrected, no longer produces the above match error.
I noticed that in the Chisel source code
def apply[T <: Data](n: Int, gen: T): Vec[T] = new Vec(gen.cloneType, n)
...
def fill[T <: Data](n: Int)(gen: => T): Vec[T] = apply(Seq.fill(n)(gen))
Is there a reason why fill can't just call apply(gen, n)
?
They don't mean the same thing... fill is used for broadcasting a data value across the elements in a Vec (which is mostly only useful for initializing a Reg[Vec]). apply is used to create a type.
Makes sense, and this explains to me why Vec.fill ends up wrapping the Vec in a Wire whereas standard apply does not
See #157.
This is too vague of a report right now but I'm pasting this here so I don't lose it or forget about it: Will update later today.