Skip to content

Commit

Permalink
reticulating htq codegen
Browse files Browse the repository at this point in the history
  • Loading branch information
rcgoodfellow committed Sep 12, 2024
1 parent 0153a66 commit e497bca
Show file tree
Hide file tree
Showing 6 changed files with 195 additions and 63 deletions.
8 changes: 8 additions & 0 deletions codegen/htq/src/expression.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// Copyright 2024 Oxide Computer Company
use crate::error::CodegenError;

pub(crate) fn _emit_expression(
_stmt: &p4::ast::Expression,
) -> Result<Vec<htq::ast::Statement>, CodegenError> {
todo!()
}
41 changes: 41 additions & 0 deletions codegen/htq/src/header.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright 2024 Oxide Computer Company

use crate::{error::CodegenError, p4_type_to_htq_type};

pub(crate) fn p4_header_to_htq_header(
p4h: &p4::ast::Header,
) -> Result<htq::ast::Header, CodegenError> {
Ok(htq::ast::Header {
name: p4h.name.clone(),
fields: p4h
.members
.iter()
.map(p4_header_member_to_htq_type)
.collect::<Result<Vec<htq::ast::Type>, CodegenError>>()?,
})
}

pub(crate) fn p4_struct_to_htq_header(
p4s: &p4::ast::Struct,
) -> Result<htq::ast::Header, CodegenError> {
Ok(htq::ast::Header {
name: p4s.name.clone(),
fields: p4s
.members
.iter()
.map(p4_struct_member_to_htq_type)
.collect::<Result<Vec<htq::ast::Type>, CodegenError>>()?,
})
}

pub(crate) fn p4_header_member_to_htq_type(
p4f: &p4::ast::HeaderMember,
) -> Result<htq::ast::Type, CodegenError> {
p4_type_to_htq_type(&p4f.ty)
}

pub(crate) fn p4_struct_member_to_htq_type(
p4f: &p4::ast::StructMember,
) -> Result<htq::ast::Type, CodegenError> {
p4_type_to_htq_type(&p4f.ty)
}
89 changes: 26 additions & 63 deletions codegen/htq/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,61 +3,67 @@
use std::io::Write;

use error::CodegenError;
use header::{p4_header_to_htq_header, p4_struct_to_htq_header};
use htq::emit::Emit;
use p4::hlir::Hlir;
use parser::emit_parser_functions;
use table::p4_table_to_htq_table;

use crate::error::EmitError;

mod error;
mod expression;
mod header;
mod parser;
mod statement;
mod table;

pub fn emit(
ast: &p4::ast::AST,
hlir: &Hlir,
filename: &str,
) -> Result<(), EmitError> {
let headers: Vec<_> =
let mut headers: Vec<_> =
ast.headers
.iter()
.map(p4_header_to_htq_header)
.collect::<Result<Vec<htq::ast::Header>, CodegenError>>()?;

headers.extend(
ast.structs
.iter()
.map(p4_struct_to_htq_header)
.collect::<Result<Vec<htq::ast::Header>, CodegenError>>()?,
);

let tables: Vec<_> = ast
.controls
.iter()
.flat_map(|c| c.tables.iter().map(|t| (c, t)).collect::<Vec<_>>())
.map(|(c, t)| p4_table_to_htq_table(c, t, hlir))
.collect::<Result<Vec<htq::ast::Table>, CodegenError>>()?;

let parser_functions: Vec<_> = emit_parser_functions(ast, hlir)?;

let mut f = std::fs::File::create(filename)?;

for h in &headers {
writeln!(f, "{}", h.emit())?;
}
writeln!(f)?;

for t in &tables {
writeln!(f, "{}", t.emit())?;
}
writeln!(f)?;

Ok(())
}

fn p4_header_to_htq_header(
p4h: &p4::ast::Header,
) -> Result<htq::ast::Header, CodegenError> {
Ok(htq::ast::Header {
name: p4h.name.clone(),
fields: p4h
.members
.iter()
.map(p4_header_member_to_htq_type)
.collect::<Result<Vec<htq::ast::Type>, CodegenError>>()?,
})
}
for func in &parser_functions {
//TODO htq function emit
writeln!(f, "{}", func.emit())?;
}
writeln!(f)?;

fn p4_header_member_to_htq_type(
p4f: &p4::ast::HeaderMember,
) -> Result<htq::ast::Type, CodegenError> {
p4_type_to_htq_type(&p4f.ty)
Ok(())
}

fn p4_type_to_htq_type(
Expand Down Expand Up @@ -101,46 +107,3 @@ fn p4_type_to_htq_type(
p4::ast::Type::String => todo!("string types not yet supported"),
})
}

fn p4_match_kind_to_htq_match_kind(
p4m: &p4::ast::MatchKind,
) -> htq::ast::LookupType {
match p4m {
p4::ast::MatchKind::Exact => htq::ast::LookupType::Exact,
p4::ast::MatchKind::LongestPrefixMatch => htq::ast::LookupType::Lpm,
p4::ast::MatchKind::Range => htq::ast::LookupType::Range,
p4::ast::MatchKind::Ternary => htq::ast::LookupType::Ternary,
}
}

