-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This patch adds the frep extension to the snitch emulator. Register staggering is not supported currently, but could be added at a later date. This patch also adds f64 support to the xssr extension.
- Loading branch information
1 parent
5a939ee
commit f50b3a9
Showing
10 changed files
with
296 additions
and
103 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
from typing import List, Type, Union, Set, Literal | ||
|
||
from riscemu.colors import FMT_CPU, FMT_NONE | ||
from riscemu.config import RunConfig | ||
from riscemu.core import UserModeCPU | ||
from riscemu.instructions import InstructionSet, Instruction, RV32F, RV32D | ||
|
||
from dataclasses import dataclass | ||
|
||
from snitch.regs import StreamingRegs | ||
|
||
|
||
@dataclass(frozen=True) | ||
class FrepState: | ||
rep_count: int | ||
ins_count: int | ||
mode: Literal["inner", "outer"] | ||
|
||
|
||
class FrepEnabledCpu(UserModeCPU): | ||
repeat: Union[FrepState, None] | ||
allowed_ins: Set[str] | ||
|
||
def __init__(self, instruction_sets: List[Type["InstructionSet"]], conf: RunConfig): | ||
super().__init__(instruction_sets, conf) | ||
self.regs = StreamingRegs( | ||
mem=self.mmu, infinite_regs=conf.unlimited_registers, flen=conf.flen | ||
) | ||
self.repeats = None | ||
# only floating point instructions are allowed inside an frep! | ||
self.allowed_ins = set(x for x, y in RV32F(self).get_instructions()) | ||
if conf.flen > 32: | ||
self.allowed_ins.union(x for x, y in RV32D(self).get_instructions()) | ||
|
||
def step(self, verbose: bool = False): | ||
if self.repeats is None: | ||
super().step(verbose=verbose) | ||
return | ||
# get the spec | ||
spec: FrepState = self.repeats | ||
self.repeats = None | ||
|
||
instructions = [ | ||
self.mmu.read_ins(self.pc + i * self.INS_XLEN) | ||
for i in range(spec.ins_count) | ||
] | ||
|
||
for ins in instructions: | ||
if ins.name not in self.allowed_ins: | ||
# TODO: wrap in a nicer error type | ||
raise RuntimeError( | ||
"Forbidden instruction inside frep loop: {}".format(ins) | ||
) | ||
|
||
if verbose: | ||
print( | ||
FMT_CPU | ||
+ "┌────── floating point repetition ({}) {} times".format( | ||
spec.mode, spec.rep_count + 1 | ||
) | ||
) | ||
for i, ins in enumerate(instructions): | ||
print( | ||
FMT_CPU | ||
+ "│ 0x{:08X}:{} {}".format( | ||
self.pc + i * self.INS_XLEN, FMT_NONE, ins | ||
) | ||
) | ||
print(FMT_CPU + "└────── end of floating point repetition" + FMT_NONE) | ||
|
||
pc = self.pc | ||
if spec.mode == "outer": | ||
for _ in range(spec.rep_count + 1): | ||
for ins in instructions: | ||
self.run_instruction(ins) | ||
elif spec.mode == "inner": | ||
for ins in instructions: | ||
for _ in range(spec.rep_count + 1): | ||
self.run_instruction(ins) | ||
else: | ||
raise RuntimeError(f"Unknown frep mode: {spec.mode}") | ||
self.cycle += (spec.rep_count + 1) * spec.ins_count | ||
self.pc = pc + (spec.ins_count * self.INS_XLEN) | ||
|
||
|
||
class Xfrep(InstructionSet): | ||
def instruction_frep_o(self, ins: Instruction): | ||
self.frep(ins, "outer") | ||
|
||
def instruction_frep_i(self, ins: Instruction): | ||
self.frep(ins, "inner") | ||
|
||
def frep(self, ins: Instruction, mode: Literal["inner", "outer"]): | ||
assert isinstance(self.cpu, FrepEnabledCpu) | ||
assert len(ins.args) == 4 | ||
assert ins.get_imm(2).abs_value.value == 0, "staggering not supported yet" | ||
assert ins.get_imm(3).abs_value.value == 0, "staggering not supported yet" | ||
|
||
self.cpu.repeats = FrepState( | ||
rep_count=self.regs.get(ins.get_reg(0)).unsigned_value, | ||
ins_count=ins.get_imm(1).abs_value.value, | ||
mode=mode, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
// RUN: python3 -m snitch %s -o libc -v | filecheck %s | ||
|
||
.text | ||
.globl main | ||
main: | ||
// load constants | ||
li t0, 0 | ||
fcvt.s.w ft0, t0 | ||
li t0, 1 | ||
fcvt.s.w ft1, t0 | ||
|
||
// repeat 100 times | ||
li t0, 99 | ||
frep.i t0, 1, 0, 0 | ||
fadd.s ft0, ft0, ft1 // add one | ||
|
||
// print result to stdout | ||
printf "100 * 1 = {:f32}", ft0 | ||
// CHECK: 100 * 1 = 100.0 | ||
// return 0 | ||
li a0, 0 | ||
ret | ||
|
||
// CHECK-NEXT: [CPU] Program exited with code 0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
// RUN: python3 -m snitch %s -o libc -v --flen 32 | filecheck %s | ||
|
||
.data | ||
|
||
vec0: | ||
.word 0x0, 0x3f800000, 0x40000000, 0x40400000, 0x40800000, 0x40a00000, 0x40c00000, 0x40e00000, 0x41000000, 0x41100000 | ||
vec1: | ||
.word 0x0, 0x3f800000, 0x40000000, 0x40400000, 0x40800000, 0x40a00000, 0x40c00000, 0x40e00000, 0x41000000, 0x41100000 | ||
dest: | ||
.space 40 | ||
expected: | ||
.word 0x0, 0x3e800000, 0x3f800000, 0x40100000, 0x40800000, 0x40c80000, 0x41100000, 0x41440000, 0x41800000, 0x41a20000 | ||
|
||
.text | ||
.globl main | ||
|
||
main: | ||
// ssr config | ||
ssr.configure 0, 10, 4 | ||
ssr.configure 1, 10, 4 | ||
ssr.configure 2, 10, 4 | ||
|
||
// ft0 streams from vec0 | ||
la a0, vec0 | ||
ssr.read a0, 0, 0 | ||
|
||
// ft1 streams from vec1 | ||
la a0, vec1 | ||
ssr.read a0, 1, 0 | ||
|
||
// ft2 streams to dest | ||
la a0, dest | ||
ssr.write a0, 2, 0 | ||
|
||
li a0, 9 | ||
// some constant to divide by | ||
li t0, 4 | ||
fcvt.s.w ft3, t0 | ||
ssr.enable | ||
|
||
frep.o a0, 2, 0, 0 | ||
fmul.s ft4, ft0, ft1 // ft3 = vec0[i] * vec1[i] | ||
fdiv.s ft2, ft4, ft3 // dest[i] = ft3 / 4 | ||
|
||
// stop ssr | ||
ssr.disable | ||
|
||
// check values were written correctly: | ||
la t0, dest | ||
la t1, expected | ||
li a0, 36 | ||
loop: | ||
add s0, t0, a0 | ||
add s1, t1, a0 | ||
|
||
// load vec0, vec1 and dest elements | ||
flw ft0, 0(s0) | ||
flw ft1, 0(s1) | ||
|
||
// assert ft0 == ft1 (expected[i] == dest[i]) | ||
feq.s s0, ft0, ft1 | ||
beq zero, s0, fail | ||
|
||
addi a0, a0, -4 | ||
bge a0, zero loop | ||
|
||
li a0, 0 | ||
ret | ||
|
||
fail: | ||
printf "Assertion failure: {} != {} (at {})", ft0, ft1, a0 | ||
li a0, -1 | ||
ret | ||
|
||
// CHECK: [CPU] Program exited with code 0 |
Oops, something went wrong.