Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move numeric_types.py from fud/verilator to calyx-py (another attempt at #1715 ) #1719

Merged
merged 8 commits into from
Feb 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ jobs:
- name: Run Python Tests
working-directory: /home/calyx
run: pytest fud/fud/stages/verilator/tests/numeric_types.py
run: pytest calyx-py/test/numeric_types.py

evaluation:
name: Polybench Integration
Expand Down
30 changes: 10 additions & 20 deletions calyx-py/calyx/gen_exp.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@
)
from calyx.utils import float_to_fixed_point
from math import factorial, log2
from fud.stages.verilator import numeric_types
from calyx.numeric_types import FixedPoint
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is a great outcome here that the calyx-py library doesn't need to depend on fud for this. That direction of dependency was always extremely weird.

from calyx.gen_ln import generate_ln

from calyx.builder import (
Builder,
ComponentBuilder,
Expand All @@ -19,7 +18,6 @@
if_with,
invoke,
CellBuilder,
ExprBuilder,
const,
HI,
par,
Expand Down Expand Up @@ -52,7 +50,7 @@ def generate_fp_pow_component(

# groups
with comp.group("init") as init:
pow.in_ = numeric_types.FixedPoint(
pow.in_ = FixedPoint(
"1.0", width, int_width, is_signed=is_signed
).unsigned_integer()
pow.write_en = 1
Expand Down Expand Up @@ -105,14 +103,12 @@ def generate_cells(
comp.const(
"one",
width,
numeric_types.FixedPoint(
"1.0", width, int_width, is_signed=is_signed
).unsigned_integer(),
FixedPoint("1.0", width, int_width, is_signed=is_signed).unsigned_integer(),
)
comp.const(
"e",
width,
numeric_types.FixedPoint(
FixedPoint(
str(float_to_fixed_point(2.7182818284, frac_width)),
width,
int_width,
Expand All @@ -124,7 +120,7 @@ def generate_cells(
comp.const(
"negative_one",
width,
numeric_types.FixedPoint(
FixedPoint(
"-1.0", width, int_width, is_signed=is_signed
).unsigned_integer(),
)
Expand Down Expand Up @@ -168,7 +164,7 @@ def generate_cells(
# reciprocal factorials
for i in range(2, degree + 1):
fixed_point_value = float_to_fixed_point(1.0 / factorial(i), frac_width)
value = numeric_types.FixedPoint(
value = FixedPoint(
str(fixed_point_value), width, int_width, is_signed=is_signed
).unsigned_integer()
comp.const(f"reciprocal_factorial{i}", width, value)
Expand Down Expand Up @@ -540,9 +536,7 @@ def gen_constant_cell(
return comp.const(
name,
width,
numeric_types.FixedPoint(
value, width, int_width, is_signed=is_signed
).unsigned_integer(),
FixedPoint(value, width, int_width, is_signed=is_signed).unsigned_integer(),
)


Expand Down Expand Up @@ -571,16 +565,12 @@ def generate_fp_pow_full(
const_one = comp.const(
"one",
width,
numeric_types.FixedPoint(
"1.0", width, int_width, is_signed=is_signed
).unsigned_integer(),
FixedPoint("1.0", width, int_width, is_signed=is_signed).unsigned_integer(),
)
const_zero = comp.const(
"zero",
width,
numeric_types.FixedPoint(
"0.0", width, int_width, is_signed=is_signed
).unsigned_integer(),
FixedPoint("0.0", width, int_width, is_signed=is_signed).unsigned_integer(),
)
mult = comp.cell(
"mult",
Expand All @@ -597,7 +587,7 @@ def generate_fp_pow_full(
const_neg_one = comp.const(
"neg_one",
width,
numeric_types.FixedPoint(
FixedPoint(
"-1.0", width, int_width, is_signed=is_signed
).unsigned_integer(),
)
Expand Down
2 changes: 1 addition & 1 deletion calyx-py/calyx/gen_ln.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
Import,
)
from calyx.utils import float_to_fixed_point
from fud.stages.verilator import numeric_types
from calyx import numeric_types
from calyx.gen_msb import gen_msb_calc

from calyx.builder import Builder, ComponentBuilder, CellBuilder, HI, par, invoke
Expand Down
15 changes: 0 additions & 15 deletions calyx-py/calyx/gen_msb.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,11 @@
from typing import List
from calyx.py_ast import (
Connect,
CompVar,
Cell,
Group,
ConstantPort,
CompPort,
Stdlib,
Component,
ThisPort,
HolePort,
PortDef,
SeqComp,
Enable,
While,
Control,
CombGroup,
)
from calyx.builder import (
Builder,
CellAndGroup,
ComponentBuilder,
const,
HI,
while_with,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,20 @@
from fractions import Fraction
from dataclasses import dataclass
from decimal import Decimal, getcontext
from fud.errors import InvalidNumericType
import math
import logging as log


class InvalidNumericType(Exception):
"""
An error raised when an invalid numeric type is provided.
"""

def __init__(self, msg):
msg = f"""Invalid Numeric Type: {msg}"""
super().__init__(msg)


@dataclass
class NumericType:
"""Interface for a numeric type.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from random import randint
from fud.stages.verilator.numeric_types import FixedPoint, Bitnum
from fud.errors import InvalidNumericType
from calyx.numeric_types import FixedPoint, Bitnum, InvalidNumericType
from hypothesis import given, strategies as st # type: ignore
import numpy as np
import pytest # type: ignore
Expand Down
2 changes: 1 addition & 1 deletion frontends/relay/relay_visitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
Component,
)
from calyx.utils import float_to_fixed_point
from fud.stages.verilator import numeric_types
from calyx import numeric_types
from dahlia_impl import emit_components

calyx_keywords_list = ["input"]
Expand Down
2 changes: 1 addition & 1 deletion frontends/systolic-lang/convert-mems.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import argparse
import json
from fud.stages.verilator import numeric_types
from calyx import numeric_types


if __name__ == "__main__":
Expand Down
2 changes: 1 addition & 1 deletion frontends/systolic-lang/gen_array_component.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env python3

from gen_pe import pe, PE_NAME, BITWIDTH
import calyx.builder as cb
from calyx import builder as cb
from calyx import py_ast
from calyx.utils import bits_needed
from systolic_arg_parser import SystolicConfiguration
Expand Down
4 changes: 2 additions & 2 deletions frontends/systolic-lang/gen_post_op.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
#!/usr/bin/env python3

import calyx.builder as cb
from calyx import builder as cb
from calyx import py_ast
from gen_array_component import NAME_SCHEME
from gen_pe import BITWIDTH, INTWIDTH, FRACWIDTH
from fud.stages.verilator import numeric_types
from calyx import numeric_types
from calyx.utils import float_to_fixed_point
from systolic_arg_parser import SystolicConfiguration
from calyx.utils import bits_needed
Expand Down
10 changes: 0 additions & 10 deletions fud/fud/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,16 +255,6 @@ def __init__(self, path):
super().__init__(msg)


class InvalidNumericType(FudError):
"""
An error raised when an invalid numeric type is provided.
"""

def __init__(self, msg):
msg = f"""Invalid Numeric Type: {msg}"""
super().__init__(msg)


class Malformed(FudError):
"""
An error raised when the input to a stage is malformed in some manner.
Expand Down
20 changes: 9 additions & 11 deletions fud/fud/stages/interpreter.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
from pathlib import Path
import simplejson as sjson
import numpy as np
from fud.stages.verilator.numeric_types import FixedPoint, Bitnum
from fud.errors import InvalidNumericType
from calyx.numeric_types import FixedPoint, Bitnum, InvalidNumericType
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It could be described as slightly weird, although not overwhelmingly weird, that fud depends on calyx-py now. Like, if you think of the calyx-py library as being for generating code, it's not clear why fud would need that. But actually, calyx-py currently is sort of sprawling and covers lots of things, including all our individual code generators (it is not just a code generation library). Therefore this doesn't seem like much messier than it was before, so I think it's fine!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, I think we should eventually externalize all these stages from the core logic in fud so that these false dependencies can be eliminated. The fud API is rich enough that we don't actually need to have these stages sitting in the definition of fud itself anymore.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the idea to have all stages be external then? Or rather to get rid of the notion of non-external stages?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I'd say barring any API problems, there should be no internal stages whatsoever.

from fud.stages.verilator.json_to_dat import parse_fp_widths, float_to_fixed
from fud.utils import shell, TmpDir, unwrap_or, transparent_shell
from fud import config as cfg
Expand Down Expand Up @@ -88,8 +87,9 @@ def _is_data_converter(self):

def _define_steps(self, input_data, builder, config):
script = config["stages", self.name, "exec"]
data_path_exists: bool = (config["stages", "verilog", "data"] or
config.get(["stages", "mrxl", "data"]))
data_path_exists: bool = config["stages", "verilog", "data"] or config.get(
["stages", "mrxl", "data"]
)

cmd = [
script,
Expand Down Expand Up @@ -118,7 +118,9 @@ def mktmp() -> SourceType.Directory:
"""
return TmpDir()

@builder.step(description="Dynamically retrieve the value of stages.verilog.data")
@builder.step(
description="Dynamically retrieve the value of stages.verilog.data"
)
def get_verilog_data() -> SourceType.Path:
data_path = config.get(["stages", "verilog", "data"])
path = Path(data_path) if data_path else None
Expand Down Expand Up @@ -197,9 +199,7 @@ def parse_output(
data_path = get_verilog_data()

if data_path_exists:
convert_json_to_interp_json(
tmpdir, data_path
)
convert_json_to_interp_json(tmpdir, data_path)

if self._is_data_converter():
if data_path_exists:
Expand All @@ -213,9 +213,7 @@ def parse_output(
result = interpret(input_data, tmpdir)

if "--raw" in cmd:
return parse_output(
result, data_path, tmpdir
)
return parse_output(result, data_path, tmpdir)
else:
return result

Expand Down
4 changes: 2 additions & 2 deletions fud/fud/stages/verilator/json_to_dat.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import simplejson as sjson
import numpy as np
from .numeric_types import FixedPoint, Bitnum
from calyx.numeric_types import FixedPoint, Bitnum, InvalidNumericType
from pathlib import Path
from fud.errors import InvalidNumericType, Malformed
from fud.errors import Malformed
import logging as log


Expand Down
2 changes: 1 addition & 1 deletion fud/fud/stages/verilator/tables.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from itertools import product
from decimal import Decimal
from fud.stages.verilator.numeric_types import FixedPoint
from calyx.numeric_types import FixedPoint


def compute_exp_frac_table(frac_width: int):
Expand Down
25 changes: 14 additions & 11 deletions fud/fud/xclrun.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
from typing import Mapping, Any, Dict
from pathlib import Path
from fud.stages.verilator.json_to_dat import parse_fp_widths, float_to_fixed
from fud.errors import InvalidNumericType
from calyx.numeric_types import InvalidNumericType


def mem_to_buf(mem):
Expand Down Expand Up @@ -96,8 +96,9 @@ def run(xclbin: Path, data: Mapping[str, Any]) -> Dict[str, Any]:
# Collect the output data.
for buf in buffers:
buf.sync_from_device()
mems = {name: buf_to_mem(data[name]["format"], buf)
for name, buf in zip(data, buffers)}
mems = {
name: buf_to_mem(data[name]["format"], buf) for name, buf in zip(data, buffers)
}

# PYNQ recommends explicitly freeing its resources.
del buffers
Expand All @@ -118,14 +119,16 @@ def _dtype(fmt) -> np.dtype:
def xclrun():
# Parse command-line arguments.
parser = argparse.ArgumentParser(
description='run a compiled XRT program',
description="run a compiled XRT program",
)
parser.add_argument("bin", metavar="XCLBIN", help="the .xclbin binary file to run")
parser.add_argument("data", metavar="DATA", help="the JSON input data file")
parser.add_argument(
"--out",
"-o",
metavar="FILE",
help="write JSON results to a file instead of stdout",
)
parser.add_argument('bin', metavar='XCLBIN',
help='the .xclbin binary file to run')
parser.add_argument('data', metavar='DATA',
help='the JSON input data file')
parser.add_argument('--out', '-o', metavar='FILE',
help='write JSON results to a file instead of stdout')
args = parser.parse_args()

# Load the input JSON data file.
Expand All @@ -136,7 +139,7 @@ def xclrun():
out_data = run(Path(args.bin), in_data)

# Dump the output JSON data.
outfile = open(args.out, 'w') if args.out else sys.stdout
outfile = open(args.out, "w") if args.out else sys.stdout
sjson.dump(out_data, outfile, indent=2, use_decimal=True)


Expand Down
Loading