Skip to main content

powdr_riscv_types/
lib.rs

1use powdr_isa_utils::SingleDataValue;
2use std::fmt;
3
4#[derive(Clone, Copy, PartialEq, Eq, Debug)]
5pub struct Register {
6    value: u8,
7}
8
9impl Register {
10    pub fn new(value: u8) -> Self {
11        Self { value }
12    }
13
14    pub fn is_zero(&self) -> bool {
15        self.value == 0
16    }
17
18    pub fn addr(&self) -> u8 {
19        self.value
20    }
21}
22
23/// List of machine registers, declared in the asm machine.
24/// NOTE: the bootloader expects the PC to be the last register in this list.
25pub const REGISTER_NAMES: [&str; 3] = ["main::query_arg_1", "main::query_arg_2", "main::pc"];
26
27/// These are the names of the RISCV registers that are stored in memory.
28pub const REGISTER_MEMORY_NAMES: [&str; 37] = [
29    "x0",
30    "x1",
31    "x2",
32    "x3",
33    "x4",
34    "x5",
35    "x6",
36    "x7",
37    "x8",
38    "x9",
39    "x10",
40    "x11",
41    "x12",
42    "x13",
43    "x14",
44    "x15",
45    "x16",
46    "x17",
47    "x18",
48    "x19",
49    "x20",
50    "x21",
51    "x22",
52    "x23",
53    "x24",
54    "x25",
55    "x26",
56    "x27",
57    "x28",
58    "x29",
59    "x30",
60    "x31",
61    "tmp1",
62    "tmp2",
63    "tmp3",
64    "tmp4",
65    "lr_sc_reservation",
66];
67
68impl fmt::Display for Register {
69    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
70        write!(f, "{}", REGISTER_MEMORY_NAMES[self.value as usize])
71    }
72}
73
74impl From<&str> for Register {
75    fn from(s: &str) -> Self {
76        REGISTER_MEMORY_NAMES
77            .iter()
78            .position(|&name| name == s)
79            .map(|value| Self::new(value as u8))
80            .unwrap_or_else(|| panic!("Invalid register"))
81    }
82}
83
84pub enum Statement<'a, L: AsRef<str>, A: InstructionArgs> {
85    DebugLoc { file: u64, line: u64, col: u64 },
86    Label(L),
87    Instruction { op: &'a str, args: A },
88}
89
90pub struct MemEntry {
91    pub label: Option<String>,
92    pub addr: u32,
93    pub value: SingleDataValue,
94}
95
96pub struct SourceFileInfo<'a> {
97    pub id: u32,
98    pub dir: &'a str,
99    pub file: &'a str,
100}
101
102/// A RISC-V program that can be translated to POWDR ASM.
103pub trait RiscVProgram {
104    /// Takes the listing of source files, to be used in the debug statements.
105    fn take_source_files_info(&mut self) -> impl Iterator<Item = SourceFileInfo<'_>>;
106
107    /// Takes the initial memory snapshot.
108    fn take_initial_mem(&mut self) -> impl Iterator<Item = MemEntry>;
109
110    /// Takes the executable statements and labels.
111    fn take_executable_statements(
112        &mut self,
113    ) -> impl Iterator<Item = Statement<'_, impl AsRef<str>, impl InstructionArgs>>;
114
115    /// Returns the addresses of the start and end of prover data.
116    fn prover_data_bounds(&self) -> (u32, u32);
117
118    /// The name of the function that should be called to start the program.
119    fn start_function(&self) -> impl AsRef<str>;
120}
121
122pub trait InstructionArgs {
123    type Error: fmt::Display;
124
125    fn l(&self) -> Result<impl AsRef<str>, Self::Error>;
126    fn r(&self) -> Result<Register, Self::Error>;
127    fn rri(&self) -> Result<(Register, Register, u32), Self::Error>;
128    /// Returns the usual rd, rs1, rs2
129    fn rrr(&self) -> Result<(Register, Register, Register), Self::Error>;
130    /// Special case used in amo* instructions, returning rd, rs2, rs1
131    fn rrr2(&self) -> Result<(Register, Register, Register), Self::Error>;
132    fn ri(&self) -> Result<(Register, u32), Self::Error>;
133    fn rr(&self) -> Result<(Register, Register), Self::Error>;
134    fn rrl(&self) -> Result<(Register, Register, impl AsRef<str>), Self::Error>;
135    fn rl(&self) -> Result<(Register, impl AsRef<str>), Self::Error>;
136    fn rro(&self) -> Result<(Register, Register, u32), Self::Error>;
137    fn empty(&self) -> Result<(), Self::Error>;
138}