470 likes | 605 Views
This tutorial provides an in-depth exploration of constructive computer architecture using Bluespec SystemVerilog (BSV). We cover the fundamental types, focusing on registers, sequential circuits, and arithmetic operations, particularly multiplication. Key principles of dynamic selection and optimization techniques are examined, such as using shift operations in lieu of multiplexers. The course also addresses common challenges like double-write errors in FIFO implementations. Ideal for students and professionals looking to enhance their knowledge of computer architecture design and implementation in BSV.
E N D
Constructive Computer Architecture Tutorial 1 BSV Types Andy Wright 6.175 TA http://csg.csail.mit.edu/6.175
Constructive Computer Architecture Sequential Circuits - 2 Arvind Computer Science & Artificial Intelligence Lab. Massachusetts Institute of Technology http://csg.csail.mit.edu/6.175
Sequential Circuit for Multiply Reg#(Bit#(32)) a <- mkRegU(); Reg#(Bit#(32)) b <- mkRegU(); Reg#(Bit#(32)) prod <-mkRegU();Reg#(Bit#(32)) tp <- mkReg(0); Reg#(Bit#(6)) i <- mkReg(32); rule mulStep if (i < 32); Bit#(32) m = (a[i]==0)? 0 : b; Bit#(33) sum = add32(m,tp,0); prod[i] <= sum[0];tp <= sum[32:1]; i <= i+1;endrule http://csg.csail.mit.edu/6.175
Sequential Circuit for Multiply Reg#(Bit#(32)) a <- mkRegU(); Reg#(Bit#(32)) b <- mkRegU(); Reg#(Bit#(32)) prod <-mkRegU();Reg#(Bit#(32)) tp <- mkReg(0); Reg#(Bit#(6)) i <- mkReg(32); rule mulStep if (i < 32); Bit#(32) m = (a[i]==0)? 0 : b; Bit#(33) sum = add32(m,tp,0); prod[i] <= sum[0];tp <= sum[32:1]; i <= i+1;endrule Dynamic selection http://csg.csail.mit.edu/6.175
Dynamic selection requires a mux i when the selection indices are regular then it is better to use a shift operator (no gates!) a[i] a >> a a[0],a[1],a[2],… 0 http://csg.csail.mit.edu/6.175
Replacing repeated selections by shifts Reg#(Bit#(32)) a <- mkRegU(); Reg#(Bit#(32)) b <- mkRegU(); Reg#(Bit#(32)) prod <-mkRegU();Reg#(Bit#(32)) tp <- mkReg(0); Reg#(Bit#(6)) i <- mkReg(32); rule mulStep if (i < 32); Bit#(32) m = (a[0]==0)? 0 : b; a <= a >> 1; Bit#(33) sum = add32(m,tp,0); prod <= {sum[0], prod[31:1]};tp <= sum[32:1]; i <= i+1;endrule http://csg.csail.mit.edu/6.175
Replacing repeated selections by shifts Reg#(Bit#(32)) a <- mkRegU(); Reg#(Bit#(32)) b <- mkRegU(); Reg#(Bit#(32)) prod <-mkRegU();Reg#(Bit#(32)) tp <- mkReg(0); Reg#(Bit#(6)) i <- mkReg(32); rule mulStep if (i < 32); Bit#(32) m = (a[0]==0)? 0 : b; a <= a >> 1; Bit#(33) sum = add32(m,tp,0);prod <= {sum[0], prod[31:1]};tp <= sum[32:1]; i <= i+1;endrule Just like dynamic selection optimization, but with dynamic insertion instead http://csg.csail.mit.edu/6.175
Circuit for Sequential Multiply bIn aIn s1 b 0 0 << 0 s1 +1 add << s1 s1 0 32:1 [30:0] 31 prod a i tp s2 s2 s2 s2 31:0 0 == 32 done result (high) result (low) s1 = start_en s2 = start_en | !done http://csg.csail.mit.edu/6.175
Circuit analysis • Number of add32 circuits has been reduced from 31 to one, though some registers and muxes have been added • The longest combinational path has been reduced from 62 FAs to to one add32 plus a few muxes • The sequential circuit will take 31 clock cycles to compute an answer http://csg.csail.mit.edu/6.175
Observations • These programs are not very complex and yet it would have been tedious to express these programs in a state table or as a circuit directly • BSV method calls are not available in Verilog/VHDL, and thus such programs sometimes require tedious programming • Even the meaning of double-write errors is not standardized across tool implementations in Verilog http://csg.csail.mit.edu/6.175
A subtle problem while(!isDone(x)) { x = doStep(x); } doStep workQ done ? doneQ let x = workQ.first; workQ.deq; if (isDone(x)) begin doneQ.enq(x); end else begin workQ.enq(doStep(x)); end Double write problem for 1-element Fifo stay tuned! http://csg.csail.mit.edu/6.175
Constructive Computer Architecture Tutorial 1 BSV Types Andy Wright 6.175 TA http://csg.csail.mit.edu/6.175
Bit#(numeric type n) • The most important type in BSV • We’ll go into the details later http://csg.csail.mit.edu/6.175
Bit#(numeric type n) • Literal values: • Decimal: 0, 1, 2, … (each have type Bit#(n) • Binary: 5’b01101 (13 with type Bit#(5)),2’b11 (3 with type Bit#(2)) • Hex: 5’hD, 2’h3, 16’h1FF0 • Common functions: • Bitwise Logic: |, &, ^, ~, etc. • Arithmetic: +, -, *, %, etc. • Indexing: a[i] • Concatenation: {a, b} http://csg.csail.mit.edu/6.175
Bool • Literal values: • True, False • Common functions: • Boolean Logic: ||, &&, !, ==, !=, etc. • All comparison operators (==, !=, >, <, >=, <=) return Bools http://csg.csail.mit.edu/6.175
Int#(n), UInt#(n) • Literal values: • Decimal: • 0, 1, 2, … (Int#(n) and UInt#(n)) • -1, -2, … (Int#(n)) • Common functions: • Arithmetic: +, -, *, %, etc. (Int#(n) performs signed operations, UInt#(n) performs unsigned operations) • Comparison: >, <, >=, <=, ==, !=, etc. http://csg.csail.mit.edu/6.175
Constructing new types • Renaming types: • typedef • Enumeration types: • enum • Compound types: • struct • vector • maybe • tagged union http://csg.csail.mit.edu/6.175
typedef • Syntax: • typedef <type> <new_type_name>; • Basic: • typedef 8 BitsPerWord; • typedef Bit#(BitsPerWord) Word; • Can’t be used with parameter: Word#(n) • Parameterized: • typedef Bit#(TMul#(BitsPerWord,n)) Word#(n); • Can’t be used withoutparameter: Word http://csg.csail.mit.edu/6.175
enum typedefenum{red, blue} Color deriving (Bits, Eq); • Creates the type Color with values red and blue • Can create registers containing colors • Reg#(Color) • Values can be compared with == and != http://csg.csail.mit.edu/6.175
struct typedefstruct { Bit#(12) address; Bit#(8) data; Boolwrite_en; } MemReq deriving (Bits, Eq); • Elements from MemReq x can be accessed with x.address,x.data,x.write_en http://csg.csail.mit.edu/6.175
Tuples • Types: • Tuple2#(type t1, type t2) • Tuple3#(type t1, type t2, type t3) • up to Tuple8 • Values: • tuple2( x, y ), tuple3( x, y, z ), … • Accessing an element: • tpl_1( tuple2(x, y) ) = x • tpl_2( tuple3(x, y, z) ) = y • … http://csg.csail.mit.edu/6.175
Vector • Type: • Vector#(numeric type size, type data_type) • Values: • newVector(), replicate(val) • Functions: • Access an element: [] • Rotate functions • Advanced functions: zip, map, fold • Can contain registers or modules • Must have ‘import Vector::*;’ in BSV file http://csg.csail.mit.edu/6.175
Maybe#(t) • Type: • Maybe#(type t) • Values: • tagged Invalid • tagged Valid x (where x is a value of type t) • Functions: • isValid(x) • Returns true if x is valid • fromMaybe(default, m) • If m is valid, returns the valid value of m if m is valid, otherwise returns default • Commonly used fromMaybe(?, m) http://csg.csail.mit.edu/6.175
tagged union • Maybe is a special type of tagged union typedefunion tagged { void Invalid; t Valid; } Maybe#(type t) deriving (Eq, Bits); • Tagged unions are collections of types and tags. The type contained in the union depends on the tag of the union. • If tagged Valid, this type contains a value of type t http://csg.csail.mit.edu/6.175
tagged union – Continued • Values: • tagged <tag> value • Pattern matching to get values: case (x) matches tagged Valid .a : return a; tagged Invalid : return 0; endcase • See BSV Reference Guide (on course website) for more examples of pattern matching http://csg.csail.mit.edu/6.175
Reg#(t)State element of BSV • Main state element in BSV • Type: Reg#(type data_type) • Instantiated differently from normal variables • Uses <- notation • Written to differently from normal variables • Uses <= notation • Can only be done inside of rules and methods Reg#(Bit#(32)) a_reg <- mkReg(0) // value set to 0 Reg#(Bit#(32)) b_reg <- mkRegU() // uninitialized // write to b_reg (needs to be done inside rule) b_reg <= 7; http://csg.csail.mit.edu/6.175
Reg and Vector • Register of Vectors • Reg#( Vector#(32, Bit#(32) ) ) rfile; • rfile <- mkReg( replicate(0) ); • Vector of Registers • Vector#( 32, Reg#(Bit#(32)) ) rfile; • rfile <- replicateM( mkReg(0) ); • Each has its own advantages and disadvantages http://csg.csail.mit.edu/6.175
Partial Writes • Reg#(Bit#(8)) r; • r[0] <= 0 counts as a read and write to the entire register r • let r_new = r; r_new[0] = 0; r <= r_new • Reg#(Vector#(8, Bit#(1))) r • Same problem, r[0] <= 0 counts as a read and write to the entire register • r[0] <= 0; r[1] <= 1 counts as two writes to register r – double write problem • Vector#(8,Reg#(Bit#(1))) r • r is 8 different registers • r[0] <= 0 is only a write to register r[0] • r[0] <= 0 ; r[1] <= 1 is not a double write problem http://csg.csail.mit.edu/6.175
Modules • Modules are building blocks for larger systems • Modules contain other modules and rules • Modules are accessed through their interface • module mkAdder( Adder#(32) ); • Adder#(32) is the interface http://csg.csail.mit.edu/6.175
Interfaces • Interfaces contain methods for other modules to interact with the given module • Interfaces can also contain other interfaces interface MyInterface#(numeric type n); method ActionValue#(Bit#(b)) f(); interface SubInterfaces; endinterface http://csg.csail.mit.edu/6.175
Interface Methods • Method • Returns value, doesn’t change state • method Bit#(32) peek_at_front(); • Action • Changes state, doesn’t return value • method Action enqueue(); • ActionValue • Changes state, returns value • method ActionValue#(Bit#(32)) dequeue_front() http://csg.csail.mit.edu/6.175
Strong Typing • The Bluespec Compiler throws errors if it can’t figure out a type • Which of the following lines work? Bit#(32) a = 7; Bit#(8) small_b = 3; let b = zeroExtend( small_b ); let a_plus_b = a + b; Bit#(8) b_plus_fifty_truncated = truncate( b + 50 ); http://csg.csail.mit.edu/6.175
Quiz http://csg.csail.mit.edu/6.175
Question 1 • What is the type of a? Bit#(n) x = 1; Bit#(m) y = 3; let a = {x,y}; Bit#(TAdd#(n,m)) http://csg.csail.mit.edu/6.175
Question 2 • What is the type of b? Bit#(n) x = 1; Bit#(m) y = 3; let a = {x,y}; let b = x + y; Type Error! + expects inputs and outputs to all have the same type http://csg.csail.mit.edu/6.175
Question 2 – BSC Error Error: “File.bsv”, line 10, column 9: … Type error at: y Expected type: Bit#(n) Inferred type: Bit#(m) http://csg.csail.mit.edu/6.175
Question 3 • What is the type of c? Bit#(8) x = 9; let c = x[0]; Bit#(1) http://csg.csail.mit.edu/6.175
Question 4 • What is the type of d? Bit#(8) x = 9; let d = zeroExtend(x); Can’t tell, so the compiler gives a type error http://csg.csail.mit.edu/6.175
Question 5 • What does this function do? How does it work? function Bit#(m) resize(Bit#(n) x) Bit#(m) y = truncate(zeroExtend(x)); return y; endfunction Produces a compiler error! zeroExtend(x) has an unknown type http://csg.csail.mit.edu/6.175
Question 5 – Fixed function Bit#(m) resize(Bit#(n) x) Bit#(TMax#(m,n)) x_ext; x_ext = zeroExtend(x); Bit#(m) y = truncate(x_ext); return y; endfunction http://csg.csail.mit.edu/6.175
Question 6 • What does this code do? // mainQ, redQ, blueQare FIFOs // redC, blueC let x = mainQ.first; mainQ.deq; if( isRed(x) ) redQ.enq(x); redC <= redC + 1; if( isBlue(x) ) blueQ.enq(x); blueC <= blueC + 1; Not what it looks like http://csg.csail.mit.edu/6.175
Question 6 – Rewritten let x = mainQ.first; mainQ.deq; if( isRed(x) ) redQ.enq(x); redC <= redC + 1; if( isBlue(x) ) blueQ.enq(x); blueC <= blueC + 1; Only the first action/expression after the if is done, that’s why we have begin/end http://csg.csail.mit.edu/6.175
Question 6 – Fixed let x = mainQ.first; mainQ.deq; if( isRed(x) ) begin redQ.enq(x); redC <= redC + 1; end if( isBlue(x) ) begin blueQ.enq(x); blueC <= blueC + 1; end http://csg.csail.mit.edu/6.175
Why is Bit#(n) so important? • Bit#(n) is the only type that can be synthesized as a set of wires • Other types are synthesizable only if they can be converted to Bit#(n) • How do you keep track of types that can be converted to Bit#(n)? • Typeclasses! (specifically the Bits#(t) typeclass) http://csg.csail.mit.edu/6.175
Bits#(a,n) typeclass typeclass Bits#(type a, type n); function Bit#(n) pack(a x); function a unpack(Bit#(n) y); endtypeclass If there is an instance of the typeclassBits#(mytype, n), then mytype can be converted to Bits#(n) using pack. Furthermore, mytype can be stored in a register of type Reg#(mytype) http://csg.csail.mit.edu/6.175
Bits#(a,n) instance typedefenum { red, green, blue } Color deriving (Eq); // but not bits instance Bits#(Color, 2); function Bit#(2) pack(a x); if( x == red ) return 0; else if( x == green ) return 1; else return 2; function Color unpack(Bit#(2) y) if( x == 0 ) return red; else if( x == 1 ) return green; else return blue; endfunction endinstance http://csg.csail.mit.edu/6.175
Typeclasses • Typeclasses allow polymorphism across types • Examples: • Eq: contains == and != • Ord: contains <, >, <=, >=, etc. • Bits: contains pack and unpack • Arith: contains arithmetic functions • Bitwise: contains bitwise logic http://csg.csail.mit.edu/6.175