Skip to content
Draft
Show file tree
Hide file tree
Changes from 38 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
b8e61d1
add pc module
gabizon103 Jun 12, 2023
94c5d72
add pc
gabizon103 Jun 12, 2023
b0ce2b2
try some harness things
gabizon103 Jun 13, 2023
6cabf67
attempt more harness
gabizon103 Jun 14, 2023
38afd67
(mostly) correct calyx
gabizon103 Jun 14, 2023
78f8722
harness works now
gabizon103 Jun 15, 2023
0faf054
cleanup
gabizon103 Jun 15, 2023
3a6a006
Merge branch 'main' into frisc
gabizon103 Jun 15, 2023
39bbbf7
compile things without main
gabizon103 Jun 16, 2023
2c0400b
rm gen files, add script
gabizon103 Jun 16, 2023
1d9caec
format
gabizon103 Jun 16, 2023
a63839c
format
gabizon103 Jun 16, 2023
4006e38
format
gabizon103 Jun 16, 2023
02e1b80
Merge branch 'main' into frisc
gabizon103 Jun 16, 2023
70465a0
set default to main
gabizon103 Jun 19, 2023
496443d
add pc
gabizon103 Jun 19, 2023
2bb2b6f
pc works with cpu
gabizon103 Jun 19, 2023
0939ee3
add pc
gabizon103 Jun 19, 2023
8412985
remove comb cycle
gabizon103 Jun 20, 2023
3899590
add load/stores
gabizon103 Jun 20, 2023
9034893
mess around with harness things
gabizon103 Jun 20, 2023
7e45734
add mem prim?
gabizon103 Jun 20, 2023
719c4bf
integrate dram in filament program
gabizon103 Jun 21, 2023
bc9ee00
it works
gabizon103 Jun 21, 2023
3f83dcc
harness works
gabizon103 Jun 21, 2023
896427f
remove gen files
gabizon103 Jun 21, 2023
0c85266
add lb and lh, untested
gabizon103 Jun 21, 2023
adc5590
add hw and byte instrs
gabizon103 Jun 22, 2023
a067a03
test
gabizon103 Jun 22, 2023
f4acacc
fix resets
gabizon103 Jun 23, 2023
e2ed443
merge
gabizon103 Jul 8, 2024
8430fa2
cleanup
gabizon103 Jul 8, 2024
5c6e91f
Merge branch 'main' into frisc
gabizon103 Sep 30, 2024
a4f3855
reformat
gabizon103 Nov 11, 2024
baea5f0
remove code
gabizon103 Nov 11, 2024
562a568
remove memory primitive
gabizon103 Nov 11, 2024
79f996f
Merge branch 'main' into frisc
gabizon103 Nov 11, 2024
dc7d597
Merge branch 'main' into frisc
gabizon103 Nov 12, 2024
b9dbeca
frisc tests
gabizon103 Nov 26, 2024
a005ba3
testing things
gabizon103 Dec 7, 2024
4956621
cleanup
gabizon103 Jan 17, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions apps/frisc/README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
# `frisc`: A RISC-V Processor in Filament

`frisc` is an experimental, statically-scheduled [RISC-V processor][riscv] written in Filament that implements the base instruction set.
`frisc` is an experimental, statically-scheduled [RISC-V processor][riscv] written that implements the base instruction set.
We're implementing simple 3-stage pipeline and after validating it, will work on more complex pipelines and instruction extensions.

The driver code is written in Calyx and invokes modules generated by Filament.

[riscv]: https://riscv.org/wp-content/uploads/2017/05/riscv-spec-v2.2.pdf
[riscv]: https://riscv.org/wp-content/uploads/2017/05/riscv-spec-v2.2.pdf
Empty file added apps/frisc/harness/frisc.futil
Empty file.
6 changes: 3 additions & 3 deletions apps/frisc/harness/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
# Script that will compile the RISC-V core, run the Calyx harness, and then
# delete generated files

