Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/main' into mingzhe-structRef
Browse files Browse the repository at this point in the history
  • Loading branch information
mingzheTerapines committed Jul 5, 2024
2 parents aac2043 + 24d07b7 commit 27d2c2f
Show file tree
Hide file tree
Showing 7 changed files with 138 additions and 3 deletions.
3 changes: 3 additions & 0 deletions frontends/PyCDE/src/pycde/constructs.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ def NamedWire(type_or_value: Union[Type, Signal], name: str):

class NamedWire(type._get_value_class()):

if not type.is_hw_type:
raise TypeError(f"NamedWire must have a hardware type, not {type}")

def __init__(self):
self.assigned_value = None
# TODO: We assume here that names are unique within a module, which isn't
Expand Down
48 changes: 48 additions & 0 deletions frontends/PyCDE/src/pycde/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ def strip(self):
def bitwidth(self):
return hw.get_bitwidth(self._type)

@property
def is_hw_type(self) -> bool:
assert False, "Subclass must override this method"

def __call__(self, obj, name: str = None) -> "Signal":
"""Create a Value of this type from a python object."""
assert not isinstance(
Expand Down Expand Up @@ -175,6 +179,10 @@ def __new__(cls, element_type: Type):
def element_type(self) -> Type:
return _FromCirctType(self._type.element_type)

@property
def is_hw_type(self) -> bool:
return True

def _get_value_class(self):
from .signals import InOutSignal
return InOutSignal
Expand Down Expand Up @@ -205,6 +213,10 @@ def __new__(cls, inner_type: Type, name: str):

return super(TypeAlias, cls).__new__(cls, alias, incl_cls_in_key=False)

@property
def is_hw_type(self) -> bool:
return self.inner_type.is_hw_type

@staticmethod
def declare_aliases(mod):
if TypeAlias.RegisteredAliases is None:
Expand Down Expand Up @@ -291,6 +303,10 @@ def inner_type(self):
def element_type(self):
return _FromCirctType(self._type.element_type)

@property
def is_hw_type(self) -> bool:
return True

@property
def size(self):
return self._type.size
Expand Down Expand Up @@ -345,6 +361,10 @@ def __new__(
return super(StructType, cls).__new__(
cls, hw.StructType.get([(n, t._type) for (n, t) in fields]))

@property
def is_hw_type(self) -> bool:
return True

@property
def fields(self):
return [(n, _FromCirctType(t)) for n, t in self._type.get_fields()]
Expand Down Expand Up @@ -408,13 +428,21 @@ def __call__(self, **kwargs):
def _get_value_class(self):
return self._value_class

@property
def is_hw_type(self) -> bool:
return True


class BitVectorType(Type):

@property
def width(self):
return self._type.width

@property
def is_hw_type(self) -> bool:
return True

def _from_obj_check(self, x):
"""This functionality can be shared by all the int types."""
if not isinstance(x, int):
Expand Down Expand Up @@ -498,6 +526,10 @@ class ClockType(Type):
def __new__(cls):
return super(ClockType, cls).__new__(cls, seq.ClockType.get())

@property
def is_hw_type(self) -> bool:
return False

def _get_value_class(self):
from .signals import ClockSignal
return ClockSignal
Expand All @@ -511,6 +543,10 @@ class Any(Type):
def __new__(cls):
return super(Any, cls).__new__(cls, esi.AnyType.get())

@property
def is_hw_type(self) -> bool:
return False


class Channel(Type):
"""An ESI channel type."""
Expand All @@ -531,6 +567,10 @@ def __new__(cls,
def inner_type(self):
return _FromCirctType(self._type.inner)

@property
def is_hw_type(self) -> bool:
return False

@property
def signaling(self):
return self._type.signaling
Expand Down Expand Up @@ -604,6 +644,10 @@ def _get_value_class(self):
from .signals import BundleSignal
return BundleSignal

@property
def is_hw_type(self) -> bool:
return False

@property
def channels(self):
return [
Expand Down Expand Up @@ -720,6 +764,10 @@ def __new__(cls, element_type: Type):
def element_type(self):
return _FromCirctType(self._type.element_type)

@property
def is_hw_type(self) -> bool:
return False

@property
def _get_value_class(self):
from .signals import ListSignal
Expand Down
15 changes: 14 additions & 1 deletion frontends/PyCDE/test/test_constructs_errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@

from pycde import generator, types, Module
from pycde.common import Clock, Input
from pycde.constructs import Reg, Wire
from pycde.constructs import NamedWire, Reg, Wire
from pycde.testing import unittestmodule
from pycde.types import Channel, UInt


@unittestmodule()
Expand Down Expand Up @@ -61,3 +62,15 @@ def create(ports):
r.assign(ports.In)
# CHECK: ValueError: Cannot assign value to Reg twice.
r.assign(ports.In)


# -----


@unittestmodule()
class NamedWireHWError(Module):

@generator
def create(ports):
# CHECK: TypeError: NamedWire must have a hardware type, not Channel<UInt<32>, ValidReady>
NamedWire(Channel(UInt(32)), "asdf")
16 changes: 15 additions & 1 deletion include/circt/Dialect/Moore/MooreOps.td
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ def VariableOp : MooreOp<"variable", [
`` custom<ImplicitSSAName>($name) ($initial^)? attr-dict
`:` type($result)
}];
let hasCanonicalizeMethod = true;
}

def NetKindAttr : I32EnumAttr<"NetKind", "Net type kind", [
Expand Down Expand Up @@ -250,11 +251,24 @@ def NetOp : MooreOp<"net", [
);
let results = (outs Res<RefType, "", [MemAlloc]>:$result);
let assemblyFormat = [{
``custom<ImplicitSSAName>($name) $kind ($assignment^)? attr-dict
`` custom<ImplicitSSAName>($name) $kind ($assignment^)? attr-dict
`:` type($result)
}];
}

def AssignedVarOp : MooreOp<"assigned_variable", [
DeclareOpInterfaceMethods<OpAsmOpInterface, ["getAsmResultNames"]>,
TypesMatchWith<"initial value and variable types match",
"result", "initial", "cast<RefType>($_self).getNestedType()">
]> {
let summary = "The copy of variable must have the initial value";
let arguments = (ins StrAttr:$name, UnpackedType:$initial);
let results = (outs Res<RefType, "", [MemAlloc]>:$result);
let assemblyFormat = [{
`` custom<ImplicitSSAName>($name) $initial attr-dict `:` type($result)
}];
}

def ReadOp : MooreOp<"read", [
DeclareOpInterfaceMethods<PromotableMemOpInterface>,
TypesMatchWith<"input and result types match",
Expand Down
30 changes: 29 additions & 1 deletion lib/Dialect/Moore/MooreOps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,27 @@ VariableOp::handlePromotionComplete(const MemorySlot &slot, Value defaultValue,
this->erase();
return std::nullopt;
}
LogicalResult VariableOp::canonicalize(VariableOp op,
::mlir::PatternRewriter &rewriter) {
Value initial;
for (auto *user : op->getUsers())
if (isa<ContinuousAssignOp>(user) &&
(user->getOperand(0) == op.getResult())) {
// Don't canonicalize the multiple continuous assignment to the same
// variable.
if (initial)
return failure();
initial = user->getOperand(1);
}

if (initial) {
rewriter.replaceOpWithNewOp<AssignedVarOp>(op, op.getType(), op.getName(),
initial);
return success();
}

return failure();
}

SmallVector<DestructurableMemorySlot> VariableOp::getDestructurableSlots() {
if (isa<SVModuleOp>(getOperation()->getParentOp()))
Expand Down Expand Up @@ -324,7 +345,6 @@ VariableOp::handleDestructuringComplete(const DestructurableMemorySlot &slot,
this->erase();
return std::nullopt;
}

//===----------------------------------------------------------------------===//
// NetOp
//===----------------------------------------------------------------------===//
Expand All @@ -333,6 +353,14 @@ void NetOp::getAsmResultNames(OpAsmSetValueNameFn setNameFn) {
setNameFn(getResult(), getName());
}

//===----------------------------------------------------------------------===//
// AssignedVarOp
//===----------------------------------------------------------------------===//

void AssignedVarOp::getAsmResultNames(OpAsmSetValueNameFn setNameFn) {
setNameFn(getResult(), getName());
}

//===----------------------------------------------------------------------===//
// ConstantOp
//===----------------------------------------------------------------------===//
Expand Down
28 changes: 28 additions & 0 deletions test/Dialect/Moore/canonicalizers.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,31 @@ func.func @Casts(%arg0: !moore.i1) -> (!moore.i1, !moore.i1) {
// CHECK: return %arg0, %arg0
return %0, %1 : !moore.i1, !moore.i1
}

// CHECK-LABEL: moore.module @SingleAssign
moore.module @SingleAssign() {
// CHECK-NOT: moore.variable
// CHECK: %a = moore.assigned_variable %0 : <i32>
%a = moore.variable : <i32>
// CHECK: %0 = moore.constant 32 : i32
%0 = moore.constant 32 : i32
// CHECK: moore.assign %a, %0 : i32
moore.assign %a, %0 : i32
moore.output
}

// CHECK-LABEL: moore.module @MultiAssign
moore.module @MultiAssign() {
// CHECK-NOT: moore.assigned_variable
// CHECK: %a = moore.variable : <i32>
%a = moore.variable : <i32>
// CHECK: %0 = moore.constant 32 : i32
%0 = moore.constant 32 : i32
// CHECK: moore.assign %a, %0 : i32
moore.assign %a, %0 : i32
// CHECK: %1 = moore.constant 64 : i32
%1 = moore.constant 64 : i32
// CHECK: moore.assign %a, %1 : i32
moore.assign %a, %1 : i32
moore.output
}
1 change: 1 addition & 0 deletions tools/circt-verilog/circt-verilog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ static LogicalResult populateMooreTransforms(mlir::PassManager &pm) {

pm.addPass(mlir::createSROA());
pm.addPass(mlir::createMem2Reg());

// TODO: like dedup pass.

return success();
Expand Down

0 comments on commit 27d2c2f

Please sign in to comment.