From e5b9f6ec710e8573ce262330731bebc7524296e5 Mon Sep 17 00:00:00 2001 From: azidar Date: Wed, 8 Apr 2015 11:28:29 -0700 Subject: Finished expand whens. started infer widths. added pdf for people to view --- notes/chisel.04.06.15.txt | 207 ++++++++++++++++++++++++++++++++++++++++++++++ notes/memory.txt | 40 +++++++++ 2 files changed, 247 insertions(+) create mode 100644 notes/chisel.04.06.15.txt create mode 100644 notes/memory.txt (limited to 'notes') diff --git a/notes/chisel.04.06.15.txt b/notes/chisel.04.06.15.txt new file mode 100644 index 00000000..67f80aa5 --- /dev/null +++ b/notes/chisel.04.06.15.txt @@ -0,0 +1,207 @@ +=================================== +Supporting Memory Variety in FIRRTL +=================================== + +----------- Masks? ------------------ + +== High FIRRTL == +mem m : { tag : UInt<10> data : UInt<128> }[32] +accessor w = m[i] + +== Low FIRRTL == +mem m : { tag : UInt<10> data : UInt<128> }[32] +wire w#tag : UInt<10> +wire w#data : UInt<128> +WritePort(m.tag,i,en*) := w#tag +WritePort(m.data,i,en*) := w#data + +== Example Backend == ;Keep merged mem for masks, easy because mem declaration preserves bundle type +mem m : UInt<138>[32] +wire w : UInt<138> +wire w#tag : UInt<10> +wire w#data : UInt<128> +w := concat(w#tag,w#concat) +MaskedWritePort(m,i,mask*) := w ; mask* calculated from enables and mem declaration + +== Example Backend == ;Split mem, easy because accessors are bundle-expanded +mem m#tag : UInt<10>[32] +mem m#data : UInt<128>[32] +wire w#tag : UInt<10> +WritePort(m#tag,i,en*) := w#tag +wire w#data : UInt<128> +WritePort(m#data,i,en*) := w#data + + +--------- Combination/Sequential Reads? ---------- + +== High FIRRTL == +cmem m-com : UInt<128>[32] +smem m-seq : UInt<128>[32] + +== Low FIRRTL == +cmem m-com : UInt<128>[32] ;FIRRTL does nothing +smem m-seq : UInt<128>[32] + + +--------- Read&Write Ports? --------------- + +read accessor r = m[i] +write accessor w = m[i] +readwrite accessor rw = m[i] +? accessor u = m[i] /can infer read, write, but not readwrite + + +== Chisel == +val m = Mem(UInt(128),32) +val rw = ReadWritePort(m,index) + +== High FIRRTL == +mem m : UInt<128>[32] +readwrite accessor rw = m[index] + +== Low FIRRTL == +mem m<1> : UInt<128>[32] ;r/w ports are always synchronous because writes always synchronous +wire rw : UInt<128> +rw := ReadWritePort(m,index,ren*,wen*) + +== Backends == + ; Example of read/write to same address, can handle differently in BRAM's on FPGA, + but is undefined for SRAMs. (Specifically for Synchronous). + +----------- Notes ----------------- + + Catch-all is to always use black boxes + We are not absorbing registers! + User registers the address input, and chisel is allowed to retime the register into the address + Not firrtl's job to autotune - that is the library writer (ASIC backend? FIRRTL library?) + e.g. FPGA backend is an executable that iterates and does DSE + + + +================================ +Supporting Annotations in FIRRTL +================================ + +Example pass: +We have a decoupled interface in Chisel - {data:UInt, valid:UInt, flip ready:UInt} - and want +to test our design by adding a random number of buffers between every bulk connect of this type. + +== High FIRRTL == +wire a : { data : UInt<32>, valid : UInt<1>, flip ready : UInt<1> } +wire b : { data : UInt<32>, valid : UInt<1>, flip ready : UInt<1> } +b := a + +== Low FIRRTL, no FIFO PASS == +wire a#data : UInt<32> +wire a#valid : UInt<1> +wire a#ready : UInt<1> +wire b#data : UInt<32> +wire b#valid : UInt<1> +wire b#ready : UInt<1> +b#data := a#data +b#valid := a#valid +a#ready := b#ready + +== High FIRRTL after FIFO Pass == +wire a : { data : UInt, valid : UInt, flip ready : UInt } +reg r : { data : UInt, valid : UInt, flip ready : UInt } +wire b : { data : UInt, valid : UInt, flip ready : UInt } +r := a +b := r + +== Low FIRRTL after FIFO Pass == +wire a#data : UInt<32> +wire a#valid : UInt<1> +wire a#ready : UInt<1> +wire b#data : UInt<32> +wire b#valid : UInt<1> +wire b#ready : UInt<1> +reg r#data : UInt<32> +reg r#valid : UInt<1> +reg r#ready : UInt<1> +r#data := a#data +r#valid := a#valid +a#ready := r#ready +b#data := r#data +b#valid := r#valid +r#ready := b#ready + +-------- Option 1: Only Unique IDs -------- +FIRRTL provides no support for annotations, except guaranteeing that each node has a unique id. +------------------------------------------- +Generator Pass Structure: + Walk tree and build hashtable of symbol => boolean, where each reference's id matches a symbol, and the boolean is true if the type of the reference matches the decoupled interface. + +Consumer Pass Structure: + Walk tree and for any ':=', check if both references are in table. If so, insert a random number of buffers + +Points: + + Very simple to implement. + - If generator operates on high firrtl and consumer operates on low firrtl, bundle-expansion breaks the consumer pass. Whose fault is it?? + - Can't pass annotations from front-end to back-end in the tree, but in auxilliary data structure, which can become out of date. + +TLDR: Onus is on generator pass to make it robust. Middle passes can screw things up. Easiest. + +-------- Option 2: Typed Annotations --------- +FIRRTL has (order of) 10 types of annotations with known propagation properties; each pass must state which types of annotations are preserved, which are generated, and which are broken. +---------------------------------------------- +Generator Pass Structure: + Walk tree and annotate all nodes that match the decoupled interface with an annotation type that propagates through bundle expansion + +Consumer Pass Structure: + Walk tree and for an ':=', check if both references contain generated annotation. If so, insert a random number of buffers. + +Points: + + Clear assignment of blame - notion of support for annotations can keep passes/people responsible + - Requires thinking critically about all types of annotations that will be needed. Adds additional work to every pass. + - Pass complexity is associated with number of annotation types, not actual pass algorithm + +TLDR: Onus is shared between all passes. May limit types of annotations. Strong assignment of blame. + +-------- Option 3: History Trees ---------- +FIRRTL records all graph transformations (think git), where nodes have pointers to deleted/replaced nodes. A pass can walk the history graph to understand how previous passes mutated the graph (and its annotations). +------------------------------------------- +Generator Pass Structure: + Walk tree and annotate all nodes that match the decoupled interface. + +Consumer Pass Structure: + Walk tree and for an ':=', look at both node's history to find any ancestor node which was annotated. If so, insert random number of buffers. + +Points: + + Intermediate passes can be oblivious to all annotations. + - Hard to write consumer pass correctly, because arbitrary passes could really mess with the graph. Need significant FIRRTL support for maintaining history table, and all passes must correctly use API to ensure history is indeed correct. Hard to assign blame. + - If ever restructure upstream passes, could very easily break downstream passes because can depend on history as well as the tree + +TLDR: Onus is on consumer pass. Requires significant support from FIRRTL. + +--------- Option 4: Annotation Propogation Passes ---------- +Each FIRRTL pass constructs a table mapping unique id nodes from the old circuit to a list of unique id nodes in the new circuit. The annotation writer writes a pass that uses this table, the old circuit, and the new circuit to create a new circuit with the correct annotations. +------------------------------------------------------------ +Generator Pass Structure: + Walk tree and annotate all nodes that match the decoupled interface +Propagation Pass Structure: + Per row in the annotation table, add the annotation from the old circuit's id to each node in the new circuit that match the list of nodes. +Consumer Pass Structure: + Walk tree and for each ':=', look at both node's annotations and, if contains correct annotation, insert random number of buffers. +Points: + + Passes remain simple - only need to create table + + Simple passes makes writing the annotation propogation pass easier + - Up to annotation writer to validate whether a pass's constructed annotation table is correct + + + + + +Debug info +Tagged Decoupled +Layout ideas +Daisy chains +Simulation annotations +Probability distribution of values +After inlining, what module things came from + + +Inline Module +ensure_combinational Module +throw/catch exceptions (more fanciful); on wire declaration + diff --git a/notes/memory.txt b/notes/memory.txt new file mode 100644 index 00000000..22fb95dc --- /dev/null +++ b/notes/memory.txt @@ -0,0 +1,40 @@ +Whats resonable to express, how this relates to hardware + +Catch-all? Can always use black boxes + +Read/write ports? explicitly call it out in front end, and have a r/w accessor + Can infer from enables that they are mutually exclusive in some cases, in general need SAT solver + Writer often wants a r/w port to always be generated + r/w ports are always synchronous because writes always synchronous + Example of read/write to same address, can handle differently in BRAM's on FPGA, but is undefined for SRAMs. (Specifically for Synchronous). + In this case, it is backend speciifc, so should not be in chisel code. + +Don't have both synchronous and asynchronous reads on the same memory +Declaring the memory itself to have delay? - have node for seq, and node for combinational. Could have >1 delay, but not often used. Boolean for now (0 or 1) + +Absorbing registers should stop - register the address input, and chisel is allowed to retime the register into the address + +Not firrtl's job to autotune - that is the library writer (ASIC backend? FIRRTL library?) + e.g. FPGA backend is an executable that iterates and does DSE + +Masks? + Front-end generates mem's of type bundles or vec for enable granularity. + Lowering does not expand these. + Backends treat these differently. + How do we do this? Try not expanding mems, but expanding accessors. + e.g. + +mem m : { tag : UInt<10> data : UInt<128> } +accessor r = m[i] +accessor w = m[i] + +==> + +mem m : { tag : UInt<10> data : UInt<128> } +accessor r#tag = m.tag[i] +accessor r#data = m.data[i] +accessor w#tag = m.tag[i] +accessor w#data = m.data[i] + + +Eliminate flips from bundles in mems, must error. -- cgit v1.2.3