fn p4_table_to_htq_table(
p4c: &p4::ast::Control,
p4t: &p4::ast::Table,
hlir: &Hlir,
) -> Result<htq::ast::Table, CodegenError> {
let mut action_args = Vec::new();
for a in &p4t.actions {
let act = p4c.get_action(&a.name).unwrap();
action_args.push(
act.parameters
.iter()
.map(|x| p4_type_to_htq_type(&x.ty))
.collect::<Result<Vec<htq::ast::Type>, CodegenError>>()?,
);
}
Ok(htq::ast::Table {
name: p4t.name.clone(),
keyset: p4t
.key
.iter()
.map(|(lval, match_kind)| htq::ast::TableKey {
typ: p4_type_to_htq_type(
&hlir.lvalue_decls.get(lval).unwrap().ty,
)
.unwrap(),
lookup_typ: p4_match_kind_to_htq_match_kind(match_kind),
})
.collect(),
action_args,
})
}
53 changes: 53 additions & 0 deletions codegen/htq/src/parser.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Copyright 2024 Oxide Computer Company

use crate::{
error::CodegenError, p4_type_to_htq_type, statement::emit_statement,
};
use p4::hlir::Hlir;

pub(crate) fn emit_parser_functions(
ast: &p4::ast::AST,
hlir: &Hlir,
) -> Result<Vec<htq::ast::Function>, CodegenError> {
let mut result = Vec::new();

for parser in &ast.parsers {
let pf = emit_parser(ast, hlir, parser)?;
result.extend(pf.into_iter());
}

Ok(result)
}

pub(crate) fn emit_parser(
_ast: &p4::ast::AST,
_hlir: &Hlir,
parser: &p4::ast::Parser,
) -> Result<Vec<htq::ast::Function>, CodegenError> {
let mut result = Vec::new();
let mut parameters = Vec::new();

for x in &parser.parameters {
let p = htq::ast::Parameter {
reg: htq::ast::Register::new(x.name.as_str()),
pointer: true,
typ: p4_type_to_htq_type(&x.ty)?,
};
parameters.push(p);
}

for state in &parser.states {
let mut statements = Vec::new();
for s in &state.statements.statements {
statements.extend(emit_statement(s)?.into_iter());
}
let f = htq::ast::Function {
name: format!("{}_{}", parser.name, state.name),
parameters: parameters.clone(),
statements,
};
result.push(f);
}

Ok(result)
}
19 changes: 19 additions & 0 deletions codegen/htq/src/statement.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright 2024 Oxide Computer Company

use crate::error::CodegenError;

pub(crate) fn emit_statement(
stmt: &p4::ast::Statement,
) -> Result<Vec<htq::ast::Statement>, CodegenError> {
use p4::ast::Statement as S;
match stmt {
S::Empty => Ok(Vec::new()),
S::Assignment(_lval, _expr) => todo!(),
S::Call(_call) => todo!(),
S::If(_if_block) => todo!(),
S::Variable(_v) => todo!(),
S::Constant(_c) => todo!(),
S::Transition(_t) => todo!(),
S::Return(_r) => todo!(),
}
}
48 changes: 48 additions & 0 deletions codegen/htq/src/table.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Copyright 2024 Oxide Computer Company

use p4::hlir::Hlir;

use crate::{error::CodegenError, p4_type_to_htq_type};

pub fn p4_match_kind_to_htq_match_kind(
p4m: &p4::ast::MatchKind,
) -> htq::ast::LookupType {
match p4m {
p4::ast::MatchKind::Exact => htq::ast::LookupType::Exact,
p4::ast::MatchKind::LongestPrefixMatch => htq::ast::LookupType::Lpm,
p4::ast::MatchKind::Range => htq::ast::LookupType::Range,
p4::ast::MatchKind::Ternary => htq::ast::LookupType::Ternary,
}
}

pub(crate) fn p4_table_to_htq_table(
p4c: &p4::ast::Control,
p4t: &p4::ast::Table,
hlir: &Hlir,
) -> Result<htq::ast::Table, CodegenError> {
let mut action_args = Vec::new();
for a in &p4t.actions {
let act = p4c.get_action(&a.name).unwrap();
action_args.push(
act.parameters
.iter()
.map(|x| p4_type_to_htq_type(&x.ty))
.collect::<Result<Vec<htq::ast::Type>, CodegenError>>()?,
);
}
Ok(htq::ast::Table {
name: p4t.name.clone(),
keyset: p4t
.key
.iter()
.map(|(lval, match_kind)| htq::ast::TableKey {
typ: p4_type_to_htq_type(
&hlir.lvalue_decls.get(lval).unwrap().ty,
)
.unwrap(),
lookup_typ: p4_match_kind_to_htq_match_kind(match_kind),
})
.collect(),
action_args,
})
}

0 comments on commit e497bca

Please sign in to comment.