Chiselのチュートリアルの続き。
chisel-tutorial/examples/BasicALU.scala を見てみよう。
package TutorialExamples import Chisel._ class BasicALU extends Module { val io = new Bundle { val a = UInt(INPUT, 4) val b = UInt(INPUT, 4) val opcode = UInt(INPUT, 4) val output = UInt(OUTPUT, 4) } io.output := UInt(0) //THIS SEEMS LIKE A HACK/BUG when (io.opcode === UInt(0)) { io.output := io.a //pass A } .elsewhen (io.opcode === UInt(1)) { io.output := io.b //pass B } .elsewhen (io.opcode === UInt(2)) { io.output := io.a + UInt(1) //increment A by 1 } .elsewhen (io.opcode === UInt(3)) { io.output := io.a - UInt(1) //increment B by 1 } .elsewhen (io.opcode === UInt(4)) { io.output := io.a + UInt(4) //increment A by 4 } .elsewhen (io.opcode === UInt(5)) { io.output := io.a - UInt(4) //decrement A by 4 } .elsewhen (io.opcode === UInt(6)) { io.output := io.a + io.b //add A and B } .elsewhen (io.opcode === UInt(7)) { io.output := io.a - io.b //subtract B from A } .elsewhen (io.opcode === UInt(8)) { io.output := io.a < io.b //set on A less than B } .otherwise { io.output := (io.a === io.b).toUInt() //set on A equal to B } } class SimpleALU extends Module { val io = new Bundle { val a = UInt(INPUT, 4) val b = UInt(INPUT, 4) val opcode = UInt(INPUT, 2) val output = UInt(OUTPUT, 4) } io.output := UInt(0) when (io.opcode === UInt(0)) { io.output := io.a + io.b //ADD } .elsewhen (io.opcode === UInt(1)) { io.output := io.a - io.b //SUB } .elsewhen (io.opcode === UInt(2)) { io.output := io.a //PASS A } .otherwise { io.output := io.b //PASS B } }
うーん、単純なデコーダに見えるね。全てif + elseifのように見えるけど、どのようなハードウェアが生成されるのかな?
make BasicALU.v
あれ、BasicALU.vが生成されずにSimpleALU.vが生成された。何でだろう。
module SimpleALU( input [3:0] io_a, input [3:0] io_b, input [1:0] io_opcode, output[3:0] io_output ); wire[3:0] T0; wire[3:0] T1; wire[3:0] T2; wire[3:0] T3; wire[3:0] T4; wire T5; wire[3:0] T6; wire T7; wire T8; wire T9; wire T10; wire T11; wire T12; wire T13; wire T14; wire T15; assign io_output = T0; assign T0 = T14 ? io_b : T1; assign T1 = T10 ? io_a : T2; assign T2 = T7 ? T6 : T3; assign T3 = T5 ? T4 : 4'h0; assign T4 = io_a + io_b; assign T5 = io_opcode == 2'h0; assign T6 = io_a - io_b; assign T7 = T9 & T8; assign T8 = io_opcode == 2'h1; assign T9 = T5 ^ 1'h1; assign T10 = T12 & T11; assign T11 = io_opcode == 2'h2; assign T12 = T13 ^ 1'h1; assign T13 = T5 | T8; assign T14 = T15 ^ 1'h1; assign T15 = T13 | T11; endmodule
うわ、読み辛い....
次はRouter.scalaだ。
class ReadCmd extends Bundle { val addr = UInt(width = 32); } class WriteCmd extends ReadCmd { val data = UInt(width = 32) } class Packet extends Bundle { val header = UInt(width = 8) val body = Bits(width = 64) } class RouterIO(n: Int) extends Bundle { override def clone = new RouterIO(n).asInstanceOf[this.type] val reads = new DeqIO(new ReadCmd()) val replies = new EnqIO(UInt(width = 8)) val writes = new DeqIO(new WriteCmd()) val in = new DeqIO(new Packet()) val outs = Vec.fill(n){ new EnqIO(new Packet()) } } class Router extends Module { val depth = 32 val n = 4 val io = new RouterIO(n) val tbl = Mem(UInt(width = sizeof(n)), depth) when(io.reads.valid && io.replies.ready) { val cmd = io.reads.deq(); io.replies.enq(tbl(cmd.addr)) } .elsewhen(io.writes.valid) { val cmd = io.writes.deq(); tbl(cmd.addr) := cmd.data } .elsewhen(io.in.valid) { val pkt = io.in.bits val idx = tbl(pkt.header(0)) when (io.outs(idx).ready) { io.in.deq(); io.outs(idx).enq(pkt) } } }
生成されたRouter.vは、
module Router(input clk, output io_reads_ready, input io_reads_valid, input [31:0] io_reads_bits_addr, input io_replies_ready, output io_replies_valid, output[7:0] io_replies_bits, output io_writes_ready, input io_writes_valid, input [31:0] io_writes_bits_addr, input [31:0] io_writes_bits_data, output io_in_ready, input io_in_valid, input [7:0] io_in_bits_header, input [63:0] io_in_bits_body, input io_outs_3_ready, output io_outs_3_valid, output[7:0] io_outs_3_bits_header, output[63:0] io_outs_3_bits_body, input io_outs_2_ready, output io_outs_2_valid, output[7:0] io_outs_2_bits_header, output[63:0] io_outs_2_bits_body, input io_outs_1_ready, output io_outs_1_valid, output[7:0] io_outs_1_bits_header, output[63:0] io_outs_1_bits_body, input io_outs_0_ready, output io_outs_0_valid, output[7:0] io_outs_0_bits_header, output[63:0] io_outs_0_bits_body ); wire[63:0] T0; wire T1; wire T2; wire[3:0] T3; wire[1:0] T4; wire[1:0] T44; wire[2:0] T5; reg [2:0] tbl [31:0]; wire[2:0] T6; wire[2:0] T45; wire T7; wire T8; wire T9; wire[4:0] T46; wire[4:0] T47; wire T10; wire T11; wire T12; wire T13; wire T14; wire T15; wire T16; wire T17; wire T18; wire T19; ...
うぎゃ、こりゃデバッグは出来無いな...