cargo run -- ../src/cpu.fil --library ../.. --toplevel CPU > frisc.futil
cargo run --bin filament ../src/cpu.fil --library ../../.. > frisc.futil

fud exec top.futil --to dat --through icarus-verilog -s verilog.data top.json \
--from futil
--from calyx

rm frisc.futil
# rm frisc.futil

rm model.smt
48 changes: 24 additions & 24 deletions apps/frisc/harness/top.futil
Original file line number Diff line number Diff line change
@@ -1,46 +1,46 @@
import "primitives/memories.futil";
import "frisc.futil";
import "primitives/memories/comb.futil";

component main () -> (out:32) {
cells {
@external iram = seq_mem_d1(32,5,32);
@external res = seq_mem_d1(32,5,32);
@external iram = comb_mem_d1(32,6,32);
@external res = comb_mem_d1(32,6,32);
cpu = CPU();
dram = ByteAccess1D(256,32);

pc = std_reg(32);
pc1 = std_reg(32);
pc_adder = std_add(32);

add_cond = std_add(32);
pc_reg = std_reg(32);
}
wires {
static<1> group init {
pc.in = 32'd0;
pc.write_en = 1'd1;
pc1.in = 32'd0;
pc1.write_en = 1'd1;
pc_reg.in = 32'd0;
pc_reg.write_en = 1'b1;
}

static<1> group read_iram {
iram.addr0 = pc.out;
iram.addr0 = cpu.pc;
iram.read_en = 1'b1;

cpu.instr = iram.read_data;
}
cpu.dataIn = dram.read_data;

static<1> group inc_counter {
add_cond.left = pc.out;
add_cond.right = 32'd1;
pc.in = add_cond.out;
pc.write_en = %0 ? 1'd1;
pc1.in = pc.out;
pc1.write_en = %0 ? 1'd1;
dram.addr0 = cpu.memAddr;
dram.write_data = cpu.memData;
dram.write_mask = cpu.memWriteMask;
}

static<1> group write_res {
res.addr0 = pc1.out;
res.addr0 = pc_reg.out;
res.write_data = cpu.out;
res.write_en = %0 ? 1'd1;
}

static<1> group reg_pc {
pc_reg.in = cpu.pc;
pc_reg.write_en = 1'd1;
}

cpu.pcin = cpu.nextpc;
cpu.rfDataIn = cpu.rfDataOut;
}
control {
static seq {
Expand All @@ -49,8 +49,8 @@ component main () -> (out:32) {
static par {
read_iram;
write_res;
inc_counter;
}
reg_pc;
}
}
}
}
Expand Down
16 changes: 11 additions & 5 deletions apps/frisc/harness/top.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
{
"iram": {
"data": [1074823347,1081491,2130067,3178643,4227219],
"data": [
"sub x1 x1 x1",
"addi x2 x1 99",
"addi x2 x2 1",
"addi x2 x2 1",
"addi x2 x2 1",
"addi x2 x2 1"
],
"format": {
"numeric_type": "bitnum",
"is_signed": false,
"width": 32
"numeric_type": "risc-v",
"isa": "32i"
}
},
"res": {
"data": [9999,200,200,200,200],
"data": [9999,9999,9999,9999,9999,9999],
"format": {
"numeric_type": "bitnum",
"is_signed": false,
Expand Down
22 changes: 11 additions & 11 deletions apps/frisc/src/alu.fil
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import "primitives/core.fil";
import "./extras/extras.fil";
import "apps/frisc/src/extras/extras.fil";

comp ALU<'G:1> (
inA: ['G,'G+1] 32,
inB: ['G,'G+1] 32,
funct: ['G,'G+1] 8, // one-hot encoding
isAdd: ['G,'G+1] 1, // 1 if add, 0 if sub
isArith: ['G,'G+1] 1, // 0 if log, 1 if arith
inA: ['G, 'G+1] 32,
inB:['G, 'G+1] 32,
funct: ['G, 'G+1] 8, // one-hot encodin'G
isAdd: ['G, 'G+1] 1, // 1 if add, 0 if sub
isArith: ['G, 'G+1] 1, // 0 if lo'G, 1 if arith
) -> (
out: ['G,'G+1] 32
out: ['G, 'G+1] 32
) {
oneConst_1b := new Const[1,1]<'G>();
oneConst_33b := new Const[33,1]<'G>();
Expand All @@ -31,17 +31,17 @@ comp ALU<'G:1> (

shamt := new Slice[32,4,0,5]<'G>(inB);
shamt_ext := new ZeroExtend[5,32]<'G>(shamt.out);

xor := new Xor[32]<'G>(inA, inB);
or := new Or[32]<'G>(inA, inB);
and := new And[32]<'G>(inA, inB);
sr := new RightShifter[32]<'G>(inA, shamt_ext.out, isArith);
sll := new ShiftLeft[32]<'G>(inA, inB);

aluMinus32 := new Select[33,32]<'G>(aluMinus.out);

ltguard := new Xor[1]<'G>(inA31.out, inB31.out);
ltTernary := new Mux[1]<'G>(ltguard.out, inA31.out, aluMinus32.out);
ltGuard := new Xor[1]<'G>(inA31.out, inB31.out);
ltTernary := new Mux[1]<'G>(ltGuard.out, inA31.out, aluMinus32.out);
lt := new ZeroExtend[1,32]<'G>(ltTernary.out);
ltu := new ZeroExtend[1,32]<'G>(aluMinus32.out);

Expand Down
199 changes: 186 additions & 13 deletions apps/frisc/src/cpu.fil
Original file line number Diff line number Diff line change
@@ -1,31 +1,204 @@
import "./alu.fil";
import "./decode.fil";
import "./regfile.fil";
import "./extras/extras.fil";
import "apps/frisc/src/alu.fil";
import "apps/frisc/src/decode.fil";
import "apps/frisc/src/regfile.fil";
import "apps/frisc/src/extras/extras.fil";
import "apps/frisc/src/pc.fil";

comp CPU<'G:1> (
clk:1,
//go: interface['G],
reset: ['G,'G+1] 1,
instr: ['G,'G+1] 32
reset:1,
instr: ['G,'G+1] 32,
pcin: ['G,'G+1] 32,
dataIn: ['G,'G+1] 32,
rfDataIn: ['G,'G+1] 32,
) -> (
out: ['G,'G+1] 32,
aluInA: ['G,'G+1] 32,
aluInB: ['G,'G+1] 32,
pc: ['G,'G+1] 32, // current instr
nextpc: ['G,'G+1] 32, // next instr to fetch
out: ['G,'G+1] 32, // output of ALU
memAddr: ['G,'G+1] 32, // memory address
memData: ['G,'G+1] 32, // data to write to mem
memWriteMask: ['G,'G+1] 4, // 4 bytes in a word
rfDataOut: ['G,'G+1] 32
) {

/* ============================================================ */
/* DECODER
/* ============================================================ */

rd := new Slice[32,11,7,5]<'G>(instr);
rs1 := new Slice[32,19,15,5]<'G>(instr);
rs2 := new Slice[32,24,20,5]<'G>(instr);

decoder := new Decode<'G>(instr);
rf := new RegFile<'G>(reset, decoder.rf_write, rd.out, alu.out, rs1.out, rs2.out);

/* ============================================================ */
/* REGISTER FILE
/* ============================================================ */

// Set register file data in - use 1-hot encoding bc why not
// {0, 0, 0, isLUI, isALU, isAUIPC, isJ, isLoad}

// 00000001 -> isLoad, so use memDataIn
// 00000010 -> isJ, so use pcPlus4
// 00000100 -> isAUIPC, so use pcPlusImm
// 00001000 -> isALU, so use alu.out
// 00010000 -> isLUI, so use decoder.Uimm

const0 := new Const[32,0]<'G>();
isALU := new Or[1]<'G>(decoder.isALUImm, decoder.isALUReg);
isJ := new Or[1]<'G>(decoder.isJALR, decoder.isJAL);

c0 := new Concat[1,1,2]<'G>(decoder.isLUI, isALU.out);
c1 := new Concat[1,1,2]<'G>(decoder.isAUIPC, isJ.out);
c2 := new Concat[2,1,3]<'G>(c1.out, decoder.isLoad);
c3 := new Concat[2,3,5]<'G>(c0.out, c2.out);
dInSel := new ZeroExtend[5,8]<'G>(c3.out);

rfData := new OneHotMux[32]<'G>(dInSel.out, loadData.out, pcPlus4.out, pcPlusImm.out, alu.out,
decoder.Uimm, const0.out, const0.out, const0.out);

rf := new RegFile<'G>(decoder.rf_write, rd.out, rfDataIn, rs1.out, rs2.out);

/* ============================================================ */
/* LOAD/STORE
/* ============================================================ */

// LOADS
const0_2 := new Const[2,0]<'G>();
const1_2 := new Const[2,1]<'G>();

instr13_12 := new Slice[32,13,12,2]<'G>(instr);
instr14 := new Select[32,14]<'G>(instr);
byteAccess := new Eq[2]<'G>(instr13_12.out, const0_2.out);
hwAccess := new Eq[2]<'G>(instr13_12.out, const1_2.out);

hwSign := new Select[16,15]<'G>(hw.out);
bSign := new Select[8,7]<'G>(byte.out);

accessSign := new Mux[1]<'G>(byteAccess.out, bSign.out, hwSign.out);
not14 := new Not[1]<'G>(instr14.out);
loadSign := new And[1]<'G>(not14.out, accessSign.out);

loadByteSign := new Extend[1,24]<'G>(loadSign.out);
loadHWSign := new Extend[1,16]<'G>(loadSign.out);

loadHW := new Concat[16,16,32]<'G>(loadHWSign.out, hw.out);
loadByte := new Concat[24,8,32]<'G>(loadByteSign.out, byte.out);

hwOrW := new Mux[32]<'G>(hwAccess.out, loadHW.out, dataIn);
loadData := new Mux[32]<'G>(byteAccess.out, loadByte.out, hwOrW.out);

addr1 := new Select[32,1]<'G>(loadStoreAddr.out);
dataInUpper := new Slice[32,31,16,16]<'G>(dataIn);
dataInLower := new Slice[32,15,0,16]<'G>(dataIn);
hw := new Mux[16]<'G>(addr1.out, dataInUpper.out, dataInLower.out);

addr0 := new Select[32,0]<'G>(loadStoreAddr.out);
loadHUpper := new Slice[16,15,8,8]<'G>(hw.out);
loadHLower := new Slice[16,7,0,8]<'G>(hw.out);
byte := new Mux[8]<'G>(addr0.out, loadHUpper.out, loadHLower.out);

addrAdder := new Add[32];
addrImm := new Mux[32]<'G>(decoder.isStore, decoder.Simm, decoder.Iimm);
loadStoreAddr := addrAdder<'G>(rf.rs1, addrImm.out);

// STORES
rs2_7_0 := new Slice[32,7,0,8]<'G>(rf.rs2);
rs2_15_8 := new Slice[32,15,8,8]<'G>(rf.rs2);
rs2_23_16 := new Slice[32,23,16,8]<'G>(rf.rs2);
rs2_31_24 := new Slice[32,31,24,8]<'G>(rf.rs2);

memAddr_0 := new Select[32,0]<'G>(loadStoreAddr.out);
memAddr_1 := new Select[32,1]<'G>(loadStoreAddr.out);

memData_15_8 := new Mux[8]<'G>(memAddr_0.out,rs2_7_0.out, rs2_15_8.out);
memData_23_16 := new Mux[8]<'G>(memAddr_1.out, rs2_7_0.out, rs2_23_16.out);

_mux0 := new Mux[8]<'G>(memAddr_1.out, rs2_15_8.out, rs2_31_24.out);
memData_31_24 := new Mux[8]<'G>(memAddr_0.out, rs2_7_0.out, _mux0.out);

memData_31_16 := new Concat[8,8,16]<'G>(memData_31_24.out, memData_23_16.out);
memData_15_0 := new Concat[8,8,16]<'G>(memData_15_8.out, rs2_7_0.out);
memData_31_0 := new Concat[16,16,32]<'G>(memData_31_16.out, memData_15_0.out);

// WRITE MASK
// 1111 -> write a whole word
// 0011 or 1100 -> write a halfword
// 0001, 0010, 0100, 1000 -> write a byte

maskWord := new Const[4,15]<'G>(); // 1111
maskHWUp := new Const[4, 12]<'G>(); // 1100
maskHWLow := new Const[4,3]<'G>(); // 0011
maskByte0 := new Const[4,1]<'G>(); // 0001
maskByte1 := new Const[4,2]<'G>(); // 0010
maskByte2 := new Const[4,4]<'G>(); // 0100
maskByte3 := new Const[4,8]<'G>(); // 1000

_muxHW_HL := new Mux[4]<'G>(memAddr_1.out, maskHWUp.out, maskHWLow.out);
_muxHW := new Mux[4]<'G>(hwAccess.out, _muxHW_HL.out, maskWord.out);

_muxB_3_2 := new Mux[4]<'G>(memAddr_0.out, maskByte3.out, maskByte2.out);
_muxB_1_0 := new Mux[4]<'G>(memAddr_0.out, maskByte1.out, maskByte0.out);
_muxB_HL := new Mux[4]<'G>(memAddr_1.out, _muxB_3_2.out, _muxB_1_0.out);

writeMask := new Mux[4]<'G>(byteAccess.out, _muxB_HL.out, _muxHW.out);

/* ============================================================ */
/* DATA MEMORY
/* ============================================================ */

// sz, dw, aw read_addr write_en write_addr write_data
dataMem := new Mem1D[32, 32, 32]<'G>(loadStoreAddr.out, decoder.isStore, loadStoreAddr.out, rf.rs2);

/* ============================================================ */
/* ALU
/* ============================================================ */

aluInBGuard := new Or[1]<'G>(decoder.isBranch, decoder.isALUReg);
aluInB := new Mux[32]<'G>(aluInBGuard.out, rf.rs2, decoder.Iimm);

alu := new ALU<'G>(rf.rs1, aluInB.out, decoder.funct, decoder.isAdd, decoder.isArith);

/* ============================================================ */
/* PROGRAM COUNTER
/* ============================================================ */

pc := new PC<'G>(pcin);

// nextPC = isJAL ? Jimm : isAUIPC ? Uimm : Bimm
// for jumps
pcAdderImm := new Add[32];

// not jumps
pcAdder := new Add[32];

// Compute what we add to PC
// isJAL ? Jimm : isAUIPC ? Uimm : Bimm
t0 := new Mux[32]<'G>(decoder.isAUIPC, decoder.Uimm, decoder.Bimm);
t1 := new Mux[32]<'G>(decoder.isJAL, decoder.Jimm, t0.out);

// No jumps - next instr
const1 := new Const[32,1]<'G>();

// compute nextPC
pcPlusImm := pcAdderImm<'G>(pc.pc, t1.out);
pcPlus4 := pcAdder<'G>(pc.pc, const1.out);

// isBranch || isJAL || isAUIPC
branchJmp := new Or[1]<'G>(decoder.isBranch, decoder.isJAL);
useImm := new Or[1]<'G>(branchJmp.out, decoder.isAUIPC);

nextPC := new Mux[32]<'G>(useImm.out, pcPlusImm.out, pcPlus4.out);

/* ============================================================ */
/* OUTPUTS
/* ============================================================ */

out = alu.out;
aluInA = rf.rs1;
aluInB = aluInB.out;
nextpc = nextPC.out;
pc = pc.pc;
memAddr = loadStoreAddr.out;
memData = memData_31_0.out;
memWriteMask = writeMask.out;
rfDataOut = rfData.out;
}
Loading