Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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
213 changes: 213 additions & 0 deletions apps/frisc/harness/expected.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
import argparse
from harness import parse_instrs, init, reg_to_binary, generate_json
import tests
from tests import *
import json
import subprocess
import os

def run_instr_seq(instrs, mem, rf):
for instr in instrs:
run_instr(instr, mem, rf)
return mem

def parse_rtype(instr):
rd = instr[1]
rs1 = instr[2]
rs2 = instr[3]
return [rd, rs1, rs2]

def parse_itype(instr):
rd = instr[1]
rs1 = instr[2]
imm = int(instr[3])
return [rd, rs1, imm]

def parse_store(instr):
rs2 = instr[1]
imm_rs1 = instr[2]
[imm, rs1] = imm_rs1.split('(')
rs1 = rs1.split(')')[0]
return [rs1, rs2, int(imm)]

def parse_load(instr):
rd = instr[1]
imm_rs1 = instr[2]
[imm, rs1] = imm_rs1.split('(')
rs1 = rs1.split(')')[0]
return [rd, rs1, int(imm)]

def unsigned(n):
return n & 0xffffffff

def run_instr(instr, mem, rf):
instr_split = instr.split(' ')
op = instr_split[0]
match op:
case "add":
[rd, rs1, rs2] = parse_rtype(instr_split)
rf[rd] = rf[rs1] + rf[rs2]
case "sub":
[rd, rs1, rs2] = parse_rtype(instr_split)
rf[rd] = rf[rs1] - rf[rs2]
case "xor":
[rd, rs1, rs2] = parse_rtype(instr_split)
rf[rd] = rf[rs1] ^ rf[rs2]
case "or":
[rd, rs1, rs2] = parse_rtype(instr_split)
rf[rd] = rf[rs1] | rf[rs2]
case "and":
[rd, rs1, rs2] = parse_rtype(instr_split)
rf[rd] = rf[rs1] & rf[rs2]
case "sll":
[rd, rs1, rs2] = parse_rtype(instr_split)
rf[rd] = rf[rs1] << rf[rs2]
case "sra":
[rd, rs1, rs2] = parse_rtype(instr_split)
rf[rd] = rf[rs1] >> rf[rs2]
case "slt":
[rd, rs1, rs2] = parse_rtype(instr_split)
rf[rd] = rf[rs1] < rf[rs2]
case "sltu": # todo
[rd, rs1, rs2] = parse_rtype(instr_split)
rf[rd] = rf[rs1] < rf[rs2]
case "addi":
[rd, rs1, imm] = parse_itype(instr_split)
rf[rd] = rf[rs1] + imm
case "xori":
[rd, rs1, imm] = parse_itype(instr_split)
rf[rd] = rf[rs1] ^ imm
case "ori":
[rd, rs1, imm] = parse_itype(instr_split)
rf[rd] = rf[rs1] | imm
case "andi":
[rd, rs1, imm] = parse_itype(instr_split)
rf[rd] = rf[rs1] & imm
case "slli":
[rd, rs1, imm] = parse_itype(instr_split)
rf[rd] = rf[rs1] << imm
case "srli":
[rd, rs1, imm] = parse_itype(instr_split)
rf[rd] = rf[rs1] >> imm
case "srai":
[rd, rs1, imm] = parse_itype(instr_split)
rf[rd] = rf[rs1] >> imm
case "slti":
[rd, rs1, imm] = parse_itype(instr_split)
rf[rd] = rf[rs1] < imm
case "sltiu":
[rd, rs1, imm] = parse_itype(instr_split)
rf[rd] = rf[rs1] < imm
case "sw":
[rs1, rs2, imm] = parse_store(instr_split)
mem[rf[rs1]+imm] = rf[rs2]
case "lw":
[rd, rs1, imm] = parse_load(instr_split)
rd = mem[rf[rs1]+imm]

# Formats mem as an array
def mem_to_array(mem):
mem_arr = [99999] * 64
for k in sorted(mem.keys()):
mem_arr[k] = mem[k]
return mem_arr

# Formats a result memory into a json
def mem_to_json(instrs, mem):
output_dict = {}
output_dict["iram"] = parse_instrs(instrs)

output_dict["res"] = mem_to_array(mem)
output_json = json.dumps(output_dict)
return output_json

def run_fud(insn_size, data_size, dump_vcd):
subprocess.run([
"fud",
"e",
f"top_{insn_size}_{data_size}.futil",
"--to",
"vcd" if dump_vcd else "dat",
"--through",
"icarus-verilog",
"-s",
"verilog.data",
"top.json"
], stdout=open("top.out",'w'), stderr=open("top.err", 'w')
)

def generate_input_json(instrs, data_size):
int_lst = parse_instrs(instrs)
output_dict= {}
output_dict["iram"] = {}
output_dict["iram"]["data"] = int_lst

# set format
output_dict["iram"]["format"] = {}
output_dict["iram"]["format"]["numeric_type"] = "bitnum"
output_dict["iram"]["format"]["is_signed"] = False
output_dict["iram"]["format"]["width"] = 32

output_dict["res"] = {}
output_dict["res"]["data"] = data_size * [99999]
output_dict["res"]["format"] = {}
output_dict["res"]["format"]["numeric_type"] = "bitnum"
output_dict["res"]["format"]["is_signed"] = False
output_dict["res"]["format"]["width"] = 32

output_json = json.dumps(output_dict)

with open("top.json", 'w') as f:
f.write(output_json)

def generate_top(insn_size, data_size):
subprocess.run([
"cp",
"top.futil",
f"top_{insn_size}_{data_size}.futil"
])
os.system(f"sed -i '' 's/INSN_SIZE/{insn_size}/g;s/DATA_SIZE/{data_size}/g' top_{insn_size}_{data_size}.futil")

def main():
parser = argparse.ArgumentParser(description="Parse arguments for generating tests")
parser.add_argument("--vcd", action="store_true")
args = parser.parse_args()

# test is a string
for test in tests.tests1:
mem = {}
rf = {}
for i in range(0, 32):
x_str = 'x' + str(i)
rf[x_str] = 0

# instrs is a list of strings
instrs = init(test)
insn_size = len(instrs)
data_size = 64
exp_mem = run_instr_seq(instrs, mem, rf)
print(f"exp_mem: {exp_mem}")

# the expected memory output
exp_mem_json = mem_to_json(instrs, exp_mem)

generate_input_json(instrs, data_size)

generate_top(insn_size, data_size)

# run fud
run_fud(insn_size, data_size, args.vcd)

processed_fud_out = {}
with open("top.out") as f:
fud_out = json.load(f)
processed_fud_out = fud_out["memories"]
processed_fud_out = str(processed_fud_out).replace("\'", "\"")

if exp_mem_json != processed_fud_out and not args.vcd:
print(f"expected {exp_mem_json} but got {processed_fud_out}\n")
elif exp_mem_json == processed_fud_out:
print(f"got {exp_mem_json}")

if __name__ == "__main__":
main()
Loading
Loading