module Wb { submod_type tagdec { input tag<4>; output raddr<3>; instrin do; instrout is_reg; } input dtag<4>, wdata<16>; output addr<3>, data<16>; tagdec TD; instrin do; instrout wback; instruct_arg wback(addr, data); instruct_arg TD.do(tag); instruct do any { TD.do(dtag).is_reg : wback(TD.raddr, wdata); } } module bnot4 { /* ** module bnot4 ** ** 4bit bitwise NOT module ** ** by NAGAMI Kou-ichi **** ** x<4> : 4bit binary ** z<4> : */ input x<4>; output z<4>; instrin do; instruct do par { z = (^x<3>)||(^x<2>)||(^x<1>)||(^x<0>); } } module reg16 { /* ** module reg16 ** ** 16bit register ** ** by NAGAMI Kou-ichi **** ** din<16> : write data ** mask<2> : write mask ** dout<4> : read data */ input din<16>; output dout<16>; reg R<16>; instrin read; instrin write; instruct write R := din; instruct read any { (^write) : dout = R; ( write) : dout = din; } } module expand8to16 { input in<8>; output out<16>; tmp s_<8>; instrin signed; instrin unsigned; instruct signed par { s_ = in<7>||in<7>||in<7>||in<7>|| in<7>||in<7>||in<7>||in<7>; out = s_||in; } instruct unsigned par { s_ = 0b00000000; out = s_||in; } } module eq3 { /* ** module eq3 ** ** 3bit equivalence checker ** ** by NAGAMI Kou-ichi **** ** x<3>, y<3> : 3bit binaries to be checked ** eq : (x == y) */ input x<3>, y<3>; instrin do; instrout eq; instruct_arg eq(); instruct do any { (^(x<2>@y<2>))&(^(x<1>@y<1>))&(^(x<0>@y<0>)) : eq(); } } module band4 { /* ** module band4 ** ** 4bit bitwise AND module ** ** by NAGAMI Kou-ichi **** ** x<4>, y<4> : 4bit binaries ** z<4> : x \& y */ input x<4>, y<4>; output z<4>; instrin do; instruct do par { z = (x<3>&y<3>)||(x<2>&y<2>)||(x<1>&y<1>)||(x<0>&y<0>); } } module bnot16 { /* ** module bnot16 ** ** 16bit bitwise NOT module ** ** by NAGAMI Kou-ichi **** ** x<16> : 16bit binary ** z<16> : */ submod_type bnot4 { input x<4>; output z<4>; instrin do; } input x<16>; output z<16>; bnot4 BN3, BN2, BN1, BN0; instrin do; instruct_arg BN3.do(x); instruct_arg BN2.do(x); instruct_arg BN1.do(x); instruct_arg BN0.do(x); instruct do par { z = BN3.do(x<15:12>).z || BN2.do(x<11: 8>).z || BN1.do(x< 7: 4>).z || BN0.do(x< 3: 0>).z; } } module dec3to8 { /* ** module dec3to8 ** ** 3bit -> 8bit decoder ** ** by NAGAMI Kou-ichi **** ** in<8> : binary encoded data ** out<8> : the number represented by `in' */ submod_type dec2to4 { input in<2>; output out<4>; instrin do; } submod_type gate4 { input in<4>, enable; output out<4>; instrin do; } input in<3>; output out<8>; dec2to4 D; gate4 GH, GL; instrin do; instruct_arg D.do(in); instruct_arg GH.do(in, enable); instruct_arg GL.do(in, enable); instruct do par { D.do(in<1:0>); out = GH.do(D.out, in<2>).out|| GL.do(D.out, ^in<2>).out; } } module expand11to16 { input in<11>; output out<16>; tmp s_<5>; instrin signed; instrin unsigned; instruct signed par { s_ = in<10>||in<10>||in<10>||in<10>|| in<10>; out = s_||in; } instruct unsigned par { s_ = 0b00000; out = s_||in; } } module band16 { /* ** module band16 ** ** 16bit bitwise AND module ** ** by NAGAMI Kou-ichi **** ** x<16>, y<16> : 16bit binaries ** z<16> : x \& y */ submod_type band4 { input x<4>, y<4>; output z<4>; instrin do; } input x<16>, y<16>; output z<16>; band4 BA3, BA2, BA1, BA0; instrin do; instruct_arg BA3.do(x, y); instruct_arg BA2.do(x, y); instruct_arg BA1.do(x, y); instruct_arg BA0.do(x, y); instruct do par { z = BA3.do(x<15:12>, y<15:12>).z ||BA2.do(x<11: 8>, y<11: 8>).z ||BA1.do(x< 7: 4>, y< 7: 4>).z ||BA0.do(x< 3: 0>, y< 3: 0>).z; } } module gate4 { /* ** module gate4 ** ** 4bit ** ** by NAGAMI Kou-ichi **** ** in<4> : ** en : ** out<4> : */ input in<4>, enable; output out<4>; instrin do; instruct do par { out = (in<3> & enable) ||(in<2> & enable) ||(in<1> & enable) ||(in<0> & enable); } } module bor16 { /* ** module bor16 ** ** 16bit bitwise OR module ** ** by NAGAMI Kou-ichi **** ** x<16>, y<16> : 16bit binaries ** z<16> : x \& y */ submod_type bor4 { input x<4>, y<4>; output z<4>; instrin do; } input x<16>, y<16>; output z<16>; bor4 BO3, BO2, BO1, BO0; instrin do; instruct_arg BO3.do(x, y); instruct_arg BO2.do(x, y); instruct_arg BO1.do(x, y); instruct_arg BO0.do(x, y); instruct do par { z = BO3.do(x<15:12>, y<15:12>).z ||BO2.do(x<11: 8>, y<11: 8>).z ||BO1.do(x< 7: 4>, y< 7: 4>).z ||BO0.do(x< 3: 0>, y< 3: 0>).z; } } module bxor4 { /* ** module bxor4 ** ** 4bit bitwise XOR module ** ** by NAGAMI Kou-ichi **** ** x<4>, y<4> : 4bit binaries ** z<4> : x \@ y */ input x<4>, y<4>; output z<4>; instrin do; instruct do par { z = (x<3>@y<3>)||(x<2>@y<2>)||(x<1>@y<1>)||(x<0>@y<0>); } } module reg16cell8 { /* ** module reg16cell8 ** ** 16bit registers (4 read ports and 2 write port) ** ** by NAGAMI Kou-ichi **** ** raddr*<3> : read address ** waddr*<3> : write address ** din*<16> : write data ** dout*<16> : read data ** */ submod_type reg16 { input din<16>; output dout<16>; instrin read; instrin write; } submod_type dec3to8 { input in<3>; output out<8>; instrin do; } input raddr0<3>, raddr1<3>, raddr2<3>, raddr3<3>; input waddr0<3>, waddr1<3>, din0<16>, din1<16>; output dout0<16>, dout1<16>, dout2<16>, dout3<16>; reg16 R0, R1, R2, R3, R4, R5, R6, R7; dec3to8 RAD0, RAD1, RAD2, RAD3, WAD0, WAD1; instrin read0, read1, read2, read3; instrin write0, write1; /* must be exclusive ! */ instruct_arg R0.read(); instruct_arg R0.write(din); instruct_arg R1.read(); instruct_arg R1.write(din); instruct_arg R2.read(); instruct_arg R2.write(din); instruct_arg R3.read(); instruct_arg R3.write(din); instruct_arg R4.read(); instruct_arg R4.write(din); instruct_arg R5.read(); instruct_arg R5.write(din); instruct_arg R6.read(); instruct_arg R6.write(din); instruct_arg R7.read(); instruct_arg R7.write(din); instruct_arg RAD0.do(in); instruct_arg RAD1.do(in); instruct_arg RAD2.do(in); instruct_arg RAD3.do(in); instruct_arg WAD0.do(in); instruct_arg WAD1.do(in); instruct read0 par { RAD0.do(raddr0); any { RAD0.out<7> : dout0 = R7.read().dout; RAD0.out<6> : dout0 = R6.read().dout; RAD0.out<5> : dout0 = R5.read().dout; RAD0.out<4> : dout0 = R4.read().dout; RAD0.out<3> : dout0 = R3.read().dout; RAD0.out<2> : dout0 = R2.read().dout; RAD0.out<1> : dout0 = R1.read().dout; RAD0.out<0> : dout0 = R0.read().dout; } } instruct read1 par { RAD1.do(raddr1); any { RAD1.out<7> : dout1 = R7.read().dout; RAD1.out<6> : dout1 = R6.read().dout; RAD1.out<5> : dout1 = R5.read().dout; RAD1.out<4> : dout1 = R4.read().dout; RAD1.out<3> : dout1 = R3.read().dout; RAD1.out<2> : dout1 = R2.read().dout; RAD1.out<1> : dout1 = R1.read().dout; RAD1.out<0> : dout1 = R0.read().dout; } } instruct read2 par { RAD2.do(raddr2); any { RAD2.out<7> : dout2 = R7.read().dout; RAD2.out<6> : dout2 = R6.read().dout; RAD2.out<5> : dout2 = R5.read().dout; RAD2.out<4> : dout2 = R4.read().dout; RAD2.out<3> : dout2 = R3.read().dout; RAD2.out<2> : dout2 = R2.read().dout; RAD2.out<1> : dout2 = R1.read().dout; RAD2.out<0> : dout2 = R0.read().dout; } } instruct read3 par { RAD3.do(raddr3); any { RAD3.out<7> : dout3 = R7.read().dout; RAD3.out<6> : dout3 = R6.read().dout; RAD3.out<5> : dout3 = R5.read().dout; RAD3.out<4> : dout3 = R4.read().dout; RAD3.out<3> : dout3 = R3.read().dout; RAD3.out<2> : dout3 = R2.read().dout; RAD3.out<1> : dout3 = R1.read().dout; RAD3.out<0> : dout3 = R0.read().dout; } } instruct write0 par { WAD0.do(waddr0); any { WAD0.out<7> : R7.write(din0); WAD0.out<6> : R6.write(din0); WAD0.out<5> : R5.write(din0); WAD0.out<4> : R4.write(din0); WAD0.out<3> : R3.write(din0); WAD0.out<2> : R2.write(din0); WAD0.out<1> : R1.write(din0); WAD0.out<0> : R0.write(din0); } } instruct write1 par { WAD1.do(waddr1); any { WAD1.out<7> : R7.write(din1); WAD1.out<6> : R6.write(din1); WAD1.out<5> : R5.write(din1); WAD1.out<4> : R4.write(din1); WAD1.out<3> : R3.write(din1); WAD1.out<2> : R2.write(din1); WAD1.out<1> : R1.write(din1); WAD1.out<0> : R0.write(din1); } } } module eq2 { /* ** module eq2 ** ** 2bit equivalence checker ** ** by NAGAMI Kou-ichi **** ** x<2>, y<2> : 2bit binaries to be checked ** eq : (x == y) */ input x<2>, y<2>; instrin do; instrout eq; instruct_arg eq(); instruct do any { (^(x<1>@y<1>))&(^(x<0>@y<0>)) : eq(); } } module dec4to16 { /* ** module dec4to16 ** ** 4bit -> 16bit decoder ** ** by NAGAMI Kou-ichi **** ** in<4> : binary encoded data ** out<16> : the number represented by `in' */ submod_type dec2to4 { input in<2>; output out<4>; instrin do; } submod_type gate4 { input in<4>, enable; output out<4>; instrin do; } input in<4>; output out<16>; dec2to4 DH, DL; gate4 G3, G2, G1, G0; instrin do; instruct_arg DH.do(in); instruct_arg DL.do(in); instruct_arg G3.do(in, enable); instruct_arg G2.do(in, enable); instruct_arg G1.do(in, enable); instruct_arg G0.do(in, enable); instruct do par { DH.do(in<3:2>); DL.do(in<1:0>); out = G3.do(DL.out, DH.out<3>).out|| G2.do(DL.out, DH.out<2>).out|| G1.do(DL.out, DH.out<1>).out|| G0.do(DL.out, DH.out<0>).out; } } module bxor16 { /* ** module bxor16 ** ** 16bit bitwise XOR module ** ** by NAGAMI Kou-ichi **** ** x<16>, y<16> : 16bit binaries ** z<16> : x \& y */ submod_type bxor4 { input x<4>, y<4>; output z<4>; instrin do; } input x<16>, y<16>; output z<16>; bxor4 BX3, BX2, BX1, BX0; instrin do; instruct_arg BX3.do(x, y); instruct_arg BX2.do(x, y); instruct_arg BX1.do(x, y); instruct_arg BX0.do(x, y); instruct do par { z = BX3.do(x<15:12>, y<15:12>).z ||BX2.do(x<11: 8>, y<11: 8>).z ||BX1.do(x< 7: 4>, y< 7: 4>).z ||BX0.do(x< 3: 0>, y< 3: 0>).z; } } module adder4 { /* ** module adder4 ** ** 4bit binary adder (carry look-ahead) ** ** by NAGAMI Kou-ichi **** ** x<4>, y<4> : operands ** cin : carry-in ** z<4> : result ** cout : carry-out ** sovf : signed over flow ** pout : carry-propagation ** gout : carry-generation */ submod_type cla4 { input pin<4>, gin<4>, cin; output cout<4>, pout, gout; instrin do; } input x<4>, y<4>, cin; output z<4>, cout, sovf, pout, gout; term p_<4>, g_<4>, c_<4>; cla4 CLA; instrin do; instruct_arg CLA.do(pin, gin, cin); instruct do par { p_ = (x<3>@y<3>)||(x<2>@y<2>)||(x<1>@y<1>)||(x<0>@y<0>); g_ = (x<3>&y<3>)||(x<2>&y<2>)||(x<1>&y<1>)||(x<0>&y<0>); c_ = CLA.do(p_, g_, cin).cout; z = (c_<2>@p_<3>)||(c_<1>@p_<2>)||(c_<0>@p_<1>)||(cin@p_<0>); cout = c_<3>; sovf = c_<3>@c_<2>; pout = CLA.pout; gout = CLA.gout; } } /* module adder4 { /* ** module adder4 ** ** 4bit binary adder (ripple carry) ** ** by NAGAMI Kou-ichi **** ** x<4>, y<4> : operands ** cin : carry-in ** z<4> : sum ** cout : carry-out ** */ submod_type fa1 { input x, y, cin; output z, cout; instrin do; } input x<4>, y<4>, cin; output z<4>, cout; fa1 A3, A2, A1, A0; instruct_arg A3.do(x, y, cin); instruct_arg A2.do(x, y, cin); instruct_arg A1.do(x, y, cin); instruct_arg A0.do(x, y, cin); instrin do; instruct do par { z = A3.do(x<3>, y<3>, A2.cout).z ||A2.do(x<2>, y<2>, A1.cout).z ||A1.do(x<1>, y<1>, A0.cout).z ||A0.do(x<0>, y<0>, cin).z; cout = A3.cout; } } */ module idpath { submod_type eq3 { input x<3>, y<3>; instrin do; instrout eq; } /* register fetch info. */ input r1addr<3>, r1in<16>; input r2addr<3>, r2in<16>; /* forwarding information (to be generated by `forward').*/ input fwdEAaddr<3>, fwdEAdata<16>, fwdEBaddr<3>, fwdEBdata<16>; input fwdMAaddr<3>, fwdMAdata<16>, fwdMBaddr<3>, fwdMBdata<16>; input fwdWAaddr<3>, fwdWAdata<16>, fwdWBaddr<3>, fwdWBdata<16>; /* mux'ed result */ output r1out<16>, r2out<16>; eq3 R1_EA, R1_EB, R1_MA, R1_MB, R1_WA, R1_WB; eq3 R2_EA, R2_EB, R2_MA, R2_MB, R2_WA, R2_WB; instrin r1req, r2req; instrin fwdEA, fwdEB; instrin fwdMA, fwdMB; instrin fwdWA, fwdWB; instruct_arg R1_EA.do(x, y); instruct_arg R1_EB.do(x, y); instruct_arg R1_MA.do(x, y); instruct_arg R1_MB.do(x, y); instruct_arg R1_WA.do(x, y); instruct_arg R1_WB.do(x, y); instruct_arg R2_EA.do(x, y); instruct_arg R2_EB.do(x, y); instruct_arg R2_MA.do(x, y); instruct_arg R2_MB.do(x, y); instruct_arg R2_WA.do(x, y); instruct_arg R2_WB.do(x, y); instruct r1req par { any { fwdEB : R1_EB.do(r1addr, fwdEBaddr); fwdEA : R1_EA.do(r1addr, fwdEAaddr); fwdMB : R1_MB.do(r1addr, fwdMBaddr); fwdMA : R1_MA.do(r1addr, fwdMAaddr); fwdWB : R1_WB.do(r1addr, fwdWBaddr); fwdWA : R1_WA.do(r1addr, fwdWAaddr); } any { R1_EB.eq : r1out = fwdEBdata; R1_EA.eq : r1out = fwdEAdata; R1_MB.eq : r1out = fwdMBdata; R1_MA.eq : r1out = fwdMAdata; R1_WB.eq : r1out = fwdWBdata; R1_WA.eq : r1out = fwdWAdata; else : r1out = r1in; } } instruct r2req par { any { fwdEB : R2_EB.do(r2addr, fwdEBaddr); fwdEA : R2_EA.do(r2addr, fwdEAaddr); fwdMB : R2_MB.do(r2addr, fwdMBaddr); fwdMA : R2_MA.do(r2addr, fwdMAaddr); fwdWB : R2_WB.do(r2addr, fwdWBaddr); fwdWA : R2_WA.do(r2addr, fwdWAaddr); } any { R2_EB.eq : r2out = fwdEBdata; R2_EA.eq : r2out = fwdEAdata; R2_MB.eq : r2out = fwdMBdata; R2_MA.eq : r2out = fwdMAdata; R2_WB.eq : r2out = fwdWBdata; R2_WA.eq : r2out = fwdWAdata; else : r2out = r2in; } } } module edecoder { submod_type icodedec { input icode<5>; instrin do; instrout lb, lbu, sb, lw, sw, lhi, lli, link; instrout add, addi, sub, subi, and, andi, or, ori; instrout xor, xori, sl, sli, slt, slti, sgt, sgti; instrout beqz, bnez, j, jr, rst, halt, nop; } input icode<5>; output func<4>; tmp add_<4>, sub_<4>; tmp and_<4>, or_<4>, xor_<4>; tmp sl_<4>; tmp slt_<4>, sgt_<4>; tmp lhi_<4>, lli_<4>; icodedec D; instrin do; instruct_arg D.do(icode); instruct do par { add_ = 0b0000; sub_ = 0b0001; and_ = 0b0010; or_ = 0b0011; xor_ = 0b0100; sl_ = 0b0101; slt_ = 0b0110; sgt_ = 0b0111; lli_ = 0b1101; lhi_ = 0b1110; D.do(icode); any { D.lb : par { func = add_; } D.lbu : par { func = add_; } D.sb : par { func = add_; } D.lw : par { func = add_; } D.sw : par { func = add_; } D.lhi : par { func = lhi_; } D.lli : par { func = lli_; } D.link: par { func = add_; } D.add : par { func = add_; } D.addi: par { func = add_; } D.sub : par { func = sub_; } D.subi: par { func = sub_; } D.and : par { func = and_; } D.andi: par { func = and_; } D.or : par { func = or_; } D.ori : par { func = or_; } D.xor : par { func = xor_; } D.xori: par { func = xor_; } D.sl : par { func = sl_; } D.sli : par { func = sl_; } D.slt : par { func = slt_; } D.slti: par { func = slt_; } D.sgt : par { func = sgt_; } D.sgti: par { func = sgt_; } D.beqz: par { func = add_; } D.bnez: par { func = add_; } D.j : par { func = add_; } D.jr : par { func = add_; } D.rst : par { func = add_; } D.halt: par { func = add_; } D.nop : par { func = add_; } } } } module idecoder { submod_type icodedec { input icode<5>; instrin do; instrout lb, lbu, sb, lw, sw, lhi, lli, link; instrout add, addi, sub, subi, and, andi, or, ori; instrout xor, xori, sl, sli, slt, slti, sgt, sgti; instrout beqz, bnez, j, jr, rst, halt, nop; } submod_type expand5to16 { input in<5>; output out<16>; instrin signed, unsigned; } submod_type expand8to16 { input in<8>; output out<16>; instrin signed, unsigned; } submod_type expand11to16 { input in<11>; output out<16>; instrin signed, unsigned; } input iword<16>; output r1addr<3>, r2addr<3>, imm<16>, tag<4>; term r1_<3>, r2_<3>, r3_<3>; term RR_tag_<4>, I5_tag_<4>, I8_tag_<4>; term imm5_<5>, imm8_<8>, imm11_<11>; icodedec D; expand5to16 E5; expand8to16 E8; expand11to16 E11; instrin do; instrout rr, ri, pi, rir; instrout beqz, bnez, j, jr, rst, halt, nop; instrout r1req, r2req; instruct_arg rr (tag); instruct_arg ri (tag, imm); instruct_arg pi (tag, imm); instruct_arg rir(tag, imm); instruct_arg beqz(r1addr, imm); instruct_arg bnez(r1addr, imm); instruct_arg j(imm); instruct_arg jr(r1addr); instruct_arg rst(); instruct_arg halt(); instruct_arg nop(); instruct_arg r1req(r1addr); instruct_arg r2req(r2addr); instruct_arg D.do(icode); instruct_arg E5.signed(in); instruct_arg E5.unsigned(in); instruct_arg E8.signed(in); instruct_arg E8.unsigned(in); instruct_arg E11.signed(in); instruct_arg E11.unsigned(in); instruct do par { r1_ = iword<10:8>; r2_ = iword< 7:5>; r3_ = iword< 4:2>; imm5_ = iword< 4:0>; imm8_ = iword< 7:0>; imm11_ = iword<10:0>; RR_tag_ = 0b0||r3_; I5_tag_ = 0b0||r2_; I8_tag_ = 0b0||r1_; D.do(iword<15:11>); any { D.lb : ri (I5_tag_, E5.signed(imm5_).out); D.lbu : ri (I5_tag_, E5.signed(imm5_).out); D.sb : rir( 0b1111, E5.signed(imm5_).out); D.lw : ri (I5_tag_, E5.signed(imm5_).out); D.sw : rir( 0b1111, E5.signed(imm5_).out); D.lhi : ri (I8_tag_, imm8_||0x00 ); D.lli : ri (I8_tag_, 0x00 ||imm8_); D.link: pi (I8_tag_, E8.signed(imm8_).out); D.add : rr(RR_tag_); D.addi: ri(I5_tag_, E5.unsigned(imm5_).out); D.sub : rr(RR_tag_); D.subi: ri(I5_tag_, E5.unsigned(imm5_).out); D.and : rr(RR_tag_); D.andi: ri(I5_tag_, E5.unsigned(imm5_).out); D.or : rr(RR_tag_); D.ori : ri(I5_tag_, E5.unsigned(imm5_).out); D.xor : rr(RR_tag_); D.xori: ri(I5_tag_, E5.unsigned(imm5_).out); D.sl : rr(RR_tag_); D.sli : ri(I5_tag_, E5. signed(imm5_).out); D.slt : rr(RR_tag_); D.slti: ri(I5_tag_, E5. signed(imm5_).out); D.sgt : rr(RR_tag_); D.sgti: ri(I5_tag_, E5. signed(imm5_).out); D.beqz: beqz(r1_, E8.signed(imm8_).out); D.bnez: bnez(r1_, E8.signed(imm8_).out); D.j : j(E11.signed(imm11_).out); D.jr : jr(r1_); D.rst : rst(); D.halt: halt(); D.nop : nop(); } any { ri|rir|rr|beqz|bnez|jr : r1req(r1_); rir|rr : r2req(r2_); } } } module cla4 { /* ** module cla4 ** ** 4bit carry look-ahead ** ** by NAGAMI Kou-ichi **** ** pin<4> : carry-propagation ** gin<4> : carry-generation ** cin : carry-in ** cout<4> : carry-out ** pout : carry-propagation ** gout : carry-generation */ input pin<4>, gin<4>, cin; output cout<4>, pout, gout; term c0_, c1_, c2_, c3_; instrin do; instruct do par { c0_ = gin<0> |(cin & pin<0>); c1_ = gin<1> |(gin<0> & pin<1>) |(cin & pin<0> & pin<1>); c2_ = gin<2> |(gin<1> & pin<2>) |(gin<0> & pin<1> & pin<2>) |(cin & pin<0> & pin<1> & pin<2>); c3_ = gin<3> |(gin<2> & pin<3>) |(gin<1> & pin<2> & pin<3>) |(gin<0> & pin<1> & pin<2> & pin<3>) |(cin & pin<0> & pin<1> & pin<2> & pin<3>); cout = c3_||c2_||c1_||c0_; pout = pin<0> & pin<1> & pin<2> & pin<3>; gout = gin<3> |(gin<2> & pin<3>) |(gin<1> & pin<2> & pin<3>) |(gin<0> & pin<1> & pin<2> & pin<3>); } } module bor4 { /* ** module bor4 ** ** 4bit bitwise OR module ** ** by NAGAMI Kou-ichi **** ** x<4>, y<4> : 4bit binaries ** z<4> : x \| y */ input x<4>, y<4>; output z<4>; instrin do; instruct do par { z = (x<3>|y<3>)||(x<2>|y<2>)||(x<1>|y<1>)||(x<0>|y<0>); } } module forward { submod_type tagdec { input tag<4>; output raddr<3>; instrin do; instrout is_reg; } submod_type eq3 { input x<3>, y<3>; instrin do; instrout eq; } /* EX stage's ALU out */ input exA_dtag<4>, exB_dtag<4>; input exA_aout<16>, exB_aout<16>; /* MEM stage's latch out */ input memA_dtag<4>, memB_dtag<4>; input memA_mar<16>, memB_mar<16>; /* mar holds alu-out data */ /* WB stage's latch out */ input wbA_dtag<4>, wbA_wdata<16>; input wbB_dtag<4>, wbB_wdata<16>; output fwdEAaddr<3>, fwdEAdata<16>, fwdEBaddr<3>, fwdEBdata<16>; output fwdMAaddr<3>, fwdMAdata<16>, fwdMBaddr<3>, fwdMBdata<16>; output fwdWAaddr<3>, fwdWAdata<16>, fwdWBaddr<3>, fwdWBdata<16>; tagdec EA_D, EB_D; tagdec MA_D, MB_D; tagdec WA_D, WB_D; eq3 EA_EB; eq3 MA_MB; eq3 WA_WB; eq3 MA_EA, MA_EB; eq3 MB_EA, MB_EB; eq3 WA_EA, WA_EB; eq3 WB_EA, WB_EB; eq3 WA_MA, WA_MB; eq3 WB_MA, WB_MB; instrin do; instrin exA_active, exB_active; instrin memA_active, memB_active; instrin wbA_active, wbB_active; instrout fwdEA, fwdEB; instrout fwdMA, fwdMB; instrout fwdWA, fwdWB; instruct_arg fwdEA(fwdEAaddr, fwdEAdata); instruct_arg fwdEB(fwdEBaddr, fwdEBdata); instruct_arg fwdMA(fwdMAaddr, fwdMAdata); instruct_arg fwdMB(fwdMBaddr, fwdMBdata); instruct_arg fwdWA(fwdWAaddr, fwdWAdata); instruct_arg fwdWB(fwdWBaddr, fwdWBdata); instruct_arg EA_D.do(tag); instruct_arg EB_D.do(tag); instruct_arg MA_D.do(tag); instruct_arg MB_D.do(tag); instruct_arg WA_D.do(tag); instruct_arg WB_D.do(tag); instruct_arg EA_EB.do(x, y); instruct_arg MA_MB.do(x, y); instruct_arg WA_WB.do(x, y); instruct_arg MA_EA.do(x, y); instruct_arg MA_EB.do(x, y); instruct_arg MB_EA.do(x, y); instruct_arg MB_EB.do(x, y); instruct_arg WA_EA.do(x, y); instruct_arg WA_EB.do(x, y); instruct_arg WB_EA.do(x, y); instruct_arg WB_EB.do(x, y); instruct_arg WA_MA.do(x, y); instruct_arg WA_MB.do(x, y); instruct_arg WB_MA.do(x, y); instruct_arg WB_MB.do(x, y); instruct do par { /* out register confliction check */ any { exA_active : EA_D.do(exA_dtag); exB_active : EB_D.do(exB_dtag); EA_D.is_reg & EB_D.is_reg: EA_EB.do(EA_D.raddr, EB_D.raddr); } any { memA_active : MA_D.do(memA_dtag); memB_active : MB_D.do(memB_dtag); MA_D.is_reg & MB_D.is_reg: MA_MB.do(MA_D.raddr, MB_D.raddr); MA_D.is_reg & EA_D.is_reg: MA_EA.do(MA_D.raddr, EA_D.raddr); MA_D.is_reg & EB_D.is_reg: MA_EB.do(MA_D.raddr, EB_D.raddr); MB_D.is_reg & EA_D.is_reg: MB_EA.do(MB_D.raddr, EA_D.raddr); MB_D.is_reg & EB_D.is_reg: MB_EB.do(MB_D.raddr, EB_D.raddr); } any { wbA_active : WA_D.do(wbA_dtag); wbB_active : WB_D.do(wbB_dtag); WA_D.is_reg & WB_D.is_reg: WA_WB.do(WA_D.raddr, WB_D.raddr); WA_D.is_reg & EA_D.is_reg: WA_EA.do(WA_D.raddr, EA_D.raddr); WA_D.is_reg & EB_D.is_reg: WA_EB.do(WA_D.raddr, EB_D.raddr); WB_D.is_reg & EA_D.is_reg: WB_EA.do(WB_D.raddr, EA_D.raddr); WB_D.is_reg & EB_D.is_reg: WB_EB.do(WB_D.raddr, EB_D.raddr); WA_D.is_reg & MA_D.is_reg: WA_MA.do(WA_D.raddr, MA_D.raddr); WA_D.is_reg & MB_D.is_reg: WA_MB.do(WA_D.raddr, MB_D.raddr); WB_D.is_reg & MA_D.is_reg: WB_MA.do(WB_D.raddr, MA_D.raddr); WB_D.is_reg & MB_D.is_reg: WB_MB.do(WB_D.raddr, MB_D.raddr); } any { EB_D.is_reg : fwdEB(EB_D.raddr, exB_aout); EA_D.is_reg & ^(EA_EB.eq): fwdEA(EA_D.raddr, exA_aout); MB_D.is_reg & ^(MB_EA.eq) & ^(MB_EB.eq): fwdMB(MB_D.raddr, memB_mar); MA_D.is_reg & ^(MA_MB.eq) & ^(MA_EA.eq) & ^(MA_EB.eq): fwdMA(MA_D.raddr, memA_mar); WB_D.is_reg & ^(WB_MA.eq) & ^(WB_MB.eq) & ^(WB_EA.eq) & ^(WB_EB.eq): fwdWB(WB_D.raddr, wbB_wdata); WA_D.is_reg & ^(WA_WB.eq) & ^(WA_MA.eq) & ^(WA_MB.eq) & ^(WA_EA.eq) & ^(WA_EB.eq): fwdWA(WA_D.raddr, wbA_wdata); } } } module tagdec { input tag<4>; output raddr<3>; instrin do; instrout is_reg; instruct_arg is_reg(); instruct do par { raddr = tag<2:0>; any { (^tag<3>) : is_reg(); } } } module mdecoder { submod_type icodedec { input icode<5>; instrin do; instrout lb, lbu, sb, lw, sw, lhi, lli, link; instrout add, addi, sub, subi, and, andi, or, ori; instrout xor, xori, sl, sli, slt, slti, sgt, sgti; instrout beqz, bnez, j, jr, rst, halt, nop; } input icode<5>; icodedec D; instrin do; instrout lb, lbu, lw, sb, sw; instruct_arg lb(); instruct_arg lbu(); instruct_arg lw(); instruct_arg sb(); instruct_arg sw(); instruct_arg D.do(icode); instruct do par { D.do(icode); any { D.lb : lb(); D.lbu : lbu(); D.sb : sb(); D.lw : lw(); D.sw : sw(); D.lhi : ; D.lli : ; D.link: ; D.add : ; D.addi: ; D.sub : ; D.subi: ; D.and : ; D.andi: ; D.or : ; D.ori : ; D.xor : ; D.xori: ; D.sl : ; D.sli : ; D.slt : ; D.slti: ; D.sgt : ; D.sgti: ; D.beqz: ; D.bnez: ; D.j : ; D.jr : ; D.rst : ; D.halt: ; } } } module dec2to4 { /* ** module dec2to4 ** ** 2bit -> 4bit decoder ** ** by NAGAMI Kou-ichi **** ** in<2> : binary encoded data ** out<4> : the number represented by `in' */ input in<2>; output out<4>; instrin do; instruct do par { out = (( in<1>)&( in<0>))|| (( in<1>)&(^in<0>))|| ((^in<1>)&( in<0>))|| ((^in<1>)&(^in<0>)); } } module expand5to16 { input in<5>; output out<16>; tmp s_<11>; instrin signed; instrin unsigned; instruct signed par { s_ = in<4>||in<4>||in<4>||in<4>|| in<4>||in<4>||in<4>||in<4>|| in<4>||in<4>||in<4>; out = s_||in; } instruct unsigned par { s_ = 0b00000000000; out = s_||in; } } module kamuri { submod_type Id { input iword<16>; input r1in<16>, r2in<16>, pcin<14>; output dtag<4>, opd1<16>, opd2<16>, opd3<16>; output r1addr<3>, r2addr<3>; instrin decode; instrout r1read, r2read; instrout done, halt; instrout beqz, bnez, j, jr, rst; } submod_type Ex { input icode<5>; input alu1<16>, alu2<16>; output aout<16>; instrin issue; } submod_type Mem { /* from latch */ input icode<5>; input sdata<16>, mar<16>; input dbus_in<16>; /* from dbus */ output addr<15>, mask<2>; output dbus_out<16>; output wdata<16>; /* result */ instrin access; instrin rdy, ack; instrout done; instrout read, write; instrout misalign; } submod_type Wb { input dtag<4>, wdata<16>; output addr<3>, data<16>; instrin do; instrout wback; } submod_type forward { /* EX stage's ALU out */ input exA_dtag<4>, exB_dtag<4>; input exA_aout<16>, exB_aout<16>; /* MEM stage's latch out */ input memA_dtag<4>, memB_dtag<4>; input memA_mar<16>, memB_mar<16>; /* mar holds alu-out data */ /* WB stage's latch out */ input wbA_dtag<4>, wbA_wdata<16>; input wbB_dtag<4>, wbB_wdata<16>; output fwdEAaddr<3>, fwdEAdata<16>, fwdEBaddr<3>, fwdEBdata<16>; output fwdMAaddr<3>, fwdMAdata<16>, fwdMBaddr<3>, fwdMBdata<16>; output fwdWAaddr<3>, fwdWAdata<16>, fwdWBaddr<3>, fwdWBdata<16>; instrin do; instrin exA_active, exB_active; instrin memA_active, memB_active; instrin wbA_active, wbB_active; instrout fwdEA, fwdEB; instrout fwdMA, fwdMB; instrout fwdWA, fwdWB; } submod_type idpath { /* register fetch info. */ input r1addr<3>, r1in<16>; input r2addr<3>, r2in<16>; /* forwarding information (to be generated by `forward').*/ input fwdEAaddr<3>, fwdEAdata<16>, fwdEBaddr<3>, fwdEBdata<16>; input fwdMAaddr<3>, fwdMAdata<16>, fwdMBaddr<3>, fwdMBdata<16>; input fwdWAaddr<3>, fwdWAdata<16>, fwdWBaddr<3>, fwdWBdata<16>; /* mux'ed result */ output r1out<16>, r2out<16>; instrin r1req, r2req; instrin fwdEA, fwdEB; instrin fwdMA, fwdMB; instrin fwdWA, fwdWB; } submod_type pcsv { input rdata<16>, pcin<14>, imm<16>; output pcout<14>; instrin reset; instrin eqz, nez, abs, rel, inc; /* must be exclusive */ instrin read; } submod_type regfile { input raddrA1<3>, raddrA2<3>, dinA<16>, waddrA<3>; input raddrB1<3>, raddrB2<3>, dinB<16>, waddrB<3>; output doutA1<16>, doutA2<16>; output doutB1<16>, doutB2<16>; instrin readA1, readA2, writeA; instrin readB1, readB2, writeB; } /* instruction/data memory I/O pins */ input ibus<32>, dbus_in<16>; output iaddr<14>, daddr<15>, dmask<2>, dbus_out<16>; output read_write; /* 0: read data 1: write data */ reg ID_PC_A<14>, IR_A<16>; reg IR_B<16>; reg EX_ICODE_A<5>; reg EX_DTAG_A<4>; reg OPD1_A<16>; reg OPD2_A<16>; reg OPD3_A<16>; reg EX_ICODE_B<5>; reg EX_DTAG_B<4>; reg OPD1_B<16>; reg OPD2_B<16>; /* reg OPD3_B<16>;*/ /* B pipe cannot exec. store */ reg MEM_ICODE_A<5>; reg MEM_DTAG_A<4>, SDATA_A<16>, MAR_A<16>; reg MEM_DTAG_B<4>, MAR_B<16>; reg WB_DTAG_A<4>, WDATA_A<16>; reg WB_DTAG_B<4>, WDATA_B<16>; Id ID_A, ID_B; Ex EX_A, EX_B; Mem MEM_A; Wb WB_A, WB_B; forward FWD; idpath IPATH_A, IPATH_B; pcsv PCSV; regfile RF; instrin chip_enable; /* chip activation */ instrin reset; /* reset */ instrin start_stop; /* start/stop toggle */ instrin irdy; /* instruction words has loaded on `ibus' */ instrin drdy; /* data words has loaded on `dbus_in' */ instrin dack; /* data store request has acknowledged */ instrout iread; /* instruction fetch request */ instrout daccess; /* data access request */ /* inner controll */ instrself IFbusy, IDbusy, EXbusy, MEMbusy, WBbusy; instrself IFgo, IDgo, EXgo, MEMgo, WBgo; instrself IFflush, IDflush, EXflush, MEMflush, WBflush; instrself halt; instruct_arg iread(iaddr); instruct_arg daccess(read_write, daddr, dmask); instruct_arg IFbusy(); instruct_arg IDbusy(); instruct_arg EXbusy(); instruct_arg MEMbusy(); instruct_arg WBbusy(); instruct_arg IFgo(); instruct_arg IDgo(); instruct_arg EXgo(); instruct_arg MEMgo(); instruct_arg WBgo(); instruct_arg IFflush(); instruct_arg IDflush(); instruct_arg EXflush(); instruct_arg MEMflush(); instruct_arg WBflush(); instruct_arg halt(); instruct_arg ID_A.decode(iword, pcin); instruct_arg ID_B.decode(iword, pcin); instruct_arg EX_A.issue(icode, alu1, alu2); instruct_arg EX_B.issue(icode, alu1, alu2); instruct_arg MEM_A.access(icode, sdata, mar); instruct_arg MEM_A.rdy(dbus_in); instruct_arg MEM_A.ack(); instruct_arg WB_A.do(dtag, wdata); instruct_arg WB_B.do(dtag, wdata); instruct_arg FWD.do(); instruct_arg FWD.exA_active(exA_dtag, exA_aout); instruct_arg FWD.exB_active(exB_dtag, exB_aout); instruct_arg FWD.memA_active(memA_dtag, memA_mar); instruct_arg FWD.memB_active(memB_dtag, memB_mar); instruct_arg FWD.wbA_active(wbA_dtag, wbA_wdata); instruct_arg FWD.wbB_active(wbB_dtag, wbB_wdata); instruct_arg IPATH_A.r1req(r1addr, r1in); instruct_arg IPATH_A.r2req(r2addr, r2in); instruct_arg IPATH_A.fwdEA(fwdEAaddr, fwdEAdata); instruct_arg IPATH_A.fwdEB(fwdEBaddr, fwdEBdata); instruct_arg IPATH_A.fwdMA(fwdMAaddr, fwdMAdata); instruct_arg IPATH_A.fwdMB(fwdMBaddr, fwdMBdata); instruct_arg IPATH_A.fwdWA(fwdWAaddr, fwdWAdata); instruct_arg IPATH_A.fwdWB(fwdWBaddr, fwdWBdata); instruct_arg IPATH_B.r1req(r1addr, r1in); instruct_arg IPATH_B.r2req(r2addr, r2in); instruct_arg IPATH_B.fwdEA(fwdEAaddr, fwdEAdata); instruct_arg IPATH_B.fwdEB(fwdEBaddr, fwdEBdata); instruct_arg IPATH_B.fwdMA(fwdMAaddr, fwdMAdata); instruct_arg IPATH_B.fwdMB(fwdMBaddr, fwdMBdata); instruct_arg IPATH_B.fwdWA(fwdWAaddr, fwdWAdata); instruct_arg IPATH_B.fwdWB(fwdWBaddr, fwdWBdata); instruct_arg PCSV.reset(); instruct_arg PCSV.eqz(rdata, pcin, imm); instruct_arg PCSV.nez(rdata, pcin, imm); instruct_arg PCSV.abs(rdata ); instruct_arg PCSV.rel( pcin, imm); instruct_arg PCSV.inc(); instruct_arg RF.readA1(raddrA1); instruct_arg RF.readA2(raddrA2); instruct_arg RF.writeA(waddrA, dinA); instruct_arg RF.readB1(raddrB1); instruct_arg RF.readB2(raddrB2); instruct_arg RF.writeB(waddrB, dinB); /* stage declarations */ stage_name CONTROLL { task controll(); } stage_name IF { task fetch(); } stage_name ID { task decode(ID_PC_A, IR_A, IR_B); } stage_name EX { task issue(EX_ICODE_A, EX_DTAG_A, OPD1_A, OPD2_A, OPD3_A, EX_ICODE_B, EX_DTAG_B, OPD1_B, OPD2_B/*, OPD3_B*/); } stage_name MEM { task access(MEM_ICODE_A, MEM_DTAG_A, SDATA_A, MAR_A, MEM_DTAG_B, MAR_B); } stage_name WB { task wback(WB_DTAG_A, WDATA_A, WB_DTAG_B, WDATA_B); } /* global actions */ /* forwarding netwark */ par { FWD.do(); any { FWD.fwdEA : par { IPATH_A.fwdEA(FWD.fwdEAaddr, FWD.fwdEAdata); IPATH_B.fwdEA(FWD.fwdEAaddr, FWD.fwdEAdata); } FWD.fwdEB : par { IPATH_A.fwdEB(FWD.fwdEBaddr, FWD.fwdEBdata); IPATH_B.fwdEB(FWD.fwdEBaddr, FWD.fwdEBdata); } FWD.fwdMA : par { IPATH_A.fwdMA(FWD.fwdMAaddr, FWD.fwdMAdata); IPATH_B.fwdMA(FWD.fwdMAaddr, FWD.fwdMAdata); } FWD.fwdMB : par { IPATH_A.fwdMB(FWD.fwdMBaddr, FWD.fwdMBdata); IPATH_B.fwdMB(FWD.fwdMBaddr, FWD.fwdMBdata); } FWD.fwdWA : par { IPATH_A.fwdWA(FWD.fwdWAaddr, FWD.fwdWAdata); IPATH_B.fwdWA(FWD.fwdWAaddr, FWD.fwdWAdata); } FWD.fwdWB : par { IPATH_A.fwdWB(FWD.fwdWBaddr, FWD.fwdWBdata); IPATH_B.fwdWB(FWD.fwdWBaddr, FWD.fwdWBdata); } } } instruct chip_enable par { generate CONTROLL.controll(); } instruct reset par { PCSV.reset(); IFflush(); IDflush(); EXflush(); MEMflush(); WBflush(); } /* CONTROLL stage */ stage CONTROLL { state_name idle; state_name running; first_state idle; any { ^chip_enable : finish; } state idle any { start_stop : goto running; } state running any { start_stop : goto idle; halt : goto idle; reset : goto idle; else : any { ^IFbusy : generate IF.fetch(); } } } /* end of CONTROLL stage */ /* IF stage */ stage IF { state_name dummy; first_state dummy; par { /* controll */ any { IDbusy : IFbusy(); IFflush : finish; else : IFgo(); } /* relay */ any { IFgo : par { iread(PCSV.read().pcout); any { irdy : par { relay ID.decode(PCSV.pcout, ibus<15:0>, ibus<31:16>); PCSV.inc(); } else : IFbusy(); } } } } } /* end of IF stage */ /* ID stage */ stage ID { state_name dummy; first_state dummy; par { /* controll */ any { EXbusy : IDbusy(); IDflush : finish; else : IDgo(); } ID_A.decode(IR_A, ID_PC_A); ID_B.decode(IR_B, ID_PC_A); /* register fetch : may be obsolete value */ any { ID_A.r1read : par { RF.readA1(ID_A.r1addr); ID_A.r1in = IPATH_A.r1req(ID_A.r1addr, RF.doutA1).r1out; } ID_A.r2read : par { RF.readA2(ID_A.r2addr); ID_A.r2in = IPATH_A.r2req(ID_A.r2addr, RF.doutA2).r2out; } ID_B.r1read : par { RF.readB1(ID_B.r1addr); ID_B.r1in = IPATH_B.r1req(ID_B.r1addr, RF.doutB1).r1out; } ID_B.r2read : par { RF.readB2(ID_B.r2addr); ID_B.r2in = IPATH_B.r2req(ID_B.r2addr, RF.doutB2).r2out; } } /* branch : [N.B.] only pipe A can handle branch instruction */ any { ID_A.beqz : PCSV.eqz(IPATH_A.r1out, ID_PC_A, ID_A.opd2<15:0>); ID_A.bnez : PCSV.nez(IPATH_A.r1out, ID_PC_A, ID_A.opd2<15:0>); ID_A.j : PCSV.rel( ID_PC_A, ID_A.opd2<15:0>); ID_A.jr : PCSV.abs(IPATH_A.r1out); ID_A.rst : PCSV.abs(0x0000); } /* relay */ any { IDgo : any { ID_A.done : par { relay EX.issue(IR_A<15:11>, ID_A.dtag, ID_A.opd1, ID_A.opd2, ID_A.opd3, IR_B<15:11>, ID_B.dtag, ID_B.opd1, ID_B.opd2 /*, ID_B.opd3*/); } ID_A.halt : par { halt(); IFflush(); } } } } } /* end of stage `ID' */ stage EX { state_name dummy; first_state dummy; par { /* controll */ any { MEMbusy : EXbusy(); EXflush : finish; else : EXgo(); } /* ALU operation */ EX_A.issue(EX_ICODE_A, OPD1_A, OPD2_A); EX_B.issue(EX_ICODE_B, OPD1_B, OPD2_B); /* forwarding */ FWD.exA_active(EX_DTAG_A, EX_A.aout); FWD.exB_active(EX_DTAG_B, EX_B.aout); /* relay */ any { EXgo : relay MEM.access(EX_ICODE_A, EX_DTAG_A, OPD3_A, EX_A.aout, EX_DTAG_B, EX_B.aout); } } } /* end of EX stage */ /* MEM stage */ stage MEM { state_name dummy; first_state dummy; par { /* controll */ any { WBbusy : MEMbusy(); MEMflush : finish; else : MEMgo(); } /* memory access */ /* [N.B.] only A pipe can handle load/store instruction */ MEM_A.access(MEM_ICODE_A, SDATA_A, MAR_A); any { MEM_A.read : par { daccess(0b0, MEM_A.addr, MEM_A.mask); } MEM_A.write : par { daccess(0b1, MEM_A.addr, MEM_A.mask); dbus_out = MEM_A.dbus_out; } } any { drdy : MEM_A.rdy(dbus_in); dack : MEM_A.ack(); } /* relay */ any { MEMgo : any { MEM_A.done : par { /* forwarding */ FWD.memA_active(MEM_DTAG_A, MEM_A.wdata); FWD.memB_active(MEM_DTAG_B, MAR_B); relay WB.wback(MEM_DTAG_A, MEM_A.wdata, MEM_DTAG_B, MAR_B); } else : MEMbusy(); } } } } /* end of MEM stage */ /* WB stage */ stage WB { state_name dummy; first_state dummy; par { /* forwarding */ FWD.wbA_active(WB_DTAG_A, WDATA_A); FWD.wbB_active(WB_DTAG_B, WDATA_B); /* write back */ WB_A.do(WB_DTAG_A, WDATA_A); WB_B.do(WB_DTAG_B, WDATA_B); any { WB_A.wback : RF.writeA(WB_A.addr, WB_A.data); WB_B.wback : RF.writeB(WB_B.addr, WB_B.data); } finish; } } /* end of WB stage */ } module align { input addr<16>, data<16>; input mode; output mask<2>, aligned_addr<15>, aligned_data<16>; instrin read, write; /* Exclusive! */ instrout misalign; instruct read any { (^mode)/*byte*/: any { (^addr<0>): par { aligned_addr = addr<15:1>; mask = 0b01; } ( addr<0>): par { aligned_addr = addr<15:1>; mask = 0b10; } } ( mode)/*word*/: any { (^addr<0>): par { aligned_addr = addr<15:1>; mask = 0b11; } ( addr<0>): misalign(); } } instruct write any { (^mode)/*byte*/: any { (^addr<0>): par { aligned_addr = addr<15:1>; aligned_data = data; mask = 0b01; } ( addr<0>): par { aligned_addr = addr<15:1>; mask = 0b10; aligned_data = data<7:0>||0x00; mask = 0b10; } } ( mode)/*word*/: any { (^addr<0>): par { aligned_addr = addr<15:1>; aligned_data = data; mask = 0b11; } ( addr<0>): misalign(); } } } module Mem { submod_type mdecoder { input icode<5>; instrin do; instrout lb, lbu, lw, sb, sw; } submod_type align { input addr<16>, data<16>; input mode; output mask<2>, aligned_addr<15>, aligned_data<16>; instrin read, write; /* Exclusive! */ instrout misalign; } submod_type expand8to16 { input in<8>; output out<16>; instrin signed, unsigned; } /* from latch */ input icode<5>; input sdata<16>, mar<16>; /* from dbus */ input dbus_in<16>; output addr<15>, mask<2>; output dbus_out<16>; /* result */ output wdata<16>; tmp byte_, word_; mdecoder D; align A; expand8to16 E; instrin access; instrin rdy, ack; instrout done; instrout read, write; instrout misalign; instruct_arg done(wdata); instruct_arg read(addr, mask); instruct_arg write(addr, mask, dbus_out); instruct_arg misalign(); instruct_arg D.do(icode); instruct_arg A.read(mode, addr); instruct_arg A.write(mode, addr, data); instruct_arg E.signed(in); instruct_arg E.unsigned(in); instruct access par { byte_ = 0b0; word_ = 0b1; D.do(icode); /* alignment */ any { D.lb : A.read (byte_, mar); D.lbu : A.read (byte_, mar); D.lw : A.read (word_, mar); D.sb : A.write(byte_, mar, sdata); D.sw : A.write(word_, mar, sdata); } /* memory access */ any { (^A.misalign) : any { (D.lb|D.lbu|D.lw) : read(A.aligned_addr, A.mask); D.lb : any { rdy : any { (^A.mask<0>)/*10*/: done(E.signed(dbus_in<15:8>).out); ( A.mask<0>)/*01*/: done(E.signed(dbus_in< 7:0>).out); } } D.lbu : any { rdy : any { (^A.mask<0>)/*10*/: done(E.unsigned(dbus_in<15:8>).out); ( A.mask<0>)/*01*/: done(E.unsigned(dbus_in< 7:0>).out); } } D.lw : any { rdy : done(dbus_in); } (D.sb|D.sw) : par { write(A.aligned_addr, A.mask, A.aligned_data); any { ack : done(mar); } /* argument is dummy */ } else : done(mar); /* argument is dummy */ } ( A.misalign) : par { misalign(); done(mar); } } } } /* module shift16 { /* ** module shift16 ** ** 16bit shifter ** ** by NAGAMI Kou-ichi **** ** x<16> : 16bit binary ** y<16> : ** z<16> : */ submod_type dec4to16 { input in<4>; output out<16>; instrin do; } input x<16>, y<16>; output z<16>; dec4to16 D; instrin do; instruct_arg D.do(in); instruct do any { (^y<15>) : par { D.do(y<3:0>); any { D.out<15> : z = x< 0>||0b000000000000000; D.out<14> : z = x< 1:0>||0b00000000000000; D.out<13> : z = x< 2:0>||0b0000000000000; D.out<12> : z = x< 3:0>||0b000000000000; D.out<11> : z = x< 4:0>||0b00000000000; D.out<10> : z = x< 5:0>||0b0000000000; D.out< 9> : z = x< 6:0>||0b000000000; D.out< 8> : z = x< 7:0>||0b00000000; D.out< 7> : z = x< 8:0>||0b0000000; D.out< 6> : z = x< 9:0>||0b000000; D.out< 5> : z = x<10:0>||0b00000; D.out< 4> : z = x<11:0>||0b0000; D.out< 3> : z = x<12:0>||0b000; D.out< 2> : z = x<13:0>||0b00; D.out< 1> : z = x<14:0>||0b0; D.out< 0> : z = x<15:0>; } } ( y<15>) : par { D.do(y<3:0>); any { D.out<15> : z = 0b0||x<15: 1>; D.out<14> : z = 0b00||x<15: 2>; D.out<13> : z = 0b000||x<15: 3>; D.out<12> : z = 0b0000||x<15: 4>; D.out<11> : z = 0b00000||x<15: 5>; D.out<10> : z = 0b000000||x<15: 6>; D.out< 9> : z = 0b0000000||x<15: 7>; D.out< 8> : z = 0b00000000||x<15: 8>; D.out< 7> : z = 0b000000000||x<15: 9>; D.out< 6> : z = 0b0000000000||x<15:10>; D.out< 5> : z = 0b00000000000||x<15:11>; D.out< 4> : z = 0b000000000000||x<15:12>; D.out< 3> : z = 0b0000000000000||x<15:13>; D.out< 2> : z = 0b00000000000000||x<15:14>; D.out< 1> : z = 0b000000000000000||x<15 >; D.out< 0> : z = 0b0000000000000000; } } } } */ module shift16 { /* ** module shift16 ** ** 16bit shifter ** ** by NAGAMI Kou-ichi **** ** x<16> : 16bit binary ** y<16> : ** z<16> : */ submod_type dec5to32 { input in<5>; output out<32>; instrin do; } input x<16>, y<16>; output z<16>; dec5to32 D; instrin do; instruct_arg D.do(in); instruct do par { D.do(y<15>||y<3:0>); any { D.out< 0>/* 0*/: z = x<15:0>; D.out< 1>/* 1*/: z = x<14:0>||0b0; D.out< 2>/* 2*/: z = x<13:0>||0b00; D.out< 3>/* 3*/: z = x<12:0>||0b000; D.out< 4>/* 4*/: z = x<11:0>||0b0000; D.out< 5>/* 5*/: z = x<10:0>||0b00000; D.out< 6>/* 6*/: z = x< 9:0>||0b000000; D.out< 7>/* 7*/: z = x< 8:0>||0b0000000; D.out< 8>/* 8*/: z = x< 7:0>||0b00000000; D.out< 9>/* 9*/: z = x< 6:0>||0b000000000; D.out<10>/* 10*/: z = x< 5:0>||0b0000000000; D.out<11>/* 11*/: z = x< 4:0>||0b00000000000; D.out<12>/* 12*/: z = x< 3:0>||0b000000000000; D.out<13>/* 13*/: z = x< 2:0>||0b0000000000000; D.out<14>/* 14*/: z = x< 1:0>||0b00000000000000; D.out<15>/* 15*/: z = x< 0>||0b000000000000000; D.out<16>/*-16*/: z = 0b0000000000000000; D.out<17>/*-15*/: z = 0b000000000000000||x<15 >; D.out<18>/*-14*/: z = 0b00000000000000||x<15:14>; D.out<19>/*-13*/: z = 0b0000000000000||x<15:13>; D.out<20>/*-12*/: z = 0b000000000000||x<15:12>; D.out<21>/*-11*/: z = 0b00000000000||x<15:11>; D.out<22>/*-10*/: z = 0b0000000000||x<15:10>; D.out<23>/*- 9*/: z = 0b000000000||x<15: 9>; D.out<24>/*- 8*/: z = 0b00000000||x<15: 8>; D.out<25>/*- 7*/: z = 0b0000000||x<15: 7>; D.out<26>/*- 6*/: z = 0b000000||x<15: 6>; D.out<27>/*- 5*/: z = 0b00000||x<15: 5>; D.out<28>/*- 4*/: z = 0b0000||x<15: 4>; D.out<29>/*- 3*/: z = 0b000||x<15: 3>; D.out<30>/*- 2*/: z = 0b00||x<15: 2>; D.out<31>/*- 1*/: z = 0b0||x<15: 1>; } } } module alu16 { /* ** module alu16 ** ** 16bit ALU ** ** by NAGAMI Kou-ichi **** ** x<16>, y<16> : 16bit binaries ** func<4> : function code ** z<16> : result */ submod_type adder16 { input x<16>, y<16>, cin; output z<16>, cout, sovf, pout, gout; instrin do; } submod_type shift16 { input x<16>, y<16>; output z<16>; instrin do; } submod_type band16 { input x<16>, y<16>; output z<16>; instrin do; } submod_type bor16 { input x<16>, y<16>; output z<16>; instrin do; } submod_type bxor16 { input x<16>, y<16>; output z<16>; instrin do; } submod_type bnot16 { input x<16>; output z<16>; instrin do; } submod_type eq16 { input x<16>, y<16>; instrin do; instrout eq; } submod_type dec4to16 { input in<4>; output out<16>; instrin do; } input x<16>, y<16>, func<4>; output z<16>; adder16 ADD; shift16 SL; band16 AND; bor16 OR; bxor16 XOR; bnot16 NOT; eq16 EQ; dec4to16 FD; /* Function Decoder */ instrin do; instruct_arg ADD.do(x, y, cin); instruct_arg SL.do(x, y); instruct_arg AND.do(x, y); instruct_arg OR.do(x, y); instruct_arg XOR.do(x, y); instruct_arg NOT.do(x); instruct_arg EQ.do(x, y); instruct_arg FD.do(in); instruct do par { FD.do(func); any { FD.out<15>: z = y; FD.out<14>: z = y<15:8>||x<7:0>; FD.out<13>: z = x<15:8>||y<7:0>; FD.out<12>: z = x; FD.out<11>: z = y; FD.out<10>: z = y<15:8>||x<7:0>; FD.out< 9>: z = x<15:8>||y<7:0>; FD.out< 8>: z = x; FD.out< 7>: par { /* > ? 1 : 0 */ EQ.do(x, y); ADD.do(x, NOT.do(y).z, 0b1); z = 0x000ob000||((ADD.sovf@(^ADD.z<15>))&(^EQ.eq)); } FD.out< 6>: par { /* < ? 1 : 0 */ ADD.do(x, NOT.do(y).z, 0b1); z = 0x000ob000||(ADD.sovf@ADD.z<15>); } FD.out< 5>: z = SL .do(x, y).z; FD.out< 4>: z = XOR.do(x, y).z; FD.out< 3>: z = OR .do(x, y).z; FD.out< 2>: z = AND.do(x, y).z; FD.out< 1>: z = ADD.do(x, NOT.do(y).z, 0b1).z; FD.out< 0>: z = ADD.do(x, y, 0b0).z; } } } module Ex { submod_type edecoder { input icode<5>; output func<4>; instrin do; } submod_type alu16 { input x<16>, y<16>, func<4>; output z<16>; instrin do; } input icode<5>; input alu1<16>, alu2<16>; output aout<16>; edecoder D; alu16 ALU; instrin issue; instruct_arg D.do(icode); instruct_arg ALU.do(x, y, func); instruct issue par { D.do(icode); ALU.do(alu1, alu2, D.func); aout = ALU.z; } } module eq16 { /* ** module eq16 ** ** 16bit equivalence checker ** ** by NAGAMI Kou-ichi **** ** x<16>, y<16> : 16bit binaries to be checked ** eq : (x == y) */ submod_type eq4 { input x<4>, y<4>; instrin do; instrout eq; } input x<16>, y<16>; eq4 E3, E2, E1, E0; instrin do; instrout eq; instruct_arg eq(); instruct_arg E3.do(x, y); instruct_arg E2.do(x, y); instruct_arg E1.do(x, y); instruct_arg E0.do(x, y); instruct do any { E3.do(x<15:12>, y<15:12>).eq & E2.do(x<11: 8>, y<11: 8>).eq & E1.do(x< 7: 4>, y< 7: 4>).eq & E0.do(x< 3: 0>, y< 3: 0>).eq : eq(); } } module adder16 { /* ** module adder16 ** ** 16bit binary adder (carry look-ahead) ** ** by NAGAMI Kou-ichi **** ** x<16>, y<16> : operands ** cin : carry-in ** z<16> : result ** cout : carry-out ** sovf : signed over flow ** pout : carry propagation ** gout : carry generation ** */ submod_type adder4 { input x<4>, y<4>, cin; output z<4>, cout, sovf, pout, gout; instrin do; } submod_type cla4 { input pin<4>, gin<4>, cin; output cout<4>, pout, gout; instrin do; } input x<16>, y<16>, cin; output z<16>, cout, sovf, pout, gout; term p_<4>, g_<4>, c_<4>; adder4 A3, A2, A1, A0; cla4 CLA; instrin do; instruct_arg A3.do(x, y, cin); instruct_arg A2.do(x, y, cin); instruct_arg A1.do(x, y, cin); instruct_arg A0.do(x, y, cin); instruct_arg CLA.do(pin, gin, cin); instruct do par { CLA.do(p_, g_, cin); A0.do(x< 3: 0>, y< 3: 0>, cin); A1.do(x< 7: 4>, y< 7: 4>, CLA.cout<0>); A2.do(x<11: 8>, y<11: 8>, CLA.cout<1>); A3.do(x<15:12>, y<15:12>, CLA.cout<2>); p_ = A3.pout||A2.pout||A1.pout||A0.pout; g_ = A3.gout||A2.gout||A1.gout||A0.gout; c_ = CLA.cout; z = A3.z||A2.z||A1.z||A0.z; cout = c_<3>; sovf = A3.sovf; pout = CLA.pout; gout = CLA.gout; } } module eq4 { /* ** module eq4 ** ** 4bit equivalence checker ** ** by NAGAMI Kou-ichi **** ** x<4>, y<4> : 4bit binaries to be checked ** eq : (x == y) */ submod_type eq2 { input x<2>, y<2>; instrin do; instrout eq; } input x<4>, y<4>; eq2 EH, EL; instrin do; instrout eq; instruct_arg eq(); instruct_arg EH.do(x, y); instruct_arg EL.do(x, y); instruct do any { EH.do(x<3:2>, y<3:2>).eq & EL.do(x<1:0>, y<1:0>).eq : eq(); } } module dec5to32 { /* ** module dec5to32 ** ** 5bit -> 32bit decoder ** ** by NAGAMI Kou-ichi **** ** in<5> : binary encoded data ** out<32> : the number represented by `in' */ submod_type dec2to4 { input in<2>; output out<4>; instrin do; } submod_type dec3to8 { input in<3>; output out<8>; instrin do; } submod_type gate4 { input in<4>, enable; output out<4>; instrin do; } input in<5>; output out<32>; dec2to4 DL; dec3to8 DH; gate4 G7, G6, G5, G4, G3, G2, G1, G0; instrin do; instruct_arg DH.do(in); instruct_arg DL.do(in); instruct_arg G7.do(in, enable); instruct_arg G6.do(in, enable); instruct_arg G5.do(in, enable); instruct_arg G4.do(in, enable); instruct_arg G3.do(in, enable); instruct_arg G2.do(in, enable); instruct_arg G1.do(in, enable); instruct_arg G0.do(in, enable); instruct do par { DH.do(in<4:2>); DL.do(in<1:0>); out = G7.do(DL.out, DH.out<7>).out|| G6.do(DL.out, DH.out<6>).out|| G5.do(DL.out, DH.out<5>).out|| G4.do(DL.out, DH.out<4>).out|| G3.do(DL.out, DH.out<3>).out|| G2.do(DL.out, DH.out<2>).out|| G1.do(DL.out, DH.out<1>).out|| G0.do(DL.out, DH.out<0>).out; } } module icodedec { submod_type dec5to32 { input in<5>; output out<32>; instrin do; } input icode<5>; dec5to32 D; instrin do; instrout lb, lbu, sb, lw, sw, lhi, lli, link; instrout add, addi, sub, subi, and, andi, or, ori; instrout xor, xori, sl, sli, slt, slti, sgt, sgti; instrout beqz, bnez, j, jr, rst, halt, nop; instruct_arg lb(); instruct_arg lbu(); instruct_arg sb(); instruct_arg lw(); instruct_arg sw(); instruct_arg lhi(); instruct_arg lli(); instruct_arg link(); instruct_arg add(); instruct_arg addi(); instruct_arg sub(); instruct_arg subi(); instruct_arg and(); instruct_arg andi(); instruct_arg or(); instruct_arg ori(); instruct_arg xor(); instruct_arg xori(); instruct_arg sl(); instruct_arg sli(); instruct_arg slt(); instruct_arg slti(); instruct_arg sgt(); instruct_arg sgti(); instruct_arg beqz(); instruct_arg bnez(); instruct_arg j(); instruct_arg jr(); instruct_arg rst(); instruct_arg halt(); instruct_arg nop(); instruct_arg D.do(in); instruct do par { D.do(icode); any { D.out< 0>: lb(); D.out< 1>: lbu(); D.out< 2>: sb(); D.out< 3>: lw(); D.out< 4>: sw(); D.out< 5>: lhi(); D.out< 6>: lli(); D.out< 7>: link(); D.out< 8>: add(); D.out< 9>: addi(); D.out<10>: sub(); D.out<11>: subi(); D.out<12>: and(); D.out<13>: andi(); D.out<14>: or(); D.out<15>: ori(); D.out<16>: xor(); D.out<17>: xori(); D.out<18>: sl(); D.out<19>: sli(); D.out<20>: slt(); D.out<21>: slti(); D.out<22>: sgt(); D.out<23>: sgti(); D.out<24>: beqz(); D.out<25>: bnez(); D.out<26>: j(); D.out<27>: jr(); D.out<28>: rst(); D.out<29>: halt(); D.out<30>: nop(); D.out<31>: nop(); } } } module pcsv { submod_type adder16 { input x<16>, y<16>, cin; output z<16>, cout, sovf, pout, gout; instrin do; } submod_type eq16 { input x<16>, y<16>; instrin do; instrout eq; } input rdata<16>, pcin<14>, imm<16>; output pcout<14>; reg PC<14>; adder16 Ar, Ai; eq16 E; instrin reset; instrin eqz, nez, abs, rel, inc; /* must be exclusive */ instrin read; instruct_arg Ar.do(x, y, cin); instruct_arg Ai.do(x, y, cin); instruct_arg E.do(x, y); alt { reset : PC := 0b00x000; else : par { any { eqz|nez : E.do(rdata, 0x0000); } any { eqz& E.eq : PC := Ar.do(0b00||pcin, imm, 0b0).z<13:0>; nez&^E.eq : PC := Ar.do(0b00||pcin, imm, 0b0).z<13:0>; abs : PC := rdata<13:0>; rel : PC := Ar.do(0b00||pcin, imm, 0b0).z<13:0>; else : any { inc : PC := Ai.do(0b00|| PC, 0x0001, 0b0).z<13:0>; } } } } instruct read pcout = PC; } module Id { submod_type idecoder { input iword<16>; output r1addr<3>, r2addr<3>, imm<16>, tag<4>; instrin do; instrout rr, ri, pi, rir; instrout beqz, bnez, j, jr, rst, halt, nop; instrout r1req, r2req; } input iword<16>, pcin<14>; input r1in<16>, r2in<16>; output dtag<4>, opd1<16>, opd2<16>, opd3<16>; output r1addr<3>, r2addr<3>; tmp pc_<16>, nil_<16>, it_<4>; idecoder D; instrin decode; instrout r1read, r2read; instrout done, halt; instrout beqz, bnez, j, jr, rst; instruct_arg r1read(r1addr); instruct_arg r2read(r2addr); instruct_arg done(dtag, opd1, opd2, opd3); instruct_arg halt(); instruct_arg beqz(r1addr); instruct_arg bnez(r1addr); instruct_arg j(); instruct_arg jr(r1addr); instruct_arg rst(); instruct_arg D.do(iword); instruct decode par { D.do(iword); /* register fetch */ any { D.r1req : par { r1read(D.r1addr); } D.r2req : par { r2read(D.r2addr); } } /* operand mode */ it_ = 0b1111; nil_ = 0x0000; pc_ = 0b00||pcin; any { D.rr : done(D.tag, r1in, r2in, nil_); D.ri : done(D.tag, r1in, D.imm, nil_); D.pi : done(D.tag, pc_, D.imm, nil_); D.rir : done(D.tag, r1in, D.imm, r2in); D.beqz: done( it_, nil_, D.imm, nil_); D.bnez: done( it_, nil_, D.imm, nil_); D.j : done( it_, nil_, D.imm, nil_); D.jr : done( it_, nil_, nil_, nil_); D.rst : done( it_, nil_, nil_, nil_); D.halt: done( it_, nil_, nil_, nil_); D.nop : done( it_, nil_, nil_, nil_); } /* branch */ any { D.beqz: beqz(D.r1addr); D.bnez: bnez(D.r1addr); D.j : j(); D.jr : jr(D.r1addr); D.rst : rst(); D.halt: halt(); } } } module regfile { /* ** module regfile ** ** register file ** ** by NAGAMI Kou-ichi **** ** ** raddrA1<3>, raddrA2<3>, waddrA<3> : read/write addresses of access A ** raddrB1<3>, raddrB2<3>, waddrB<3> : - B ** dinA<16>, doutA<16> : read/write data of access A ** dinB<16>, doutB<16> : - B ** */ submod_type reg16cell8 { input raddr0<3>, raddr1<3>, raddr2<3>, raddr3<3>; input waddr0<3>, waddr1<3>, din0<16>, din1<16>; output dout0<16>, dout1<16>, dout2<16>, dout3<16>; instrin read0, read1, read2, read3; instrin write0, write1; } submod_type eq3 { input x<3>, y<3>; instrin do; instrout eq; } input raddrA1<3>, raddrA2<3>, dinA<16>, waddrA<3>; input raddrB1<3>, raddrB2<3>, dinB<16>, waddrB<3>; output doutA1<16>, doutA2<16>; output doutB1<16>, doutB2<16>; term dh_<8>, dl_<8>, mh_, ml_; reg16cell8 R; eq3 EQ; instrin readA1, readA2, writeA; instrin readB1, readB2, writeB; instruct_arg R.read0(raddr0); instruct_arg R.read1(raddr1); instruct_arg R.read2(raddr2); instruct_arg R.read3(raddr3); instruct_arg R.write0(waddr0, din0); instruct_arg R.write1(waddr1, din1); instruct_arg EQ.do(x, y); /* write processes */ any { writeA & writeB : EQ.do(waddrA, waddrB); (^EQ.eq) : any { /* exclusive write */ writeA : R.write0(waddrA, dinA); writeB : R.write1(waddrB, dinB); } ( EQ.eq) : par { R.write1(waddrB, dinB); } } /* read processes */ instruct readA1 doutA1 = R.read0(raddrA1).dout0; instruct readA2 doutA2 = R.read1(raddrA2).dout1; instruct readB1 doutB1 = R.read2(raddrB1).dout2; instruct readB2 doutB2 = R.read3(raddrB2).dout3; }